diff --git a/.gitignore b/.gitignore index 5163e4e4..35d51be5 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,7 @@ test.zip* __pycache__ node_modules/ .cache/ +.zig* +CACHEDIR.TARGET +.package-cache +.cargo/registry diff --git a/crates/libmwemu/src/api/abi.rs b/crates/libmwemu/src/api/abi.rs new file mode 100644 index 00000000..5bb8a414 --- /dev/null +++ b/crates/libmwemu/src/api/abi.rs @@ -0,0 +1,65 @@ +use crate::emu::Emu; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ApiAbi { + Aarch64, + X86_64, +} + +impl ApiAbi { + #[inline] + pub fn from_emu(emu: &Emu) -> Self { + if emu.cfg.arch.is_x64() { + Self::X86_64 + } else { + Self::Aarch64 + } + } + + #[inline] + pub fn arg(self, emu: &Emu, idx: usize) -> u64 { + match self { + Self::Aarch64 => { + let regs = emu.regs_aarch64(); + regs.x.get(idx).copied().unwrap_or_else(|| { + panic!("AArch64 API arg{} is out of range", idx); + }) + } + Self::X86_64 => match idx { + 0 => { + let regs = emu.regs(); + regs.rdi + } + 1 => { + let regs = emu.regs(); + regs.rsi + } + 2 => { + let regs = emu.regs(); + regs.rdx + } + 3 => { + let regs = emu.regs(); + regs.rcx + } + 4 => { + let regs = emu.regs(); + regs.r8 + } + 5 => { + let regs = emu.regs(); + regs.r9 + } + _ => panic!("x86_64 API arg{} is out of range", idx), + }, + } + } + + #[inline] + pub fn set_ret(self, emu: &mut Emu, value: u64) { + match self { + Self::Aarch64 => emu.regs_aarch64_mut().x[0] = value, + Self::X86_64 => emu.regs_mut().rax = value, + } + } +} diff --git a/crates/libmwemu/src/api/linux/libc.rs b/crates/libmwemu/src/api/linux/libc.rs index 971e3e5b..6e87f77f 100644 --- a/crates/libmwemu/src/api/linux/libc.rs +++ b/crates/libmwemu/src/api/linux/libc.rs @@ -1,7 +1,15 @@ +#[path = "../abi.rs"] +mod abi; + use crate::emu::Emu; +use abi::ApiAbi; pub fn gateway(symbol: &str, emu: &mut Emu) { match symbol { + "__libc_start_main" => api_libc_start_main(emu), + "__cxa_finalize" => api_cxa_finalize(emu), + "__cxa_atexit" => api_cxa_atexit(emu), + "__gmon_start__" => api_gmon_start(emu), "printf" => api_printf(emu), "fprintf" => api_fprintf(emu), "puts" => api_puts(emu), @@ -29,51 +37,110 @@ pub fn gateway(symbol: &str, emu: &mut Emu) { } } +fn api_libc_start_main(emu: &mut Emu) { + let abi = ApiAbi::from_emu(emu); + let main_fn = abi.arg(emu, 0); + let argc = abi.arg(emu, 1); + let argv = abi.arg(emu, 2); + let envp = argv.wrapping_add((argc + 1) * 8); + + log::info!( + "{}** {} Linux API __libc_start_main(main=0x{:x}, argc={}, argv=0x{:x}) {}", + emu.colors.light_red, + emu.pos, + main_fn, + argc, + argv, + emu.colors.nc + ); + + if !emu.cfg.arch.is_x64() { + log::warn!( + "linuxapi libc: __libc_start_main bridge is only implemented for x86_64 right now" + ); + abi.set_ret(emu, 0); + return; + } + + match emu.linux_call64(main_fn, &[argc, argv, envp]) { + Ok(status) => { + // Model glibc startup minimally: after main returns, terminate the + // emulated process through the existing exit path. + emu.regs_mut().rdi = status; + api_exit(emu); + } + Err(err) => { + log::warn!("linuxapi libc: __libc_start_main failed to run main: {}", err); + emu.stop(); + } + } +} + fn api_printf(emu: &mut Emu) { - let fmt_addr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let fmt_addr = abi.arg(emu, 0); let fmt = emu.maps.read_string(fmt_addr); log::info!( "{}** {} Linux API printf(\"{}\") {}", - emu.colors.light_red, emu.pos, fmt, emu.colors.nc + emu.colors.light_red, + emu.pos, + fmt, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = fmt.len() as u64; + abi.set_ret(emu, fmt.len() as u64); } fn api_fprintf(emu: &mut Emu) { - let _stream = emu.regs_aarch64().x[0]; - let fmt_addr = emu.regs_aarch64().x[1]; + let abi = ApiAbi::from_emu(emu); + let _stream = abi.arg(emu, 0); + let fmt_addr = abi.arg(emu, 1); let fmt = emu.maps.read_string(fmt_addr); log::info!( "{}** {} Linux API fprintf(\"{}\") {}", - emu.colors.light_red, emu.pos, fmt, emu.colors.nc + emu.colors.light_red, + emu.pos, + fmt, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = fmt.len() as u64; + abi.set_ret(emu, fmt.len() as u64); } fn api_puts(emu: &mut Emu) { - let s_addr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let s_addr = abi.arg(emu, 0); let s = emu.maps.read_string(s_addr); log::info!( "{}** {} Linux API puts(\"{}\") {}", - emu.colors.light_red, emu.pos, s, emu.colors.nc + emu.colors.light_red, + emu.pos, + s, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = 0; + abi.set_ret(emu, 0); } fn api_putchar(emu: &mut Emu) { - let c = emu.regs_aarch64().x[0] as u8 as char; + let abi = ApiAbi::from_emu(emu); + let c = abi.arg(emu, 0) as u8 as char; log::info!( "{}** {} Linux API putchar('{}') {}", - emu.colors.light_red, emu.pos, c, emu.colors.nc + emu.colors.light_red, + emu.pos, + c, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = c as u64; + abi.set_ret(emu, c as u64); } fn api_exit(emu: &mut Emu) { - let status = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let status = abi.arg(emu, 0); log::info!( "{}** {} Linux API exit({}) {}", - emu.colors.light_red, emu.pos, status, emu.colors.nc + emu.colors.light_red, + emu.pos, + status, + emu.colors.nc ); emu.stop(); } @@ -81,63 +148,141 @@ fn api_exit(emu: &mut Emu) { fn api_abort(emu: &mut Emu) { log::info!( "{}** {} Linux API abort() {}", - emu.colors.light_red, emu.pos, emu.colors.nc + emu.colors.light_red, + emu.pos, + emu.colors.nc ); emu.stop(); } +fn api_cxa_finalize(emu: &mut Emu) { + let abi = ApiAbi::from_emu(emu); + let dso_handle = abi.arg(emu, 0); + log::info!( + "{}** {} Linux API __cxa_finalize(0x{:x}) {}", + emu.colors.light_red, + emu.pos, + dso_handle, + emu.colors.nc + ); + abi.set_ret(emu, 0); +} + +fn api_cxa_atexit(emu: &mut Emu) { + let abi = ApiAbi::from_emu(emu); + let func = abi.arg(emu, 0); + let arg = abi.arg(emu, 1); + let dso_handle = abi.arg(emu, 2); + log::info!( + "{}** {} Linux API __cxa_atexit(func=0x{:x}, arg=0x{:x}, dso=0x{:x}) {}", + emu.colors.light_red, + emu.pos, + func, + arg, + dso_handle, + emu.colors.nc + ); + abi.set_ret(emu, 0); +} + +fn api_gmon_start(emu: &mut Emu) { + log::info!( + "{}** {} Linux API __gmon_start__() {}", + emu.colors.light_red, + emu.pos, + emu.colors.nc + ); + let abi = ApiAbi::from_emu(emu); + abi.set_ret(emu, 0); +} + fn api_malloc(emu: &mut Emu) { - let size = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let size = abi.arg(emu, 0); log::info!( "{}** {} Linux API malloc({}) {}", - emu.colors.light_red, emu.pos, size, emu.colors.nc + emu.colors.light_red, + emu.pos, + size, + emu.colors.nc ); todo!("malloc({})", size); } -fn api_calloc(emu: &mut Emu) { todo!("calloc"); } -fn api_realloc(emu: &mut Emu) { todo!("realloc"); } +fn api_calloc(emu: &mut Emu) { + todo!("calloc"); +} +fn api_realloc(emu: &mut Emu) { + todo!("realloc"); +} fn api_free(emu: &mut Emu) { - let ptr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let ptr = abi.arg(emu, 0); log::info!( "{}** {} Linux API free(0x{:x}) {}", - emu.colors.light_red, emu.pos, ptr, emu.colors.nc + emu.colors.light_red, + emu.pos, + ptr, + emu.colors.nc ); // no-op for now } fn api_write(emu: &mut Emu) { - let fd = emu.regs_aarch64().x[0]; - let buf = emu.regs_aarch64().x[1]; - let count = emu.regs_aarch64().x[2]; + let abi = ApiAbi::from_emu(emu); + let fd = abi.arg(emu, 0); + let buf = abi.arg(emu, 1); + let count = abi.arg(emu, 2); let s = emu.maps.read_string(buf); log::info!( "{}** {} Linux API write(fd={}, \"{}\", {}) {}", - emu.colors.light_red, emu.pos, fd, s, count, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + s, + count, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = count; + abi.set_ret(emu, count); } -fn api_read(emu: &mut Emu) { todo!("read"); } -fn api_open(emu: &mut Emu) { todo!("open"); } +fn api_read(emu: &mut Emu) { + todo!("read"); +} +fn api_open(emu: &mut Emu) { + todo!("open"); +} fn api_close(emu: &mut Emu) { - let fd = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let fd = abi.arg(emu, 0); log::info!( "{}** {} Linux API close(fd={}) {}", - emu.colors.light_red, emu.pos, fd, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = 0; + abi.set_ret(emu, 0); } fn api_strlen(emu: &mut Emu) { - let s_addr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let s_addr = abi.arg(emu, 0); let s = emu.maps.read_string(s_addr); - emu.regs_aarch64_mut().x[0] = s.len() as u64; + abi.set_ret(emu, s.len() as u64); } -fn api_memcpy(emu: &mut Emu) { todo!("memcpy"); } -fn api_memset(emu: &mut Emu) { todo!("memset"); } -fn api_mmap(emu: &mut Emu) { todo!("mmap"); } -fn api_munmap(emu: &mut Emu) { todo!("munmap"); } +fn api_memcpy(emu: &mut Emu) { + todo!("memcpy"); +} +fn api_memset(emu: &mut Emu) { + todo!("memset"); +} +fn api_mmap(emu: &mut Emu) { + todo!("mmap"); +} +fn api_munmap(emu: &mut Emu) { + todo!("munmap"); +} diff --git a/crates/libmwemu/src/api/macos/libsystem.rs b/crates/libmwemu/src/api/macos/libsystem.rs index ba3350ae..9d80f0d8 100644 --- a/crates/libmwemu/src/api/macos/libsystem.rs +++ b/crates/libmwemu/src/api/macos/libsystem.rs @@ -1,4 +1,8 @@ +#[path = "../abi.rs"] +mod abi; + use crate::emu::Emu; +use abi::ApiAbi; pub fn gateway(symbol: &str, emu: &mut Emu) { match symbol { @@ -43,24 +47,32 @@ pub fn gateway(symbol: &str, emu: &mut Emu) { } fn api_printf(emu: &mut Emu) { - let fmt_addr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let fmt_addr = abi.arg(emu, 0); let fmt = emu.maps.read_string(fmt_addr); log::info!( "{}** {} macOS API printf(\"{}\") {}", - emu.colors.light_red, emu.pos, fmt, emu.colors.nc + emu.colors.light_red, + emu.pos, + fmt, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = fmt.len() as u64; + abi.set_ret(emu, fmt.len() as u64); } fn api_fprintf(emu: &mut Emu) { - let _stream = emu.regs_aarch64().x[0]; - let fmt_addr = emu.regs_aarch64().x[1]; + let abi = ApiAbi::from_emu(emu); + let _stream = abi.arg(emu, 0); + let fmt_addr = abi.arg(emu, 1); let fmt = emu.maps.read_string(fmt_addr); log::info!( "{}** {} macOS API fprintf(\"{}\") {}", - emu.colors.light_red, emu.pos, fmt, emu.colors.nc + emu.colors.light_red, + emu.pos, + fmt, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = fmt.len() as u64; + abi.set_ret(emu, fmt.len() as u64); } fn api_sprintf(emu: &mut Emu) { @@ -72,29 +84,41 @@ fn api_snprintf(emu: &mut Emu) { } fn api_puts(emu: &mut Emu) { - let s_addr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let s_addr = abi.arg(emu, 0); let s = emu.maps.read_string(s_addr); log::info!( "{}** {} macOS API puts(\"{}\") {}", - emu.colors.light_red, emu.pos, s, emu.colors.nc + emu.colors.light_red, + emu.pos, + s, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = 0; + abi.set_ret(emu, 0); } fn api_putchar(emu: &mut Emu) { - let c = emu.regs_aarch64().x[0] as u8 as char; + let abi = ApiAbi::from_emu(emu); + let c = abi.arg(emu, 0) as u8 as char; log::info!( "{}** {} macOS API putchar('{}') {}", - emu.colors.light_red, emu.pos, c, emu.colors.nc + emu.colors.light_red, + emu.pos, + c, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = c as u64; + abi.set_ret(emu, c as u64); } fn api_exit(emu: &mut Emu) { - let status = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let status = abi.arg(emu, 0); log::info!( "{}** {} macOS API exit({}) {}", - emu.colors.light_red, emu.pos, status, emu.colors.nc + emu.colors.light_red, + emu.pos, + status, + emu.colors.nc ); emu.stop(); } @@ -102,28 +126,42 @@ fn api_exit(emu: &mut Emu) { fn api_abort(emu: &mut Emu) { log::info!( "{}** {} macOS API abort() {}", - emu.colors.light_red, emu.pos, emu.colors.nc + emu.colors.light_red, + emu.pos, + emu.colors.nc ); emu.stop(); } fn api_malloc(emu: &mut Emu) { - let size = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let size = abi.arg(emu, 0); log::info!( "{}** {} macOS API malloc({}) {}", - emu.colors.light_red, emu.pos, size, emu.colors.nc + emu.colors.light_red, + emu.pos, + size, + emu.colors.nc ); todo!("malloc({})", size); } -fn api_calloc(emu: &mut Emu) { todo!("calloc"); } -fn api_realloc(emu: &mut Emu) { todo!("realloc"); } +fn api_calloc(emu: &mut Emu) { + todo!("calloc"); +} +fn api_realloc(emu: &mut Emu) { + todo!("realloc"); +} fn api_free(emu: &mut Emu) { - let _ptr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let _ptr = abi.arg(emu, 0); log::info!( "{}** {} macOS API free(0x{:x}) {}", - emu.colors.light_red, emu.pos, _ptr, emu.colors.nc + emu.colors.light_red, + emu.pos, + _ptr, + emu.colors.nc ); // no-op for now } @@ -131,54 +169,102 @@ fn api_free(emu: &mut Emu) { fn api_atexit(emu: &mut Emu) { log::info!( "{}** {} macOS API atexit() {}", - emu.colors.light_red, emu.pos, emu.colors.nc + emu.colors.light_red, + emu.pos, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = 0; + let abi = ApiAbi::from_emu(emu); + abi.set_ret(emu, 0); } fn api_write(emu: &mut Emu) { - let fd = emu.regs_aarch64().x[0]; - let buf = emu.regs_aarch64().x[1]; - let count = emu.regs_aarch64().x[2]; + let abi = ApiAbi::from_emu(emu); + let fd = abi.arg(emu, 0); + let buf = abi.arg(emu, 1); + let count = abi.arg(emu, 2); let s = emu.maps.read_string(buf); log::info!( "{}** {} macOS API write(fd={}, \"{}\", {}) {}", - emu.colors.light_red, emu.pos, fd, s, count, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + s, + count, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = count; + abi.set_ret(emu, count); } -fn api_read(emu: &mut Emu) { todo!("read"); } -fn api_open(emu: &mut Emu) { todo!("open"); } +fn api_read(emu: &mut Emu) { + todo!("read"); +} +fn api_open(emu: &mut Emu) { + todo!("open"); +} fn api_close(emu: &mut Emu) { - let fd = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let fd = abi.arg(emu, 0); log::info!( "{}** {} macOS API close(fd={}) {}", - emu.colors.light_red, emu.pos, fd, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + emu.colors.nc ); - emu.regs_aarch64_mut().x[0] = 0; + abi.set_ret(emu, 0); } -fn api_memcpy(emu: &mut Emu) { todo!("memcpy"); } -fn api_memmove(emu: &mut Emu) { todo!("memmove"); } -fn api_memset(emu: &mut Emu) { todo!("memset"); } -fn api_memcmp(emu: &mut Emu) { todo!("memcmp"); } +fn api_memcpy(emu: &mut Emu) { + todo!("memcpy"); +} +fn api_memmove(emu: &mut Emu) { + todo!("memmove"); +} +fn api_memset(emu: &mut Emu) { + todo!("memset"); +} +fn api_memcmp(emu: &mut Emu) { + todo!("memcmp"); +} fn api_strlen(emu: &mut Emu) { - let s_addr = emu.regs_aarch64().x[0]; + let abi = ApiAbi::from_emu(emu); + let s_addr = abi.arg(emu, 0); let s = emu.maps.read_string(s_addr); - emu.regs_aarch64_mut().x[0] = s.len() as u64; -} - -fn api_strcmp(emu: &mut Emu) { todo!("strcmp"); } -fn api_strncmp(emu: &mut Emu) { todo!("strncmp"); } -fn api_strcpy(emu: &mut Emu) { todo!("strcpy"); } -fn api_strncpy(emu: &mut Emu) { todo!("strncpy"); } -fn api_strcat(emu: &mut Emu) { todo!("strcat"); } -fn api_strchr(emu: &mut Emu) { todo!("strchr"); } -fn api_strrchr(emu: &mut Emu) { todo!("strrchr"); } -fn api_strstr(emu: &mut Emu) { todo!("strstr"); } -fn api_strdup(emu: &mut Emu) { todo!("strdup"); } -fn api_mmap(emu: &mut Emu) { todo!("mmap"); } -fn api_munmap(emu: &mut Emu) { todo!("munmap"); } + abi.set_ret(emu, s.len() as u64); +} + +fn api_strcmp(emu: &mut Emu) { + todo!("strcmp"); +} +fn api_strncmp(emu: &mut Emu) { + todo!("strncmp"); +} +fn api_strcpy(emu: &mut Emu) { + todo!("strcpy"); +} +fn api_strncpy(emu: &mut Emu) { + todo!("strncpy"); +} +fn api_strcat(emu: &mut Emu) { + todo!("strcat"); +} +fn api_strchr(emu: &mut Emu) { + todo!("strchr"); +} +fn api_strrchr(emu: &mut Emu) { + todo!("strrchr"); +} +fn api_strstr(emu: &mut Emu) { + todo!("strstr"); +} +fn api_strdup(emu: &mut Emu) { + todo!("strdup"); +} +fn api_mmap(emu: &mut Emu) { + todo!("mmap"); +} +fn api_munmap(emu: &mut Emu) { + todo!("munmap"); +} diff --git a/crates/libmwemu/src/emu/initialization.rs b/crates/libmwemu/src/emu/initialization.rs index 2636793f..5eaca0dc 100644 --- a/crates/libmwemu/src/emu/initialization.rs +++ b/crates/libmwemu/src/emu/initialization.rs @@ -402,6 +402,39 @@ impl Emu { self.init_stack_aarch64(); } + /// Initialize macOS x86_64 simulation for Mach-O loading. + pub fn init_macos64(&mut self) { + self.os = crate::arch::OperatingSystem::MacOS; + self.maps.is_64bits = true; + + // Mach-O front-door loading can switch the emulator from an earlier + // AArch64 session, so restore the x86 thread/register state explicitly. + if matches!( + self.threads[self.current_thread_id].arch, + crate::threading::context::ArchThreadState::AArch64 { .. } + ) { + let id = self.threads[self.current_thread_id].id; + self.threads[self.current_thread_id] = + crate::threading::context::ThreadContext::new(id, self.cfg.arch); + } + + if matches!(self.arch_state, super::ArchState::AArch64 { .. }) { + let mut formatter = IntelFormatter::new(); + formatter.options_mut().set_digit_separator(""); + formatter.options_mut().set_first_operand_char_index(6); + self.arch_state = super::ArchState::X86 { + instruction: None, + formatter, + instruction_cache: InstructionCache::new(), + decoder_position: 0, + }; + } + + self.flags_mut().clear(); + self.flags_mut().f_if = true; + self.init_stack64(); + } + /// Initialize linux x86_64 simulation, it's called from load_code() if the sample is an ELF. pub fn init_linux64(&mut self, dyn_link: bool) { //self.regs_mut().clear::<64>(); diff --git a/crates/libmwemu/src/emu/instruction_pointer.rs b/crates/libmwemu/src/emu/instruction_pointer.rs index 771a2fdf..f89560be 100644 --- a/crates/libmwemu/src/emu/instruction_pointer.rs +++ b/crates/libmwemu/src/emu/instruction_pointer.rs @@ -1,9 +1,62 @@ use crate::{ - console::Console, windows::constants, emu::Emu, exception::types::ExceptionType, - winapi::winapi32, winapi::winapi64, + console::Console, emu::Emu, exception::types::ExceptionType, winapi::winapi32, + winapi::winapi64, windows::constants, }; impl Emu { + fn resolve_unix_x64_symbol(&self, addr: u64) -> String { + let symbol = if self.os.is_macos() { + self.macho64 + .as_ref() + .and_then(|m| m.addr_to_symbol.get(&addr).cloned()) + } else if self.os.is_linux() { + self.elf64 + .as_ref() + .and_then(|elf| elf.addr_to_symbol.get(&addr).cloned()) + .or_else(|| { + self.elf64 + .as_ref() + .map(|elf| elf.sym_get_name_from_addr(addr)) + .filter(|name| !name.is_empty()) + }) + } else { + None + }; + + symbol.unwrap_or_else(|| format!("unknown_0x{:x}", addr)) + } + + fn intercept_unix_x64_api_call(&mut self, addr: u64, section_name: &str) -> bool { + if self.skip_apicall { + self.its_apicall = Some(addr); + return false; + } + + let symbol = self.resolve_unix_x64_symbol(addr); + + log::info!( + "{}** {} API call: {} (in {}) at 0x{:x} {}", + self.colors.light_red, + self.pos, + symbol, + section_name, + addr, + self.colors.nc + ); + + self.gateway_return = self.stack_pop64(false).unwrap_or(0); + self.regs_mut().rip = self.gateway_return; + + if self.os.is_macos() { + crate::macosapi::gateway(addr, section_name, &symbol, self); + } else if self.os.is_linux() { + crate::linuxapi::gateway(addr, section_name, &symbol, self); + } + + self.force_break = true; + true + } + ///TODO: reimplement set_eip and set_rip /// Redirect execution flow on 64bits. /// If the target address is a winapi, triggers it's implementation. @@ -24,7 +77,11 @@ impl Emu { if self.os.is_linux() { return false; } - let import = self.pe64.as_ref().unwrap().import_addr_to_dll_and_name(addr); + let import = self + .pe64 + .as_ref() + .unwrap() + .import_addr_to_dll_and_name(addr); if !import.is_empty() { let (dll, api) = import.split_once('!').unwrap_or(("", "")); @@ -76,8 +133,9 @@ impl Emu { } self.regs_mut().rip = addr; - } else if self.os.is_linux() { - self.regs_mut().rip = addr; // in linux libs are no implemented are emulated + } else if self.os.is_linux() || self.os.is_macos() { + let section_name = name.to_string(); + return self.intercept_unix_x64_api_call(addr, §ion_name); } else { if self.cfg.verbose >= 1 && !self.cfg.emulate_winapi { log::trace!("/!\\ changing RIP to {} ", name); @@ -87,7 +145,9 @@ impl Emu { if self.cfg.emulate_winapi { let api_name = winapi64::kernel32::guess_api_name(self, addr); if !api_name.is_empty() { - if self.cfg.verbose >= 1 { log_red!(self, "emulating {}", api_name); } + if self.cfg.verbose >= 1 { + log_red!(self, "emulating {}", api_name); + } } self.regs_mut().rip = addr; return true; @@ -199,7 +259,9 @@ impl Emu { // winapi emulation case if self.cfg.emulate_winapi { let api_name = winapi32::kernel32::guess_api_name(self, addr as u32); - if self.cfg.verbose >= 1 { log_red!(self, "emulating {}", api_name); } + if self.cfg.verbose >= 1 { + log_red!(self, "emulating {}", api_name); + } self.regs_mut().set_eip(addr); return true; } @@ -244,7 +306,9 @@ impl Emu { if self.cfg.emulate_winapi { let api_name = winapi32::kernel32::guess_api_name(self, addr as u32); if !api_name.is_empty() { - if self.cfg.verbose >= 1 { log_red!(self, "emulating {}", api_name); } + if self.cfg.verbose >= 1 { + log_red!(self, "emulating {}", api_name); + } } self.regs_mut().set_eip(addr); return true; diff --git a/crates/libmwemu/src/emu/loaders.rs b/crates/libmwemu/src/emu/loaders.rs index 419e8f94..f1fc1c42 100644 --- a/crates/libmwemu/src/emu/loaders.rs +++ b/crates/libmwemu/src/emu/loaders.rs @@ -71,6 +71,24 @@ impl Emu { log::trace!("macho64 aarch64 detected."); self.load_macho64(filename); + // Mach-O x86_64 + } else if Macho64::is_macho64_x64(filename) && !self.cfg.shellcode { + self.cfg.arch = Arch::X86_64; + self.maps.is_64bits = true; + self.maps.clear(); + + // Set maps folder for macOS dylibs (try repo root, then relative from crate) + if self.cfg.maps_folder.is_empty() { + if std::path::Path::new("maps/maps_macos").exists() { + self.cfg.maps_folder = "maps/maps_macos/".to_string(); + } else if std::path::Path::new("../../maps/maps_macos").exists() { + self.cfg.maps_folder = "../../maps/maps_macos/".to_string(); + } + } + + log::trace!("macho64 x86_64 detected."); + self.load_macho64(filename); + // ELF64 x86_64 } else if Elf64::is_elf64_x64(filename) && !self.cfg.shellcode { self.os = crate::arch::OperatingSystem::Linux; diff --git a/crates/libmwemu/src/emu/loaders/elf.rs b/crates/libmwemu/src/emu/loaders/elf.rs index e1eacd14..96d2a689 100644 --- a/crates/libmwemu/src/emu/loaders/elf.rs +++ b/crates/libmwemu/src/emu/loaders/elf.rs @@ -1,6 +1,8 @@ use crate::emu::Emu; use crate::loaders::elf::elf64::Elf64; use crate::windows::constants; +use std::collections::HashMap; +use std::path::Path; impl Emu { /// Loads an ELF64 parsing sections etc, powered by elf64.rs @@ -77,42 +79,56 @@ impl Emu { ); } - /* if dyn_link { - //let mut ld = Elf64::parse("/lib64/ld-linux-x86-64.so.2").unwrap(); - //ld.load(&mut self.maps, "ld-linux", true, dyn_link, constants::CFG_DEFAULT_BASE); - //log::trace!("--- emulating ld-linux _start ---"); - - self.regs_mut().rip = elf64.elf_hdr.e_entry; - - //TODO: emulate the linker - //self.regs_mut().rip = ld.elf_hdr.e_entry + elf64::LD_BASE; - //self.run(None); - } else { - self.regs_mut().rip = elf64.elf_hdr.e_entry; - }*/ - - /* - for lib in elf64.get_dynamic() { - log::trace!("dynamic library {}", lib); - let libspath = "/usr/lib/x86_64-linux-gnu/"; - let libpath = format!("{}{}", libspath, lib); - let mut elflib = Elf64::parse(&libpath).unwrap(); - elflib.load(&mut self.maps, &lib, true); - - if lib.contains("libc") { - elflib.craft_libc_got(&mut self.maps, "elf64"); + let mut export_map: HashMap = HashMap::new(); + + for lib in elf64.get_dynamic() { + log::trace!("dynamic library {}", lib); + + let Some(local_path) = self.resolve_linux_stub_path(&lib) else { + log::warn!("elf64: could not locate linux stub library {}", lib); + continue; + }; + + let mut elflib = match Elf64::parse(&local_path) { + Ok(lib) => lib, + Err(err) => { + log::warn!("elf64: failed to parse {}: {}", local_path, err); + continue; + } + }; + + let map_name = lib.rsplit('/').next().unwrap_or(&lib); + elflib.load(&mut self.maps, map_name, true, true, constants::CFG_DEFAULT_BASE); + + for (sym, addr) in elflib.exported_symbols() { + export_map.entry(sym.clone()).or_insert(addr); + elf64.addr_to_symbol.insert(addr, sym.clone()); + elf64.sym_to_addr.insert(sym, addr); + } } - /* - match elflib.init { - Some(addr) => { - self.call64(addr, &[]); - } - None => {} - }*/ - }*/ + let unresolved = elf64.apply_dynamic_relocations(&mut self.maps, &export_map); + if !unresolved.is_empty() { + log::warn!("elf64: unresolved dynamic imports: {:?}", unresolved); + } + } self.elf64 = Some(elf64); } + + fn resolve_linux_stub_path(&self, lib_name: &str) -> Option { + let mut candidates = Vec::new(); + + if !self.cfg.maps_folder.is_empty() { + candidates.push(self.cfg.get_maps_folder(lib_name)); + } + + candidates.push(format!("maps/maps_linux/{}", lib_name)); + candidates.push(format!("../../maps/maps_linux/{}", lib_name)); + + candidates + .into_iter() + .find(|candidate| Path::new(candidate).exists()) + } } diff --git a/crates/libmwemu/src/emu/loaders/macho.rs b/crates/libmwemu/src/emu/loaders/macho.rs index 1a58e08c..51dc7f06 100644 --- a/crates/libmwemu/src/emu/loaders/macho.rs +++ b/crates/libmwemu/src/emu/loaders/macho.rs @@ -5,11 +5,17 @@ use crate::emu::Emu; use crate::loaders::macho::macho64::Macho64; impl Emu { - /// Load a Mach-O 64-bit AArch64 binary. + /// Load a 64-bit Mach-O binary. pub fn load_macho64(&mut self, filename: &str) { let mut macho = Macho64::parse(filename).expect("cannot parse macho64 binary"); macho.load(&mut self.maps); - self.init_macos_aarch64(); + if self.cfg.arch.is_aarch64() { + self.init_macos_aarch64(); + } else if self.cfg.arch.is_x64() { + self.init_macos64(); + } else { + panic!("unsupported Mach-O architecture: {:?}", self.cfg.arch); + } self.set_pc(macho.entry); log::info!("macho64: entry point set to 0x{:x}", macho.entry); diff --git a/crates/libmwemu/src/engine/instructions/syscall.rs b/crates/libmwemu/src/engine/instructions/syscall.rs index 431c46b1..dfabcf95 100644 --- a/crates/libmwemu/src/engine/instructions/syscall.rs +++ b/crates/libmwemu/src/engine/instructions/syscall.rs @@ -1,11 +1,15 @@ use crate::color; use crate::emu::Emu; use crate::syscall::linux; +use crate::syscall::macos; use crate::syscall::windows; use iced_x86::Instruction; pub fn execute(emu: &mut Emu, ins: &Instruction, instruction_sz: usize, _rep_step: bool) -> bool { - emu.show_instruction(color!("Red"), &crate::emu::decoded_instruction::DecodedInstruction::X86(*ins)); + emu.show_instruction( + color!("Red"), + &crate::emu::decoded_instruction::DecodedInstruction::X86(*ins), + ); if emu.cfg.trace_calls && !emu.os.is_linux() { log::trace!( @@ -18,6 +22,8 @@ pub fn execute(emu: &mut Emu, ins: &Instruction, instruction_sz: usize, _rep_ste if emu.os.is_linux() { linux::syscall64::gateway(emu); + } else if emu.os.is_macos() { + macos::syscall_x86_64::gateway(emu); } else { windows::syscall64::gateway(emu); } diff --git a/crates/libmwemu/src/loaders/elf/elf64.rs b/crates/libmwemu/src/loaders/elf/elf64.rs index 116d7458..f0a859d4 100644 --- a/crates/libmwemu/src/loaders/elf/elf64.rs +++ b/crates/libmwemu/src/loaders/elf/elf64.rs @@ -1,7 +1,8 @@ -use crate::windows::constants; use crate::err::MwemuError; use crate::maps::mem64::{Mem64, Permission}; use crate::maps::Maps; +use crate::windows::constants; +use std::collections::HashMap; use std::fs::File; use std::io::Read; @@ -56,11 +57,20 @@ macro_rules! write_u64_le { pub const EI_NIDENT: usize = 16; pub const ELFCLASS64: u8 = 0x02; pub const DT_NEEDED: u64 = 1; +pub const DT_PLTRELSZ: u64 = 2; pub const DT_NULL: u64 = 0; +pub const DT_SYMTAB: u64 = 6; +pub const DT_RELA: u64 = 7; +pub const DT_RELASZ: u64 = 8; +pub const DT_RELAENT: u64 = 9; pub const DT_STRTAB: u64 = 5; +pub const DT_SYMENT: u64 = 11; +pub const DT_JMPREL: u64 = 23; pub const PT_DYNAMIC: u32 = 2; pub const STT_FUNC: u8 = 2; pub const STT_OBJECT: u8 = 1; +pub const R_X86_64_GLOB_DAT: u32 = 6; +pub const R_X86_64_JUMP_SLOT: u32 = 7; #[derive(Debug)] pub struct Elf64 { @@ -74,6 +84,9 @@ pub struct Elf64 { pub elf_dynsym: Vec, pub elf_dynstr_off: u64, pub elf_got_off: u64, + pub needed_libs: Vec, + pub sym_to_addr: HashMap, + pub addr_to_symbol: HashMap, } impl Elf64 { @@ -116,8 +129,6 @@ impl Elf64 { if off_strtab > 0 { blob_strtab = bin[off_strtab..(off_strtab + sz_strtab)].to_vec(); } - let dynstr: Vec = Vec::new(); - Ok(Elf64 { base: 0, bin, @@ -129,6 +140,9 @@ impl Elf64 { elf_dynsym: dynsym, elf_dynstr_off: 0, elf_got_off: 0, + needed_libs: Vec::new(), + sym_to_addr: HashMap::new(), + addr_to_symbol: HashMap::new(), }) } @@ -161,22 +175,268 @@ impl Elf64 { } pub fn sym_get_addr_from_name(&self, name: &str) -> Option { - for sym in self.elf_dynsym.iter() { - log::trace!("{} == {}", &sym.st_dynstr_name, name); - if sym.st_dynstr_name == name { - return Some(sym.st_value); + self.sym_to_addr.get(name).copied().or_else(|| { + self.elf_dynsym + .iter() + .find(|sym| sym.st_dynstr_name == name && sym.st_value > 0) + .map(|sym| sym.st_value) + }) + } + + pub fn sym_get_name_from_addr(&self, addr: u64) -> String { + self.addr_to_symbol + .get(&addr) + .cloned() + .or_else(|| { + self.elf_dynsym + .iter() + .find(|sym| sym.st_value == addr) + .map(|sym| sym.st_dynstr_name.clone()) + }) + .unwrap_or_default() + } + + pub fn exported_symbols(&self) -> Vec<(String, u64)> { + let mut exports = Vec::new(); + for sym in &self.elf_dynsym { + if !sym.st_dynstr_name.is_empty() && sym.st_value > 0 { + exports.push((sym.st_dynstr_name.clone(), sym.st_value)); + } + } + exports + } + + pub fn rebase_vaddr(&self, vaddr: u64) -> u64 { + if vaddr == 0 { + 0 + } else if vaddr < self.base { + vaddr + self.base + } else { + vaddr + } + } + + fn image_size(&self) -> u64 { + let mut max_end = 0; + for phdr in &self.elf_phdr { + if phdr.p_type == constants::PT_LOAD { + max_end = max_end.max(phdr.p_vaddr + phdr.p_memsz); } } + + if max_end == 0 { + for shdr in &self.elf_shdr { + max_end = max_end.max(shdr.sh_addr + shdr.sh_size); + } + } + + max_end.max(0x4000) + } + + fn read_c_string(&self, offset: usize) -> Option { + if offset >= self.bin.len() { + return None; + } + let end = self.bin[offset..] + .iter() + .position(|&c| c == 0) + .unwrap_or(self.bin.len() - offset); + std::str::from_utf8(&self.bin[offset..offset + end]) + .ok() + .map(|s| s.to_string()) + } + + fn dynamic_table_bounds(&self) -> Option<(usize, usize)> { + for shdr in &self.elf_shdr { + if self.get_section_name(shdr.sh_name as usize) == ".dynamic" { + return Some((shdr.sh_offset as usize, shdr.sh_size as usize)); + } + } + + for phdr in &self.elf_phdr { + if phdr.p_type == PT_DYNAMIC { + return Some((phdr.p_offset as usize, phdr.p_filesz as usize)); + } + } + None } - pub fn sym_get_name_from_addr(&self, addr: u64) -> String { - for sym in self.elf_dynsym.iter() { - if sym.st_value == addr { - return sym.st_dynstr_name.clone(); + fn vaddr_to_file_offset(&self, vaddr: u64) -> Option { + for phdr in &self.elf_phdr { + if phdr.p_type != constants::PT_LOAD { + continue; + } + + let end = phdr.p_vaddr.saturating_add(phdr.p_filesz.max(phdr.p_memsz)); + if vaddr >= phdr.p_vaddr && vaddr < end { + return Some((phdr.p_offset + (vaddr - phdr.p_vaddr)) as usize); } } - String::new() + + for shdr in &self.elf_shdr { + if shdr.sh_addr == 0 || shdr.sh_size == 0 { + continue; + } + let end = shdr.sh_addr.saturating_add(shdr.sh_size); + if vaddr >= shdr.sh_addr && vaddr < end { + return Some((shdr.sh_offset + (vaddr - shdr.sh_addr)) as usize); + } + } + + None + } + + pub fn dynamic_info(&self) -> Option { + let (mut off, size) = self.dynamic_table_bounds()?; + let end = off.saturating_add(size).min(self.bin.len()); + let mut info = Elf64DynamicInfo::default(); + let mut needed_offsets = Vec::new(); + + while off + 16 <= end { + let d_tag = read_u64_le!(self.bin, off); + let d_val = read_u64_le!(self.bin, off + 8); + + if d_tag == DT_NULL { + break; + } + + match d_tag { + DT_NEEDED => needed_offsets.push(d_val), + DT_STRTAB => info.strtab_addr = d_val, + DT_SYMTAB => info.symtab_addr = d_val, + DT_SYMENT => info.syment = d_val, + DT_RELA => info.rela_addr = d_val, + DT_RELASZ => info.rela_size = d_val, + DT_RELAENT => info.rela_ent = d_val, + DT_JMPREL => info.jmprel_addr = d_val, + DT_PLTRELSZ => info.pltrelsz = d_val, + _ => {} + } + + off += 16; + } + + let strtab_off = self + .vaddr_to_file_offset(info.strtab_addr) + .or_else(|| usize::try_from(info.strtab_addr).ok()) + .filter(|off| *off < self.bin.len())?; + + for needed_off in needed_offsets { + let name_off = strtab_off.saturating_add(needed_off as usize); + if let Some(name) = self.read_c_string(name_off) { + info.needed.push(name); + } + } + + Some(info) + } + + pub fn apply_dynamic_relocations( + &self, + maps: &mut Maps, + export_map: &HashMap, + ) -> Vec { + let mut unresolved = Vec::new(); + let Some(info) = self.dynamic_info() else { + return unresolved; + }; + + let rela_ent = if info.rela_ent == 0 { + Elf64Rela::size() + } else { + info.rela_ent as usize + }; + + self.apply_rela_table( + maps, + export_map, + info.rela_addr, + info.rela_size, + rela_ent, + &mut unresolved, + ); + + self.apply_rela_table( + maps, + export_map, + info.jmprel_addr, + info.pltrelsz, + rela_ent, + &mut unresolved, + ); + + unresolved + } + + fn apply_rela_table( + &self, + maps: &mut Maps, + export_map: &HashMap, + rela_addr: u64, + rela_size: u64, + rela_ent: usize, + unresolved: &mut Vec, + ) { + if rela_addr == 0 || rela_size == 0 || rela_ent == 0 { + return; + } + + let Some(mut off) = self.vaddr_to_file_offset(rela_addr) else { + log::warn!("elf64: could not translate rela addr 0x{:x}", rela_addr); + return; + }; + let end = off.saturating_add(rela_size as usize).min(self.bin.len()); + + while off + rela_ent <= end { + let rela = Elf64Rela::parse(&self.bin, off); + let r_type = rela.r_type(); + + if r_type != R_X86_64_GLOB_DAT && r_type != R_X86_64_JUMP_SLOT { + off += rela_ent; + continue; + } + + let sym_idx = rela.r_sym() as usize; + let Some(sym) = self.elf_dynsym.get(sym_idx) else { + off += rela_ent; + continue; + }; + + if sym.st_dynstr_name.is_empty() { + off += rela_ent; + continue; + } + + let resolved = export_map + .get(&sym.st_dynstr_name) + .copied() + .or_else(|| self.sym_get_addr_from_name(&sym.st_dynstr_name)); + + let Some(target_addr) = resolved else { + if !unresolved.contains(&sym.st_dynstr_name) { + unresolved.push(sym.st_dynstr_name.clone()); + } + off += rela_ent; + continue; + }; + + let patch_addr = self.rebase_vaddr(rela.r_offset); + if !maps.write_qword(patch_addr, target_addr) { + if let Some(map_name) = maps.get_addr_name(patch_addr).map(|s| s.to_string()) { + maps.get_mem_mut(&map_name) + .force_write_qword(patch_addr, target_addr); + } else { + log::warn!( + "elf64: relocation target 0x{:x} for {} is not mapped", + patch_addr, + sym.st_dynstr_name + ); + } + } + + off += rela_ent; + } } /* @@ -245,7 +505,12 @@ impl Elf64 { let elf64_base: u64; if dynamic_linking { - elf64_base = constants::ELF64_DYN_BASE; + elf64_base = if is_lib { + maps.lib64_alloc(self.image_size()) + .expect("cannot allocate elf64 library space") + } else { + constants::ELF64_DYN_BASE + }; self.load_programs(maps, name, is_lib, dynamic_linking); } else { if force_base == constants::CFG_DEFAULT_BASE { @@ -262,6 +527,9 @@ impl Elf64 { } self.base = elf64_base; + self.sym_to_addr.clear(); + self.addr_to_symbol.clear(); + self.needed_libs = self.get_dynamic(); // pre-load .dynstr for shdr in &self.elf_shdr { @@ -304,26 +572,35 @@ impl Elf64 { // load dynsym if sname == ".dynsym" { + self.elf_dynsym.clear(); let mut off = sh_offset as usize; + let entsize = if self.elf_shdr[i].sh_entsize == 0 { + Elf64Sym::size() as u64 + } else { + self.elf_shdr[i].sh_entsize + }; - for _ in 0..(sh_size / Elf64Sym::size() as u64) { + for _ in 0..(sh_size / entsize) { let mut sym = Elf64Sym::parse(&self.bin, off); - if (sym.get_st_type() == STT_FUNC || sym.get_st_type() == STT_OBJECT) - && sym.st_value > 0 - { - let off2 = (self.elf_dynstr_off + sym.st_name as u64) as usize; - let end = self.bin[off2..] - .iter() - .position(|&c| c == 0) - .unwrap_or(self.bin.len()); - if let Ok(string) = std::str::from_utf8(&self.bin[off2..(end + off2)]) { - sym.st_dynstr_name = string.to_string(); - } - - self.elf_dynsym.push(sym); + let off2 = (self.elf_dynstr_off + sym.st_name as u64) as usize; + if let Some(name) = self.read_c_string(off2) { + sym.st_dynstr_name = name; } - off += Elf64Sym::size(); + + if sym.st_value > 0 { + sym.st_value = self.rebase_vaddr(sym.st_value); + } + + if !sym.st_dynstr_name.is_empty() && sym.st_value > 0 { + self.sym_to_addr + .insert(sym.st_dynstr_name.clone(), sym.st_value); + self.addr_to_symbol + .insert(sym.st_value, sym.st_dynstr_name.clone()); + } + + self.elf_dynsym.push(sym); + off += entsize as usize; } } @@ -413,69 +690,9 @@ impl Elf64 { } pub fn get_dynamic(&self) -> Vec { - let mut libs: Vec = Vec::new(); - - for shdr in &self.elf_shdr { - if self.get_section_name(shdr.sh_name as usize) == ".dynamic" { - let mut off = shdr.sh_offset as usize; - let mut off_strtab: u64 = 0; - - loop { - let d_tag: u64 = read_u64_le!(self.bin, off); - let d_val: u64 = read_u64_le!(self.bin, off + 8); - - if d_tag == DT_NULL { - break; - } - if d_tag == DT_STRTAB { - if d_val > self.bin.len() as u64 { - off_strtab = d_val - self.elf_phdr[2].p_vaddr; - } else { - off_strtab = d_val; - } - - break; - } - off += 16; - } - - if off_strtab == 0 { - log::trace!("dt_strtab not found"); - return libs; - } - - off = shdr.sh_offset as usize; - loop { - let d_tag: u64 = read_u64_le!(self.bin, off); - let d_val: u64 = read_u64_le!(self.bin, off + 8); - - if d_tag == DT_NULL { - break; - } - if d_tag == DT_NEEDED { - let off_lib = (off_strtab + d_val) as usize; - if off_lib > self.bin.len() { - off += 16; - continue; - } - let off_lib_end = self.bin[off_lib..] - .iter() - .position(|&c| c == 0) - .expect("error searching on DT_STRTAB"); - let lib_name = - std::str::from_utf8(&self.bin[off_lib..off_lib + off_lib_end]) - .expect("libname on DT_STRTAB is not utf-8"); - log::trace!("lib: {}", lib_name); - libs.push(lib_name.to_string()); - } - off += 16; - } - - break; - } - } - - libs + self.dynamic_info() + .map(|info| info.needed) + .unwrap_or_default() } pub fn is_elf64_x64(filename: &str) -> bool { @@ -635,7 +852,7 @@ impl Elf64Shdr { sh_link: read_u32_le!(bin, shoff + 40), sh_info: read_u32_le!(bin, shoff + 44), sh_addralign: read_u64_le!(bin, shoff + 48), - sh_entsize: read_u64_le!(bin, 56), + sh_entsize: read_u64_le!(bin, shoff + 56), } } } @@ -651,6 +868,48 @@ pub struct Elf64Sym { pub st_size: u64, } +#[derive(Debug, Default)] +pub struct Elf64DynamicInfo { + pub needed: Vec, + pub strtab_addr: u64, + pub symtab_addr: u64, + pub syment: u64, + pub rela_addr: u64, + pub rela_size: u64, + pub rela_ent: u64, + pub jmprel_addr: u64, + pub pltrelsz: u64, +} + +#[derive(Debug)] +pub struct Elf64Rela { + pub r_offset: u64, + pub r_info: u64, + pub r_addend: i64, +} + +impl Elf64Rela { + pub fn parse(bin: &[u8], off: usize) -> Elf64Rela { + Elf64Rela { + r_offset: read_u64_le!(bin, off), + r_info: read_u64_le!(bin, off + 8), + r_addend: read_u64_le!(bin, off + 16) as i64, + } + } + + pub fn size() -> usize { + 24 + } + + pub fn r_sym(&self) -> u32 { + (self.r_info >> 32) as u32 + } + + pub fn r_type(&self) -> u32 { + self.r_info as u32 + } +} + impl Elf64Sym { pub fn parse(bin: &[u8], off: usize) -> Elf64Sym { Elf64Sym { diff --git a/crates/libmwemu/src/loaders/macho/macho64.rs b/crates/libmwemu/src/loaders/macho/macho64.rs index f3ad8cc9..5de4ae29 100644 --- a/crates/libmwemu/src/loaders/macho/macho64.rs +++ b/crates/libmwemu/src/loaders/macho/macho64.rs @@ -7,6 +7,7 @@ use std::io::Read; const MH_MAGIC_64: u32 = 0xFEEDFACF; const CPU_TYPE_ARM64: u32 = 0x0100000C; +const CPU_TYPE_X86_64: u32 = 0x01000007; // Chained fixup pointer format constants const DYLD_CHAINED_PTR_64_OFFSET: u16 = 6; @@ -44,22 +45,37 @@ pub struct ChainedImport { } impl Macho64 { - /// Detect a 64-bit AArch64 Mach-O file by reading the first 8 bytes. - pub fn is_macho64_aarch64(filename: &str) -> bool { + fn read_magic_and_cputype(filename: &str) -> Option<(u32, u32)> { let mut f = match std::fs::File::open(filename) { Ok(f) => f, - Err(_) => return false, + Err(_) => return None, }; let mut buf = [0u8; 8]; if f.read_exact(&mut buf).is_err() { - return false; + return None; } let magic = u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]); let cputype = u32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]]); - magic == MH_MAGIC_64 && cputype == CPU_TYPE_ARM64 + Some((magic, cputype)) + } + + /// Detect a 64-bit AArch64 Mach-O file by reading the first 8 bytes. + pub fn is_macho64_aarch64(filename: &str) -> bool { + matches!( + Self::read_magic_and_cputype(filename), + Some((MH_MAGIC_64, CPU_TYPE_ARM64)) + ) + } + + /// Detect a 64-bit x86_64 Mach-O file by reading the first 8 bytes. + pub fn is_macho64_x64(filename: &str) -> bool { + matches!( + Self::read_magic_and_cputype(filename), + Some((MH_MAGIC_64, CPU_TYPE_X86_64)) + ) } - /// Parse a Mach-O 64-bit AArch64 binary using goblin. + /// Parse a 64-bit Mach-O binary using goblin. pub fn parse(filename: &str) -> Result { let bin = fs::read(filename) .map_err(|e| MwemuError::new(&format!("cannot read macho binary: {}", e)))?; diff --git a/crates/libmwemu/src/syscall/macos/mod.rs b/crates/libmwemu/src/syscall/macos/mod.rs index 45476812..46e19cb9 100644 --- a/crates/libmwemu/src/syscall/macos/mod.rs +++ b/crates/libmwemu/src/syscall/macos/mod.rs @@ -1 +1,2 @@ pub mod syscall_aarch64; +pub mod syscall_x86_64; diff --git a/crates/libmwemu/src/syscall/macos/syscall_aarch64.rs b/crates/libmwemu/src/syscall/macos/syscall_aarch64.rs index 85886ac7..dbdd94ce 100644 --- a/crates/libmwemu/src/syscall/macos/syscall_aarch64.rs +++ b/crates/libmwemu/src/syscall/macos/syscall_aarch64.rs @@ -21,7 +21,10 @@ pub fn gateway(emu: &mut emu::Emu) { let status = emu.regs_aarch64().x[0]; log::info!( "{}** {} macos syscall exit({}) {}", - emu.colors.light_red, emu.pos, status, emu.colors.nc + emu.colors.light_red, + emu.pos, + status, + emu.colors.nc ); emu.stop(); } @@ -33,7 +36,12 @@ pub fn gateway(emu: &mut emu::Emu) { log::info!( "{}** {} macos syscall write(fd={}, buf=0x{:x}, count={}) {}", - emu.colors.light_red, emu.pos, fd, buf, count, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + buf, + count, + emu.colors.nc ); if fd == 1 || fd == 2 { @@ -51,7 +59,12 @@ pub fn gateway(emu: &mut emu::Emu) { let count = emu.regs_aarch64().x[2]; log::info!( "{}** {} macos syscall read(fd={}, buf=0x{:x}, count={}) {}", - emu.colors.light_red, emu.pos, fd, buf, count, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + buf, + count, + emu.colors.nc ); todo!("macos read syscall"); } @@ -62,7 +75,11 @@ pub fn gateway(emu: &mut emu::Emu) { let path = emu.maps.read_string(path_addr); log::info!( "{}** {} macos syscall open(\"{}\", 0x{:x}) {}", - emu.colors.light_red, emu.pos, path, flags, emu.colors.nc + emu.colors.light_red, + emu.pos, + path, + flags, + emu.colors.nc ); todo!("macos open syscall"); } @@ -71,7 +88,10 @@ pub fn gateway(emu: &mut emu::Emu) { let fd = emu.regs_aarch64().x[0]; log::info!( "{}** {} macos syscall close(fd={}) {}", - emu.colors.light_red, emu.pos, fd, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + emu.colors.nc ); todo!("macos close syscall"); } @@ -79,7 +99,9 @@ pub fn gateway(emu: &mut emu::Emu) { SYS_FORK => { log::info!( "{}** {} macos syscall fork() {}", - emu.colors.light_red, emu.pos, emu.colors.nc + emu.colors.light_red, + emu.pos, + emu.colors.nc ); todo!("macos fork syscall"); } @@ -103,7 +125,11 @@ pub fn gateway(emu: &mut emu::Emu) { let len = emu.regs_aarch64().x[1]; log::info!( "{}** {} macos syscall munmap(addr=0x{:x}, len=0x{:x}) {}", - emu.colors.light_red, emu.pos, addr, len, emu.colors.nc + emu.colors.light_red, + emu.pos, + addr, + len, + emu.colors.nc ); todo!("macos munmap syscall"); } @@ -114,7 +140,12 @@ pub fn gateway(emu: &mut emu::Emu) { let prot = emu.regs_aarch64().x[2]; log::info!( "{}** {} macos syscall mprotect(addr=0x{:x}, len=0x{:x}, prot=0x{:x}) {}", - emu.colors.light_red, emu.pos, addr, len, prot, emu.colors.nc + emu.colors.light_red, + emu.pos, + addr, + len, + prot, + emu.colors.nc ); todo!("macos mprotect syscall"); } @@ -124,7 +155,11 @@ pub fn gateway(emu: &mut emu::Emu) { let request = emu.regs_aarch64().x[1]; log::info!( "{}** {} macos syscall ioctl(fd={}, request=0x{:x}) {}", - emu.colors.light_red, emu.pos, fd, request, emu.colors.nc + emu.colors.light_red, + emu.pos, + fd, + request, + emu.colors.nc ); todo!("macos ioctl syscall"); } @@ -132,7 +167,9 @@ pub fn gateway(emu: &mut emu::Emu) { SYS_ISSETUGID => { log::info!( "{}** {} macos syscall issetugid() => 0 {}", - emu.colors.light_red, emu.pos, emu.colors.nc + emu.colors.light_red, + emu.pos, + emu.colors.nc ); emu.regs_aarch64_mut().x[0] = 0; } diff --git a/crates/libmwemu/src/syscall/macos/syscall_x86_64.rs b/crates/libmwemu/src/syscall/macos/syscall_x86_64.rs new file mode 100644 index 00000000..742a65a7 --- /dev/null +++ b/crates/libmwemu/src/syscall/macos/syscall_x86_64.rs @@ -0,0 +1,160 @@ +use crate::emu; + +// macOS BSD syscall numbers (x86_64: RAX = 0x2000000 | syscall number) +const SYS_EXIT: u64 = 0x2000001; +const SYS_FORK: u64 = 0x2000002; +const SYS_READ: u64 = 0x2000003; +const SYS_WRITE: u64 = 0x2000004; +const SYS_OPEN: u64 = 0x2000005; +const SYS_CLOSE: u64 = 0x2000006; +const SYS_MUNMAP: u64 = 0x2000049; +const SYS_MPROTECT: u64 = 0x200004a; +const SYS_MMAP: u64 = 0x20000c5; +const SYS_IOCTL: u64 = 0x2000036; +const SYS_ISSETUGID: u64 = 0x2000147; + +#[inline] +fn syscall_nr(emu: &emu::Emu) -> u64 { + let nr = emu.regs().rax; + if nr & 0x2000000 != 0 { + nr + } else { + 0x2000000 | nr + } +} + +#[inline] +fn log_syscall(emu: &emu::Emu, msg: &str) { + log::info!( + "{}** {} macos syscall {} {}", + emu.colors.light_red, + emu.pos, + msg, + emu.colors.nc + ); +} + +pub fn gateway(emu: &mut emu::Emu) { + let syscall_nr = syscall_nr(emu); + + match syscall_nr { + SYS_EXIT => { + let status = emu.regs().rdi; + log_syscall(emu, &format!("exit({})", status)); + emu.stop(); + } + + SYS_WRITE => { + let fd = emu.regs().rdi; + let buf = emu.regs().rsi; + let count = emu.regs().rdx; + + log_syscall( + emu, + &format!("write(fd={}, buf=0x{:x}, count={})", fd, buf, count), + ); + + if fd == 1 || fd == 2 { + let s = emu.maps.read_string(buf); + log::info!("{}: \"{}\"", if fd == 1 { "stdout" } else { "stderr" }, s); + } + + // Return bytes written + emu.regs_mut().rax = count; + } + + SYS_READ => { + let fd = emu.regs().rdi; + let buf = emu.regs().rsi; + let count = emu.regs().rdx; + log_syscall( + emu, + &format!("read(fd={}, buf=0x{:x}, count={})", fd, buf, count), + ); + emu.regs_mut().rax = u64::MAX; + } + + SYS_OPEN => { + let path_addr = emu.regs().rdi; + let flags = emu.regs().rsi; + let path = emu.maps.read_string(path_addr); + log_syscall(emu, &format!("open(\"{}\", 0x{:x})", path, flags)); + emu.regs_mut().rax = u64::MAX; + } + + SYS_CLOSE => { + let fd = emu.regs().rdi; + log_syscall(emu, &format!("close(fd={})", fd)); + emu.regs_mut().rax = u64::MAX; + } + + SYS_FORK => { + log_syscall(emu, "fork()"); + emu.regs_mut().rax = u64::MAX; + } + + SYS_MMAP => { + let addr = emu.regs().rdi; + let len = emu.regs().rsi; + let prot = emu.regs().rdx; + let flags = emu.regs().r10; + let fd = emu.regs().r8; + let off = emu.regs().r9; + log_syscall( + emu, + &format!( + "mmap(addr=0x{:x}, len=0x{:x}, prot=0x{:x}, flags=0x{:x}, fd={}, off=0x{:x})", + addr, len, prot, flags, fd as i64, off + ), + ); + emu.regs_mut().rax = u64::MAX; + } + + SYS_MUNMAP => { + let addr = emu.regs().rdi; + let len = emu.regs().rsi; + log_syscall(emu, &format!("munmap(addr=0x{:x}, len=0x{:x})", addr, len)); + emu.regs_mut().rax = u64::MAX; + } + + SYS_MPROTECT => { + let addr = emu.regs().rdi; + let len = emu.regs().rsi; + let prot = emu.regs().rdx; + log_syscall( + emu, + &format!( + "mprotect(addr=0x{:x}, len=0x{:x}, prot=0x{:x})", + addr, len, prot + ), + ); + emu.regs_mut().rax = u64::MAX; + } + + SYS_IOCTL => { + let fd = emu.regs().rdi; + let request = emu.regs().rsi; + log_syscall(emu, &format!("ioctl(fd={}, request=0x{:x})", fd, request)); + emu.regs_mut().rax = u64::MAX; + } + + SYS_ISSETUGID => { + log_syscall(emu, "issetugid() => 0"); + emu.regs_mut().rax = 0; + } + + _ => { + log::warn!( + "{}** {} macos unimplemented syscall 0x{:x} (rdi=0x{:x}, rsi=0x{:x}, rdx=0x{:x}) {}", + emu.colors.light_red, + emu.pos, + syscall_nr, + emu.regs().rdi, + emu.regs().rsi, + emu.regs().rdx, + emu.colors.nc + ); + emu.regs_mut().rax = u64::MAX; + } + } +} diff --git a/crates/libmwemu/src/tests/fixtures/elf64_x86_64_linux_hello.bin b/crates/libmwemu/src/tests/fixtures/elf64_x86_64_linux_hello.bin new file mode 100755 index 00000000..0305be9c Binary files /dev/null and b/crates/libmwemu/src/tests/fixtures/elf64_x86_64_linux_hello.bin differ diff --git a/crates/libmwemu/src/tests/fixtures/elf64_x86_64_linux_hello.c b/crates/libmwemu/src/tests/fixtures/elf64_x86_64_linux_hello.c new file mode 100644 index 00000000..880fce1d --- /dev/null +++ b/crates/libmwemu/src/tests/fixtures/elf64_x86_64_linux_hello.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + puts("Hello, Linux x86_64!"); + return 7; +} diff --git a/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello.bin b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello.bin new file mode 100755 index 00000000..f8d04c68 Binary files /dev/null and b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello.bin differ diff --git a/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello.c b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello.c new file mode 100644 index 00000000..83371703 --- /dev/null +++ b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + puts("Hello, macOS x86_64!"); + return 0; +} diff --git a/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello_raw.bin b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello_raw.bin new file mode 100755 index 00000000..ee9975c0 Binary files /dev/null and b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello_raw.bin differ diff --git a/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello_raw.s b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello_raw.s new file mode 100644 index 00000000..69ee315e --- /dev/null +++ b/crates/libmwemu/src/tests/fixtures/macho64_x86_64_hello_raw.s @@ -0,0 +1,17 @@ +.text +.globl _start +.p2align 4, 0x90 +_start: + movq $0x2000004, %rax + movq $1, %rdi + leaq _msg(%rip), %rsi + movq $14, %rdx + syscall + + movq $0x2000001, %rax + xorl %edi, %edi + syscall + +.section __TEXT,__cstring,cstring_literals +_msg: + .asciz "Hello, World!\n" diff --git a/crates/libmwemu/src/tests/isa/aarch64/aarch64_basic.rs b/crates/libmwemu/src/tests/isa/aarch64/aarch64_basic.rs index a29168d2..cec788e8 100644 --- a/crates/libmwemu/src/tests/isa/aarch64/aarch64_basic.rs +++ b/crates/libmwemu/src/tests/isa/aarch64/aarch64_basic.rs @@ -9,9 +9,7 @@ fn aarch64_add_1_plus_1() { // mov x1, #1 -> 0xd2800021 // add x2, x0, x1 -> 0x8b010002 let code: [u8; 12] = [ - 0x20, 0x00, 0x80, 0xd2, - 0x21, 0x00, 0x80, 0xd2, - 0x02, 0x00, 0x01, 0x8b, + 0x20, 0x00, 0x80, 0xd2, 0x21, 0x00, 0x80, 0xd2, 0x02, 0x00, 0x01, 0x8b, ]; let mut emu = emu_aarch64(); @@ -35,9 +33,7 @@ fn aarch64_sub_sets_flags() { // mov x1, #5 -> 0xd28000a1 // subs x2, x0, x1 -> 0xeb010002 let code: [u8; 12] = [ - 0xa0, 0x00, 0x80, 0xd2, - 0xa1, 0x00, 0x80, 0xd2, - 0x02, 0x00, 0x01, 0xeb, + 0xa0, 0x00, 0x80, 0xd2, 0xa1, 0x00, 0x80, 0xd2, 0x02, 0x00, 0x01, 0xeb, ]; let mut emu = emu_aarch64(); @@ -48,9 +44,9 @@ fn aarch64_sub_sets_flags() { emu.step(); // subs x2, x0, x1 assert_eq!(emu.regs_aarch64().x[2], 0); - assert!(emu.regs_aarch64().nzcv.z); // zero flag set + assert!(emu.regs_aarch64().nzcv.z); // zero flag set assert!(!emu.regs_aarch64().nzcv.n); // not negative - assert!(emu.regs_aarch64().nzcv.c); // ARM: carry = NOT borrow, so set when a >= b + assert!(emu.regs_aarch64().nzcv.c); // ARM: carry = NOT borrow, so set when a >= b } #[test] @@ -63,11 +59,8 @@ fn aarch64_str_ldr_stack() { // mov x0, #0 -> 0xd2800000 // ldr x1, [sp] -> 0xf94003e1 let code: [u8; 20] = [ - 0xff, 0x43, 0x00, 0xd1, - 0x40, 0x05, 0x80, 0xd2, - 0xe0, 0x03, 0x00, 0xf9, - 0x00, 0x00, 0x80, 0xd2, - 0xe1, 0x03, 0x40, 0xf9, + 0xff, 0x43, 0x00, 0xd1, 0x40, 0x05, 0x80, 0xd2, 0xe0, 0x03, 0x00, 0xf9, 0x00, 0x00, 0x80, + 0xd2, 0xe1, 0x03, 0x40, 0xf9, ]; let mut emu = emu_aarch64(); @@ -93,9 +86,7 @@ fn aarch64_branch_and_link() { // mov x0, #0xdead -> 0xd29bd5a0 (should be skipped) // mov x0, #0xbeef -> 0xd297dde0 (branch target) let code: [u8; 12] = [ - 0x02, 0x00, 0x00, 0x94, - 0xa0, 0xd5, 0x9b, 0xd2, - 0xe0, 0xdd, 0x97, 0xd2, + 0x02, 0x00, 0x00, 0x94, 0xa0, 0xd5, 0x9b, 0xd2, 0xe0, 0xdd, 0x97, 0xd2, ]; let mut emu = emu_aarch64(); @@ -103,8 +94,8 @@ fn aarch64_branch_and_link() { let base = emu.regs_aarch64().pc; emu.step(); // bl #8 - assert_eq!(emu.regs_aarch64().pc, base + 8); // jumped to 3rd instruction - assert_eq!(emu.regs_aarch64().x[30], base + 4); // LR = return address + assert_eq!(emu.regs_aarch64().pc, base + 8); // jumped to 3rd instruction + assert_eq!(emu.regs_aarch64().x[30], base + 4); // LR = return address emu.step(); // mov x0, #0xbeef assert_eq!(emu.regs_aarch64().x[0], 0xbeef); @@ -119,10 +110,8 @@ fn aarch64_cbz_taken() { // mov x1, #0xdead -> 0xd29bd5a1 (should be skipped) // mov x1, #1 -> 0xd2800021 (branch target) let code: [u8; 16] = [ - 0x00, 0x00, 0x80, 0xd2, - 0x40, 0x00, 0x00, 0xb4, - 0xa1, 0xd5, 0x9b, 0xd2, - 0x21, 0x00, 0x80, 0xd2, + 0x00, 0x00, 0x80, 0xd2, 0x40, 0x00, 0x00, 0xb4, 0xa1, 0xd5, 0x9b, 0xd2, 0x21, 0x00, 0x80, + 0xd2, ]; let mut emu = emu_aarch64(); @@ -179,12 +168,14 @@ fn aarch64_shellcode_sum_loop() { } assert_eq!( - emu.regs_aarch64().x[0], 15, + emu.regs_aarch64().x[0], + 15, "x0 should be 1+2+3+4+5=15, got {}", emu.regs_aarch64().x[0] ); assert_eq!( - emu.regs_aarch64().x[1], 0, + emu.regs_aarch64().x[1], + 0, "x1 (counter) should be 0 after loop" ); } @@ -221,7 +212,8 @@ fn aarch64_shellcode_sum_loop_run_to() { emu.pos ); assert_eq!( - emu.regs_aarch64().x[0], 15, + emu.regs_aarch64().x[0], + 15, "x0 should be 15, got {}", emu.regs_aarch64().x[0] ); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aaa_aas.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aaa_aas.rs index 78c9b8d4..98ccccea 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aaa_aas.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aaa_aas.rs @@ -67,7 +67,11 @@ fn test_aaa_adjustment_needed_low_nibble() { // AX = 0x000A + 0x0106 = 0x0110, then AL masked to 0x0F -> 0x00 assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0 after masking"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 1"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 1" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -84,8 +88,16 @@ fn test_aaa_adjustment_needed_af_set() { emu.run(None).unwrap(); // AX = 0x0005 + 0x0106 = 0x010B, then AL masked to 0x0F -> 0x0B - assert_eq!(emu.regs().rax & 0xFF, 0x0B, "AL should be 0x0B after masking"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0B, + "AL should be 0x0B after masking" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -98,7 +110,7 @@ fn test_aaa_all_digits_0_through_9() { let code = [0x37, 0xf4]; // AAA, HLT emu.regs_mut().rax = digit; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, digit, "AL should remain {}", digit); assert!(!emu.flags().f_cf, "CF should be clear for digit {}", digit); @@ -114,11 +126,21 @@ fn test_aaa_values_0a_through_0f() { let code = [0x37, 0xf4]; // AAA, HLT emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected_al = val.wrapping_add(6) & 0x0F; - assert_eq!(emu.regs().rax & 0xFF, expected_al, "AL should be masked for value 0x{:02X}", val); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 for value 0x{:02X}", val); + assert_eq!( + emu.regs().rax & 0xFF, + expected_al, + "AL should be masked for value 0x{:02X}", + val + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 for value 0x{:02X}", + val + ); assert!(emu.flags().f_cf, "CF should be set for value 0x{:02X}", val); assert!(emu.flags().f_af, "AF should be set for value 0x{:02X}", val); } @@ -150,7 +172,11 @@ fn test_aaa_bcd_addition_example() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5 (ones digit)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 (tens digit)"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 (tens digit)" + ); } #[test] @@ -162,7 +188,11 @@ fn test_aaa_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF_1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF_1234, + "High bits should be preserved" + ); } #[test] @@ -191,7 +221,11 @@ fn test_aaa_ah_overflow() { emu.run(None).unwrap(); // 0xFF0A + 0x0106 = 0x10010, AX wraps to 0x0010, then AL masked to 0x00 - assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX should wrap and mask to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0000, + "AX should wrap and mask to 0" + ); } // ============================================================================ @@ -230,7 +264,11 @@ fn test_aas_adjustment_needed_low_nibble() { // AL = AL - 6 = 0x0F - 6 = 0x09, then masked to 0x0F -> 0x09 // AH = AH - 1 = 0x00 - 1 = 0xFF assert_eq!(emu.regs().rax & 0xFF, 0x09, "AL should be 9"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFF, "AH should be 0xFF (decremented)"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFF, + "AH should be 0xFF (decremented)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -249,7 +287,11 @@ fn test_aas_adjustment_needed_af_set() { // AL = AL - 6 = 5 - 6 = -1 = 0xFF, masked to 0x0F -> 0x0F // AH borrows from AL subtraction, then decrements by 1 assert_eq!(emu.regs().rax & 0xFF, 0x0F, "AL should be 0x0F"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFE, "AH should be decremented with borrow"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFE, + "AH should be decremented with borrow" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -262,7 +304,7 @@ fn test_aas_all_digits_0_through_9() { let code = [0x3F, 0xf4]; // AAS, HLT emu.regs_mut().rax = digit; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, digit, "AL should remain {}", digit); assert!(!emu.flags().f_cf, "CF should be clear for digit {}", digit); @@ -278,11 +320,21 @@ fn test_aas_values_0a_through_0f() { let code = [0x3F, 0xf4]; // AAS, HLT emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected_al = ((val as i8 - 6) as u8) & 0x0F; - assert_eq!(emu.regs().rax & 0xFF, expected_al as u64, "AL should be adjusted for value 0x{:02X}", val); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFF, "AH should be 0xFF for value 0x{:02X}", val); + assert_eq!( + emu.regs().rax & 0xFF, + expected_al as u64, + "AL should be adjusted for value 0x{:02X}", + val + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFF, + "AH should be 0xFF for value 0x{:02X}", + val + ); assert!(emu.flags().f_cf, "CF should be set for value 0x{:02X}", val); assert!(emu.flags().f_af, "AF should be set for value 0x{:02X}", val); } @@ -329,7 +381,11 @@ fn test_aas_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF_1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF_1234, + "High bits should be preserved" + ); } #[test] @@ -478,7 +534,11 @@ fn test_aaa_boundary_9_to_10() { emu.regs_mut().rax = 0x000A; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0100, "AL=0x0A should adjust to 0x0100"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0100, + "AL=0x0A should adjust to 0x0100" + ); assert!(emu.flags().f_af, "AF should be set for 0x0A"); } @@ -516,7 +576,11 @@ fn test_aaa_unpacked_bcd_chain() { // 0x0011 + 0x0106 = 0x0117, masked -> 0x0107 assert_eq!(emu.regs().rax & 0xFF, 0x07, "AL should be 7 (ones digit)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 (tens digit)"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 (tens digit)" + ); } #[test] @@ -545,7 +609,11 @@ fn test_aaa_masking_high_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5 (high nibble masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x05, + "AL should be 5 (high nibble masked)" + ); } #[test] @@ -557,5 +625,9 @@ fn test_aas_masking_high_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x08, "AL should be 8 (high nibble masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x08, + "AL should be 8 (high nibble masked)" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aam_aad.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aam_aad.rs index b8fbddea..2e28f619 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aam_aad.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/aam_aad.rs @@ -33,14 +33,18 @@ fn test_aam_basic_decimal() { // AAM with base 10 (standard): AL = 35 let code = [ 0xD4, 0x0A, // AAM (base 10) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0023; // AL = 35 decimal emu.load_code_bytes(&code); emu.run(None).unwrap(); // AH = 35 / 10 = 3, AL = 35 % 10 = 5 - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x03, "AH should be 3 (quotient)"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x03, + "AH should be 3 (quotient)" + ); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5 (remainder)"); assert!(!emu.flags().f_zf, "ZF should be clear"); assert!(!emu.flags().f_sf, "SF should be clear"); @@ -99,14 +103,26 @@ fn test_aam_all_single_digit_products() { let code = [0xD4, 0x0A, 0xf4]; // AAM, HLT emu.regs_mut().rax = product as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected_ah = product / 10; let expected_al = product % 10; - assert_eq!((emu.regs().rax >> 8) & 0xFF, expected_ah as u64, - "AH wrong for {} * {} = {}", i, j, product); - assert_eq!(emu.regs().rax & 0xFF, expected_al as u64, - "AL wrong for {} * {} = {}", i, j, product); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + expected_ah as u64, + "AH wrong for {} * {} = {}", + i, + j, + product + ); + assert_eq!( + emu.regs().rax & 0xFF, + expected_al as u64, + "AL wrong for {} * {} = {}", + i, + j, + product + ); } } } @@ -180,7 +196,11 @@ fn test_aam_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF_1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF_1234, + "High bits should be preserved" + ); } #[test] @@ -234,7 +254,7 @@ fn test_aad_basic_decimal() { // AAD with base 10: AH=3, AL=5 (representing 35 in unpacked BCD) let code = [ 0xD5, 0x0A, // AAD (base 10) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0305; // AH=3, AL=5 emu.load_code_bytes(&code); @@ -299,13 +319,23 @@ fn test_aad_all_two_digit_values() { let code = [0xD5, 0x0A, 0xf4]; // AAD, HLT emu.regs_mut().rax = ((tens << 8) | ones) as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = tens * 10 + ones; - assert_eq!(emu.regs().rax & 0xFF, expected as u64, - "Wrong result for AH={}, AL={}", tens, ones); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, - "AH should be 0 for AH={}, AL={}", tens, ones); + assert_eq!( + emu.regs().rax & 0xFF, + expected as u64, + "Wrong result for AH={}, AL={}", + tens, + ones + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0, + "AH should be 0 for AH={}, AL={}", + tens, + ones + ); } } } @@ -364,7 +394,11 @@ fn test_aad_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF_1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF_1234, + "High bits should be preserved" + ); } #[test] @@ -405,15 +439,19 @@ fn test_aam_aad_roundtrip() { let code = [ 0xD4, 0x0A, // AAM 0xD5, 0x0A, // AAD - 0xf4, // HLT + 0xf4, // HLT ]; for val in 0..100 { emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, val, "Roundtrip failed for {}", val); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH should be 0 after roundtrip"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0, + "AH should be 0 after roundtrip" + ); } } @@ -425,7 +463,7 @@ fn test_aad_aam_sequence() { let code = [ 0xD5, 0x0A, // AAD (unpacked -> binary) 0xD4, 0x0A, // AAM (binary -> unpacked) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0807; // 87 in unpacked BCD emu.load_code_bytes(&code); @@ -441,7 +479,7 @@ fn test_multiply_with_aam() { let mut emu = emu64(); let code = [ 0xD4, 0x0A, // AAM - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 42; // Product of 6 * 7 emu.load_code_bytes(&code); @@ -457,13 +495,17 @@ fn test_division_with_aad() { let mut emu = emu64(); let code = [ 0xD5, 0x0A, // AAD - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0807; // 87 in unpacked BCD emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 87, "AL should be 87 (ready for division)"); + assert_eq!( + emu.regs().rax & 0xFF, + 87, + "AL should be 87 (ready for division)" + ); assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH should be 0"); } @@ -534,14 +576,22 @@ fn test_aam_all_bases() { let test_val = 100u8; emu.regs_mut().rax = test_val as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected_ah = test_val / base; let expected_al = test_val % base; - assert_eq!((emu.regs().rax >> 8) & 0xFF, expected_ah as u64, - "AH wrong for base {}", base); - assert_eq!(emu.regs().rax & 0xFF, expected_al as u64, - "AL wrong for base {}", base); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + expected_ah as u64, + "AH wrong for base {}", + base + ); + assert_eq!( + emu.regs().rax & 0xFF, + expected_al as u64, + "AL wrong for base {}", + base + ); } } @@ -572,10 +622,14 @@ fn test_aam_zero_flag_combinations() { let code = [0xD4, 0x0A, 0xf4]; // AAM emu.regs_mut().rax = val as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.flags().f_zf, expect_zf, - "ZF incorrect for value {}", val); + emu.run(None).unwrap(); + + assert_eq!( + emu.flags().f_zf, + expect_zf, + "ZF incorrect for value {}", + val + ); } } @@ -584,18 +638,22 @@ fn test_aad_zero_flag_combinations() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (0x0000u16, true), // Should set ZF - (0x0100u16, false), // Should clear ZF (AH=1, AL=0 -> 10) - (0x0A00u16, false), // Should clear ZF + (0x0000u16, true), // Should set ZF + (0x0100u16, false), // Should clear ZF (AH=1, AL=0 -> 10) + (0x0A00u16, false), // Should clear ZF ]; for (val, expect_zf) in test_cases { let code = [0xD5, 0x0A, 0xf4]; // AAD emu.regs_mut().rax = val as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.flags().f_zf, expect_zf, - "ZF incorrect for value 0x{:04X}", val); + emu.run(None).unwrap(); + + assert_eq!( + emu.flags().f_zf, + expect_zf, + "ZF incorrect for value 0x{:04X}", + val + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adc_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adc_extended.rs index 8cb9ae7d..94b6517f 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adc_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adc_extended.rs @@ -38,7 +38,7 @@ fn test_adc_al_imm8_no_carry() { // ADC AL, 5 with CF=0 let code = [ 0x14, 0x05, // ADC AL, 5 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0A; emu.load_code_bytes(&code); @@ -86,7 +86,7 @@ fn test_adc_r8_r8_no_carry() { // ADC AL, BL with CF=0 let code = [ 0x10, 0xd8, // ADC AL, BL (ModRM: 11_011_000) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x20; emu.regs_mut().rbx = 0x15; @@ -108,7 +108,11 @@ fn test_adc_r8_r8_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x81, "AL should be 0x81 (127 + 1 + 1)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x81, + "AL should be 0x81 (127 + 1 + 1)" + ); assert!(emu.flags().f_sf, "SF should be set"); assert!(emu.flags().f_of, "OF should be set (signed overflow)"); } @@ -118,9 +122,9 @@ fn test_adc_all_8bit_registers() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (0xd8, "AL"), // ADC AL, BL - (0xc8, "AL"), // ADC AL, CL - (0xd0, "AL"), // ADC AL, DL + (0xd8, "AL"), // ADC AL, BL + (0xc8, "AL"), // ADC AL, CL + (0xd0, "AL"), // ADC AL, DL ]; for (modrm, _name) in test_cases { @@ -131,7 +135,7 @@ fn test_adc_all_8bit_registers() { emu.regs_mut().rdx = 0x07; emu.flags_mut().load(0x01); // Set CF emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // Result should include carry assert!((emu.regs().rax & 0xFF) > 0x10, "ADC should add carry"); @@ -145,7 +149,7 @@ fn test_adc_extended_r8_registers() { // ADC R8B, R9B with CF=1 let code = [ 0x45, 0x10, 0xc8, // ADC R8B, R9B (REX.RB + 10 /r) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r8 = 0x40; emu.regs_mut().r9 = 0x30; @@ -153,7 +157,11 @@ fn test_adc_extended_r8_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFF, 0x71, "R8B should be 0x71 (64 + 48 + 1)"); + assert_eq!( + emu.regs().r8 & 0xFF, + 0x71, + "R8B should be 0x71 (64 + 48 + 1)" + ); } // ============================================================================ @@ -167,7 +175,7 @@ fn test_adc_ax_imm16_no_carry() { // ADC AX, 0x1234 with CF=0 let code = [ 0x66, 0x15, 0x34, 0x12, // ADC AX, 0x1234 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x5678; emu.load_code_bytes(&code); @@ -200,7 +208,7 @@ fn test_adc_r16_r16() { // ADC AX, BX with CF=1 let code = [ 0x66, 0x11, 0xd8, // ADC AX, BX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1000; emu.regs_mut().rbx = 0x2000; @@ -218,7 +226,7 @@ fn test_adc_r16_imm8_sign_extended() { // ADC AX, -1 (sign-extended from imm8) let code = [ 0x66, 0x83, 0xd0, 0xFF, // ADC AX, -1 (sign-extended) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1000; emu.load_code_bytes(&code); @@ -235,7 +243,7 @@ fn test_adc_extended_r16_registers() { // ADC R10W, R11W with CF=1 let code = [ 0x66, 0x45, 0x11, 0xda, // ADC R10W, R11W - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r10 = 0x8000; emu.regs_mut().r11 = 0x7FFF; @@ -258,7 +266,7 @@ fn test_adc_eax_imm32_no_carry() { // ADC EAX, 0x12345678 with CF=0 let code = [ 0x15, 0x78, 0x56, 0x34, 0x12, // ADC EAX, 0x12345678 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x11111111; emu.load_code_bytes(&code); @@ -291,7 +299,7 @@ fn test_adc_r32_r32() { // ADC EAX, EBX with CF=1 let code = [ 0x11, 0xd8, // ADC EAX, EBX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x80000000; emu.regs_mut().rbx = 0x7FFFFFFF; @@ -310,7 +318,7 @@ fn test_adc_r32_imm8_sign_extended() { // ADC EAX, -1 (sign-extended from imm8) let code = [ 0x83, 0xd0, 0xFF, // ADC EAX, -1 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x10000000; emu.load_code_bytes(&code); @@ -326,7 +334,7 @@ fn test_adc_extended_r32_registers() { // ADC R12D, R13D with CF=1 let code = [ 0x45, 0x11, 0xec, // ADC R12D, R13D - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r12 = 0xFFFFFFFF; emu.regs_mut().r13 = 0x00000001; @@ -349,7 +357,7 @@ fn test_adc_rax_imm32_no_carry() { // ADC RAX, 0x12345678 (sign-extended to 64-bit) let code = [ 0x48, 0x15, 0x78, 0x56, 0x34, 0x12, // ADC RAX, 0x12345678 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1111111111111111; emu.load_code_bytes(&code); @@ -370,7 +378,11 @@ fn test_adc_rax_imm32_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000080000001, "RAX should be 0x80000001"); + assert_eq!( + emu.regs().rax, + 0x0000000080000001, + "RAX should be 0x80000001" + ); } #[test] @@ -380,7 +392,7 @@ fn test_adc_r64_r64() { // ADC RAX, RBX with CF=1 let code = [ 0x48, 0x11, 0xd8, // ADC RAX, RBX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0xFFFFFFFFFFFFFFFF; emu.regs_mut().rbx = 0x0000000000000001; @@ -399,13 +411,17 @@ fn test_adc_r64_imm8_sign_extended() { // ADC RAX, -1 (sign-extended from imm8) let code = [ 0x48, 0x83, 0xd0, 0xFF, // ADC RAX, -1 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1000000000000000; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0FFFFFFFFFFFFFFF, "RAX should be decremented"); + assert_eq!( + emu.regs().rax, + 0x0FFFFFFFFFFFFFFF, + "RAX should be decremented" + ); } #[test] @@ -415,7 +431,7 @@ fn test_adc_extended_r64_registers() { // ADC R14, R15 with CF=1 let code = [ 0x4d, 0x11, 0xfe, // ADC R14, R15 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r14 = 0x8000000000000000; emu.regs_mut().r15 = 0x7FFFFFFFFFFFFFFF; @@ -438,7 +454,7 @@ fn test_adc_byte_ptr_imm8() { // ADC BYTE PTR [mem], 0x10 with CF=1 let code = [ 0x80, 0x15, 0xF9, 0x0F, 0x00, 0x00, 0x10, // ADC BYTE PTR [rip+0x0FF9], 0x10 - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_byte(DATA_ADDR, 0x20); @@ -457,8 +473,9 @@ fn test_adc_word_ptr_imm16() { let mut emu = emu64(); // ADC WORD PTR [mem], 0x1000 with CF=1 let code = [ - 0x66, 0x81, 0x15, 0xF7, 0x0F, 0x00, 0x00, 0x00, 0x10, // ADC WORD PTR [rip+0x0FF7], 0x1000 - 0xf4, // HLT + 0x66, 0x81, 0x15, 0xF7, 0x0F, 0x00, 0x00, 0x00, + 0x10, // ADC WORD PTR [rip+0x0FF7], 0x1000 + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, 0x2000); @@ -476,8 +493,9 @@ fn test_adc_dword_ptr_r32() { let mut emu = emu64(); // ADC DWORD PTR [mem], EBX with CF=1 let code = [ - 0x11, 0x1d, 0xFA, 0x0F, 0x00, 0x00, // ADC DWORD PTR [rip+0x0FFA], EBX (target: 0x2000) - 0xf4, // HLT + 0x11, 0x1d, 0xFA, 0x0F, 0x00, + 0x00, // ADC DWORD PTR [rip+0x0FFA], EBX (target: 0x2000) + 0xf4, // HLT ]; emu.regs_mut().rbx = 0x30000000; emu.flags_mut().load(0x01); // Set CF @@ -496,8 +514,9 @@ fn test_adc_qword_ptr_r64() { let mut emu = emu64(); // ADC QWORD PTR [mem], RBX with CF=1 let code = [ - 0x48, 0x11, 0x1d, 0xF9, 0x0F, 0x00, 0x00, // ADC QWORD PTR [rip+0x0FF9], RBX (target: 0x2000) - 0xf4, // HLT + 0x48, 0x11, 0x1d, 0xF9, 0x0F, 0x00, + 0x00, // ADC QWORD PTR [rip+0x0FF9], RBX (target: 0x2000) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x1000000000000000); @@ -517,7 +536,7 @@ fn test_adc_r64_from_memory() { // ADC RAX, QWORD PTR [mem] with CF=1 let code = [ 0x48, 0x13, 0x05, 0xF9, 0x0F, 0x00, 0x00, // ADC RAX, QWORD PTR [rip+0x0FF6] - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x0FFFFFFFFFFFFFFF); @@ -526,7 +545,11 @@ fn test_adc_r64_from_memory() { emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x2000000000000000, "RAX should be correct sum"); + assert_eq!( + emu.regs().rax, + 0x2000000000000000, + "RAX should be correct sum" + ); } // ============================================================================ @@ -620,17 +643,25 @@ fn test_adc_chain_64bit_addition() { let code = [ 0x48, 0x01, 0xd8, // ADD RAX, RBX (low 64 bits) 0x49, 0x11, 0xc8, // ADC R8, RCX (high 64 bits, with carry) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0xFFFFFFFFFFFFFFFF; // Low 64 bits of first number - emu.regs_mut().r8 = 0x0000000000000001; // High 64 bits of first number + emu.regs_mut().r8 = 0x0000000000000001; // High 64 bits of first number emu.regs_mut().rbx = 0x0000000000000002; // Low 64 bits of second number emu.regs_mut().rcx = 0x0000000000000000; // High 64 bits of second number emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "Low 64 bits should be 1"); - assert_eq!(emu.regs().r8, 0x0000000000000002, "High 64 bits should be 2 (with carry)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "Low 64 bits should be 1" + ); + assert_eq!( + emu.regs().r8, + 0x0000000000000002, + "High 64 bits should be 2 (with carry)" + ); } #[test] @@ -642,7 +673,11 @@ fn test_adc_preserves_high_bits_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0xDEADBEEF123456, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0xDEADBEEF123456, + "High bits should be preserved" + ); } #[test] @@ -654,7 +689,11 @@ fn test_adc_preserves_high_bits_16bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF1234, + "High bits should be preserved" + ); } #[test] @@ -667,7 +706,11 @@ fn test_adc_preserves_high_bits_32bit() { emu.run(None).unwrap(); // EAX operation zeros high 32 bits - assert_eq!(emu.regs().rax >> 32, 0, "High 32 bits should be zeroed for 32-bit op"); + assert_eq!( + emu.regs().rax >> 32, + 0, + "High 32 bits should be zeroed for 32-bit op" + ); } // ============================================================================ diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adcx_adox.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adcx_adox.rs index a9db3978..2cdde697 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adcx_adox.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/adcx_adox.rs @@ -32,7 +32,11 @@ fn test_adcx_32bit_no_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, 8, "EAX should be 8"); - assert_eq!(emu.flags().dump() & 0x01, 0, "CF should be clear (no carry out)"); + assert_eq!( + emu.flags().dump() & 0x01, + 0, + "CF should be clear (no carry out)" + ); } #[test] @@ -87,7 +91,11 @@ fn test_adcx_32bit_chain() { emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0, "ECX should be 0 (propagated carry)"); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0, + "ECX should be 0 (propagated carry)" + ); assert_ne!(emu.flags().dump() & 0x01, 0, "CF should still be set"); } @@ -155,7 +163,8 @@ fn test_adcx_64bit_overflow() { let mut emu = emu64(); let code = [ 0xf8, // CLC - 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // MOV RAX, 0xFFFFFFFFFFFFFFFF + 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, // MOV RAX, 0xFFFFFFFFFFFFFFFF 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RBX, 1 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADCX RAX, RBX 0xf4, // HLT @@ -172,14 +181,20 @@ fn test_adcx_64bit_large_values() { let mut emu = emu64(); let code = [ 0xf8, // CLC - 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, // MOV RAX, 0x8000000000000000 - 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // MOV RBX, 0x4000000000000000 + 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, // MOV RAX, 0x8000000000000000 + 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, // MOV RBX, 0x4000000000000000 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADCX RAX, RBX 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC000000000000000, "RAX should be 0xC000000000000000"); + assert_eq!( + emu.regs().rax, + 0xC000000000000000, + "RAX should be 0xC000000000000000" + ); } // ===== ADOX BASIC 32-BIT TESTS ===== @@ -253,7 +268,11 @@ fn test_adox_32bit_preserves_cf() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_ne!(emu.flags().dump() & 0x01, 0, "CF should still be set (ADOX doesn't modify CF)"); + assert_ne!( + emu.flags().dump() & 0x01, + 0, + "CF should still be set (ADOX doesn't modify CF)" + ); } // ===== ADOX 64-BIT TESTS ===== @@ -280,7 +299,8 @@ fn test_adox_64bit_overflow() { let mut emu = emu64(); let code = [ 0x31, 0xc0, // XOR EAX, EAX - 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // MOV RAX, 0xFFFFFFFFFFFFFFFF + 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, // MOV RAX, 0xFFFFFFFFFFFFFFFF 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RBX, 1 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADOX RAX, RBX 0xf4, // HLT @@ -297,14 +317,20 @@ fn test_adox_64bit_large_values() { let mut emu = emu64(); let code = [ 0x31, 0xc0, // XOR EAX, EAX - 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, // MOV RAX, 0x8000000000000000 - 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // MOV RBX, 0x4000000000000000 + 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, // MOV RAX, 0x8000000000000000 + 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, // MOV RBX, 0x4000000000000000 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADOX RAX, RBX 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC000000000000000, "RAX should be 0xC000000000000000"); + assert_eq!( + emu.regs().rax, + 0xC000000000000000, + "RAX should be 0xC000000000000000" + ); } // ===== COMBINED ADCX/ADOX TESTS ===== @@ -362,29 +388,29 @@ fn test_multiprecision_dual_chain() { let code = [ 0xf8, // CLC 0x31, 0xc0, // XOR EAX, EAX (clear OF) - // First chain (CF): Add with carry 0xb8, 0xff, 0xff, 0xff, 0xff, // MOV EAX, 0xFFFFFFFF 0xbb, 0x01, 0x00, 0x00, 0x00, // MOV EBX, 1 0x66, 0x0f, 0x38, 0xf6, 0xc3, // ADCX EAX, EBX (CF=1) - // Second chain (OF): Independent overflow chain 0xb9, 0xff, 0xff, 0xff, 0xff, // MOV ECX, 0xFFFFFFFF 0xba, 0x02, 0x00, 0x00, 0x00, // MOV EDX, 2 0xf3, 0x0f, 0x38, 0xf6, 0xca, // ADOX ECX, EDX (OF=1) - // Continue first chain 0xbe, 0x00, 0x00, 0x00, 0x00, // MOV ESI, 0 0xbf, 0x00, 0x00, 0x00, 0x00, // MOV EDI, 0 0x66, 0x0f, 0x38, 0xf6, 0xf7, // ADCX ESI, EDI (0 + 0 + CF = 1) - 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be 0"); assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 1, "ECX should be 1"); - assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 1, "ESI should be 1 (carry propagated)"); + assert_eq!( + emu.regs().rsi & 0xFFFFFFFF, + 1, + "ESI should be 1 (carry propagated)" + ); } // ===== EDGE CASES ===== @@ -427,7 +453,8 @@ fn test_adcx_memory_operand() { let mut emu = emu64(); let code = [ // Set up memory with value 0x12345678 at 0x2000 - 0xc7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12, // MOV DWORD PTR [0x2000], 0x12345678 + 0xc7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x78, 0x56, 0x34, + 0x12, // MOV DWORD PTR [0x2000], 0x12345678 0xf8, // CLC 0xb8, 0x88, 0xa9, 0xcb, 0xed, // MOV EAX, 0xEDCBA988 0x66, 0x0f, 0x38, 0xf6, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // ADCX EAX, [0x2000] @@ -435,7 +462,11 @@ fn test_adcx_memory_operand() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "Result should wrap"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "Result should wrap" + ); assert_ne!(emu.flags().dump() & 0x01, 0, "CF should be set"); } @@ -445,7 +476,8 @@ fn test_adox_memory_operand() { let mut emu = emu64(); let code = [ // Set up memory - 0xc7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // MOV DWORD PTR [0x2000], 10 + 0xc7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, // MOV DWORD PTR [0x2000], 10 0x31, 0xc0, // XOR EAX, EAX (clear OF) 0xb8, 0x14, 0x00, 0x00, 0x00, // MOV EAX, 20 0xf3, 0x0f, 0x38, 0xf6, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // ADOX EAX, [0x2000] @@ -464,22 +496,20 @@ fn test_256bit_addition_pattern() { let mut emu = emu64(); let code = [ 0xf8, // CLC - // Limb 0: Low 64 bits - 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // MOV RAX, 0xFFFFFFFFFFFFFFFF + 0x48, 0xb8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, // MOV RAX, 0xFFFFFFFFFFFFFFFF 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RBX, 1 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADCX RAX, RBX - // Limb 1 - 0x48, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // MOV RCX, 0xFFFFFFFFFFFFFFFE + 0x48, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, // MOV RCX, 0xFFFFFFFFFFFFFFFE 0x48, 0xba, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RDX, 2 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xca, // ADCX RCX, RDX - // Limb 2 0x48, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RSI, 0 0x48, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RDI, 0 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xf7, // ADCX RSI, RDI - 0xf4, // HLT ]; emu.load_code_bytes(&code); @@ -497,22 +527,18 @@ fn test_interleaved_adcx_adox() { let code = [ 0xf8, // CLC 0x31, 0xc0, // XOR EAX, EAX (clear OF) - // First operand pair (CF chain) 0xb8, 0x01, 0x00, 0x00, 0x00, // MOV EAX, 1 0xbb, 0x02, 0x00, 0x00, 0x00, // MOV EBX, 2 0x66, 0x0f, 0x38, 0xf6, 0xc3, // ADCX EAX, EBX (3, no carry) - // Second operand pair (OF chain) 0xb9, 0x04, 0x00, 0x00, 0x00, // MOV ECX, 4 0xba, 0x05, 0x00, 0x00, 0x00, // MOV EDX, 5 0xf3, 0x0f, 0x38, 0xf6, 0xca, // ADOX ECX, EDX (9, no overflow) - // Third pair (CF chain continues) 0xbe, 0x06, 0x00, 0x00, 0x00, // MOV ESI, 6 0xbf, 0x07, 0x00, 0x00, 0x00, // MOV EDI, 7 0x66, 0x0f, 0x38, 0xf6, 0xf7, // ADCX ESI, EDI (13, no carry) - 0xf4, // HLT ]; emu.load_code_bytes(&code); @@ -574,7 +600,11 @@ fn test_adcx_power_of_two() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x02000000, "EAX should be 0x02000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x02000000, + "EAX should be 0x02000000" + ); } #[test] @@ -590,7 +620,11 @@ fn test_adox_power_of_two() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x04000000, "EAX should be 0x04000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x04000000, + "EAX should be 0x04000000" + ); } #[test] @@ -599,14 +633,20 @@ fn test_adcx_64bit_power_of_two() { let mut emu = emu64(); let code = [ 0xf8, // CLC - 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // MOV RAX, 0x0000000100000000 - 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // MOV RBX, 0x0000000100000000 + 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, // MOV RAX, 0x0000000100000000 + 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, // MOV RBX, 0x0000000100000000 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADCX RAX, RBX 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000200000000, "RAX should be 0x0000000200000000"); + assert_eq!( + emu.regs().rax, + 0x0000000200000000, + "RAX should be 0x0000000200000000" + ); } #[test] @@ -615,14 +655,20 @@ fn test_adox_64bit_power_of_two() { let mut emu = emu64(); let code = [ 0x31, 0xc0, // XOR EAX, EAX - 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // MOV RAX, 0x0000000200000000 - 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // MOV RBX, 0x0000000200000000 + 0x48, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, // MOV RAX, 0x0000000200000000 + 0x48, 0xbb, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, // MOV RBX, 0x0000000200000000 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADOX RAX, RBX 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000400000000, "RAX should be 0x0000000400000000"); + assert_eq!( + emu.regs().rax, + 0x0000000400000000, + "RAX should be 0x0000000400000000" + ); } #[test] @@ -638,7 +684,11 @@ fn test_adcx_32bit_boundary() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x7FFFFFFF, "EAX should be 0x7FFFFFFF"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x7FFFFFFF, + "EAX should be 0x7FFFFFFF" + ); } #[test] @@ -654,7 +704,11 @@ fn test_adox_32bit_boundary() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x7FFFFFFF, "EAX should be 0x7FFFFFFF"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x7FFFFFFF, + "EAX should be 0x7FFFFFFF" + ); } #[test] @@ -752,14 +806,19 @@ fn test_adcx_64bit_full_range() { let mut emu = emu64(); let code = [ 0xf8, // CLC - 0x48, 0xb8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, // MOV RAX, 0x7FFFFFFFFFFFFFFE + 0x48, 0xb8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, // MOV RAX, 0x7FFFFFFFFFFFFFFE 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RBX, 1 0x66, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADCX RAX, RBX 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x7FFFFFFFFFFFFFFF, "RAX should be 0x7FFFFFFFFFFFFFFF"); + assert_eq!( + emu.regs().rax, + 0x7FFFFFFFFFFFFFFF, + "RAX should be 0x7FFFFFFFFFFFFFFF" + ); } #[test] @@ -768,14 +827,19 @@ fn test_adox_64bit_full_range() { let mut emu = emu64(); let code = [ 0x31, 0xc0, // XOR EAX, EAX - 0x48, 0xb8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, // MOV RAX, 0x7FFFFFFFFFFFFFFE + 0x48, 0xb8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x7f, // MOV RAX, 0x7FFFFFFFFFFFFFFE 0x48, 0xbb, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV RBX, 1 0xf3, 0x48, 0x0f, 0x38, 0xf6, 0xc3, // ADOX RAX, RBX 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x7FFFFFFFFFFFFFFF, "RAX should be 0x7FFFFFFFFFFFFFFF"); + assert_eq!( + emu.regs().rax, + 0x7FFFFFFFFFFFFFFF, + "RAX should be 0x7FFFFFFFFFFFFFFF" + ); } #[test] @@ -811,5 +875,9 @@ fn test_adox_with_initial_overflow_propagation() { ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should be 1 (overflow in)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should be 1 (overflow in)" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/add_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/add_extended.rs index 613a9147..4411dcd6 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/add_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/add_extended.rs @@ -103,7 +103,7 @@ fn test_add_all_8bit_gp_registers() { emu.regs_mut().rcx = addend + 1; emu.regs_mut().rdx = addend + 2; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert!((emu.regs().rax & 0xFF) > base, "ADD should increase AL"); } @@ -145,7 +145,7 @@ fn test_add_r8_from_r9_to_r15() { } emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = match reg_num { 8 => emu.regs().r8, @@ -235,8 +235,13 @@ fn test_add_all_16bit_gp_registers() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let regs_to_test = vec![ - (0xD8, "BX"), (0xC8, "CX"), (0xD0, "DX"), - (0xF0, "SI"), (0xF8, "DI"), (0xE0, "SP"), (0xE8, "BP"), + (0xD8, "BX"), + (0xC8, "CX"), + (0xD0, "DX"), + (0xF0, "SI"), + (0xF8, "DI"), + (0xE0, "SP"), + (0xE8, "BP"), ]; for (modrm, _name) in regs_to_test { @@ -386,7 +391,11 @@ fn test_add_r64_r64() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x3000000000000000, "RAX should be correct sum"); + assert_eq!( + emu.regs().rax, + 0x3000000000000000, + "RAX should be correct sum" + ); } #[test] @@ -398,7 +407,11 @@ fn test_add_r64_imm8_sign_extended() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0FFFFFFFFFFFFFFF, "RAX should be decremented"); + assert_eq!( + emu.regs().rax, + 0x0FFFFFFFFFFFFFFF, + "RAX should be decremented" + ); } #[test] @@ -406,8 +419,8 @@ fn test_add_all_64bit_gp_registers() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let all_regs = [ - "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", - "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" + "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", + "R13", "R14", "R15", ]; for i in 0..all_regs.len() { @@ -436,9 +449,13 @@ fn test_add_all_64bit_gp_registers() { emu.regs_mut().r15 = 0x0F00000000000000; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert!(emu.regs().rax >= 0x1000000000000000, "RAX should increase for {}", all_regs[i]); + assert!( + emu.regs().rax >= 0x1000000000000000, + "RAX should increase for {}", + all_regs[i] + ); } } @@ -531,7 +548,11 @@ fn test_add_r64_from_memory() { emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x3000000000000000, "RAX should be correct sum"); + assert_eq!( + emu.regs().rax, + 0x3000000000000000, + "RAX should be correct sum" + ); } // ============================================================================ @@ -656,7 +677,11 @@ fn test_add_preserves_high_bits_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0xDEADBEEF123456, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0xDEADBEEF123456, + "High bits should be preserved" + ); } #[test] @@ -668,7 +693,11 @@ fn test_add_preserves_high_bits_16bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF1234, + "High bits should be preserved" + ); } #[test] @@ -680,7 +709,11 @@ fn test_add_zeros_high_bits_32bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 32, 0, "High 32 bits should be zeroed for 32-bit op"); + assert_eq!( + emu.regs().rax >> 32, + 0, + "High 32 bits should be zeroed for 32-bit op" + ); } #[test] @@ -714,5 +747,9 @@ fn test_add_commutative() { emu2.load_code_bytes(&code2); emu2.run(None).unwrap(); - assert_eq!(emu1.regs().rax & 0xFF, emu2.regs().rbx & 0xFF, "Results should match"); + assert_eq!( + emu1.regs().rax & 0xFF, + emu2.regs().rbx & 0xFF, + "Results should match" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aaa.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aaa.rs index 04ebbf48..322591c4 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aaa.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aaa.rs @@ -99,8 +99,16 @@ fn test_aaa_lower_nibble_0a() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0x00 (0x0A + 0x06 = 0x10, masked to 0x00)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x00, + "AL should be 0x00 (0x0A + 0x06 = 0x10, masked to 0x00)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -116,7 +124,11 @@ fn test_aaa_lower_nibble_0b() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x01, "AL should be 0x01"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -132,7 +144,11 @@ fn test_aaa_lower_nibble_0f() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 0x05"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -151,8 +167,16 @@ fn test_aaa_with_upper_nibble_1x() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0x00 (upper nibble cleared)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x00, + "AL should be 0x00 (upper nibble cleared)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -168,7 +192,11 @@ fn test_aaa_with_upper_nibble_2x() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x01, "AL should be 0x01"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -184,7 +212,11 @@ fn test_aaa_with_upper_nibble_fx() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x02, "AL should be 0x02"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x02, "AH should be incremented to 0x02"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x02, + "AH should be incremented to 0x02" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -220,7 +252,11 @@ fn test_aaa_ah_nonzero_adjust() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x03, "AL should be 0x03"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x08, "AH should be incremented to 0x08"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x08, + "AH should be incremented to 0x08" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -256,8 +292,16 @@ fn test_aaa_af_set_valid_bcd() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x0B, "AL should be 0x0B (0x05 + 0x06 = 0x0B)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0B, + "AL should be 0x0B (0x05 + 0x06 = 0x0B)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -274,7 +318,11 @@ fn test_aaa_af_set_zero() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x06, "AL should be 0x06"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -290,8 +338,16 @@ fn test_aaa_af_set_nine() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x0F, "AL should be 0x0F (0x09 + 0x06 = 0x0F)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be incremented to 0x01"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0F, + "AL should be 0x0F (0x09 + 0x06 = 0x0F)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be incremented to 0x01" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -307,8 +363,8 @@ fn test_aaa_after_add_3_plus_4() { let code = [ 0xb0, 0x03, // MOV AL, 3 0x04, 0x04, // ADD AL, 4 - 0x37, // AAA - 0xf4, // HLT + 0x37, // AAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -326,14 +382,22 @@ fn test_aaa_after_add_5_plus_6() { let code = [ 0xb0, 0x05, // MOV AL, 5 0x04, 0x06, // ADD AL, 6 - 0x37, // AAA - 0xf4, // HLT + 0x37, // AAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x01, "Result should be 1 (ones digit)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 (tens digit)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x01, + "Result should be 1 (ones digit)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 (tens digit)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -345,14 +409,22 @@ fn test_aaa_after_add_9_plus_9() { let code = [ 0xb0, 0x09, // MOV AL, 9 0x04, 0x09, // ADD AL, 9 - 0x37, // AAA - 0xf4, // HLT + 0x37, // AAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x08, "Result should be 8 (ones digit)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 (tens digit)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x08, + "Result should be 8 (ones digit)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 (tens digit)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -364,14 +436,22 @@ fn test_aaa_after_add_7_plus_8() { let code = [ 0xb0, 0x07, // MOV AL, 7 0x04, 0x08, // ADD AL, 8 - 0x37, // AAA - 0xf4, // HLT + 0x37, // AAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x05, "Result should be 5 (ones digit)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 (tens digit)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x05, + "Result should be 5 (ones digit)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 (tens digit)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -387,8 +467,8 @@ fn test_aaa_multidigit_34_plus_45() { let code = [ 0xb0, 0x04, // MOV AL, 4 0x04, 0x05, // ADD AL, 5 - 0x37, // AAA - 0xf4, // HLT + 0x37, // AAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -404,8 +484,8 @@ fn test_aaa_multidigit_38_plus_47() { let code = [ 0xb0, 0x08, // MOV AL, 8 0x04, 0x07, // ADD AL, 7 - 0x37, // AAA - 0xf4, // HLT + 0x37, // AAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -426,14 +506,20 @@ fn test_aaa_all_lower_nibbles() { let code = [0x37, 0xf4]; emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); if val <= 9 { assert_eq!(emu.regs().rax & 0xFF, val, "AL should remain {:#04x}", val); assert!(!emu.flags().f_cf, "CF should be clear for {:#04x}", val); } else { let expected = (val + 6) & 0x0F; - assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {:#04x} for input {:#04x}", expected, val); + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "AL should be {:#04x} for input {:#04x}", + expected, + val + ); assert!(emu.flags().f_cf, "CF should be set for {:#04x}", val); } } @@ -448,7 +534,11 @@ fn test_aaa_upper_bits_cleared() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xF0, 0x00, "Upper 4 bits of AL should be cleared"); + assert_eq!( + emu.regs().rax & 0xF0, + 0x00, + "Upper 4 bits of AL should be cleared" + ); } #[test] @@ -460,7 +550,11 @@ fn test_aaa_preserves_high_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0x1234_5678_DEAD, "High bits of RAX should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0x1234_5678_DEAD, + "High bits of RAX should be preserved" + ); } #[test] @@ -470,10 +564,10 @@ fn test_aaa_sequential_operations() { let code = [ 0xb0, 0x08, // MOV AL, 8 0x04, 0x05, // ADD AL, 5 (result: 13 = 0x0D) - 0x37, // AAA (result: AL=3, AH=1) + 0x37, // AAA (result: AL=3, AH=1) 0x04, 0x07, // ADD AL, 7 (result: 10 = 0x0A) - 0x37, // AAA (result: AL=0, AH=2) - 0xf4, // HLT + 0x37, // AAA (result: AL=0, AH=2) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -488,9 +582,9 @@ fn test_aaa_with_initial_carry() { let mut emu = emu64(); let code = [ 0xb8, 0x08, 0x00, // MOV AX, 0x0008 (AH=0, AL=8) - 0x04, 0x09, // ADD AL, 9 (result: 17 = 0x11) - 0x37, // AAA (result: AL=7, AH=1) - 0xf4, // HLT + 0x04, 0x09, // ADD AL, 9 (result: 17 = 0x11) + 0x37, // AAA (result: AL=7, AH=1) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aad.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aad.rs index 91431f89..6537c6a0 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aad.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aad.rs @@ -38,7 +38,7 @@ fn test_aad_zero() { // AX = 0x0000, result: AL = 0, AH = 0 let code = [ 0xd5, 0x0a, // AAD - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0000; emu.load_code_bytes(&code); @@ -222,10 +222,10 @@ fn test_aad_before_div_58_by_4() { let mut emu = emu64(); let code = [ 0xb8, 0x08, 0x05, // MOV AX, 0x0508 (BCD 58) - 0xd5, 0x0a, // AAD (convert to binary 58) - 0xb3, 0x04, // MOV BL, 4 - 0xf6, 0xf3, // DIV BL (AL = quotient, AH = remainder) - 0xf4, // HLT + 0xd5, 0x0a, // AAD (convert to binary 58) + 0xb3, 0x04, // MOV BL, 4 + 0xf6, 0xf3, // DIV BL (AL = quotient, AH = remainder) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -240,10 +240,10 @@ fn test_aad_before_div_72_by_8() { let mut emu = emu64(); let code = [ 0xb8, 0x02, 0x07, // MOV AX, 0x0702 (BCD 72) - 0xd5, 0x0a, // AAD (convert to binary 72) - 0xb3, 0x08, // MOV BL, 8 - 0xf6, 0xf3, // DIV BL - 0xf4, // HLT + 0xd5, 0x0a, // AAD (convert to binary 72) + 0xb3, 0x08, // MOV BL, 8 + 0xf6, 0xf3, // DIV BL + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -258,10 +258,10 @@ fn test_aad_before_div_37_by_5() { let mut emu = emu64(); let code = [ 0xb8, 0x07, 0x03, // MOV AX, 0x0307 (BCD 37) - 0xd5, 0x0a, // AAD (convert to binary 37) - 0xb3, 0x05, // MOV BL, 5 - 0xf6, 0xf3, // DIV BL - 0xf4, // HLT + 0xd5, 0x0a, // AAD (convert to binary 37) + 0xb3, 0x05, // MOV BL, 5 + 0xf6, 0xf3, // DIV BL + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -276,10 +276,10 @@ fn test_aad_before_div_99_by_9() { let mut emu = emu64(); let code = [ 0xb8, 0x09, 0x09, // MOV AX, 0x0909 (BCD 99) - 0xd5, 0x0a, // AAD (convert to binary 99) - 0xb3, 0x09, // MOV BL, 9 - 0xf6, 0xf3, // DIV BL - 0xf4, // HLT + 0xd5, 0x0a, // AAD (convert to binary 99) + 0xb3, 0x09, // MOV BL, 9 + 0xf6, 0xf3, // DIV BL + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -299,7 +299,7 @@ fn test_aad_base_2() { // AX = 0x0301 (3*2 + 1 = 7 in base 2), result: AL = 7 let code = [ 0xd5, 0x02, // AAD 2 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0301; emu.load_code_bytes(&code); @@ -316,7 +316,7 @@ fn test_aad_base_8_octal() { // AX = 0x0305 (3*8 + 5 = 29 in base 8), result: AL = 29 let code = [ 0xd5, 0x08, // AAD 8 (octal) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0305; emu.load_code_bytes(&code); @@ -333,7 +333,7 @@ fn test_aad_base_12() { // AX = 0x0407 (4*12 + 7 = 55 in base 12), result: AL = 55 let code = [ 0xd5, 0x0c, // AAD 12 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0407; emu.load_code_bytes(&code); @@ -350,7 +350,7 @@ fn test_aad_base_16_hex() { // AX = 0x0A0B (10*16 + 11 = 171 in base 16), result: AL = 171 let code = [ 0xd5, 0x10, // AAD 16 (hex) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0A0B; emu.load_code_bytes(&code); @@ -367,7 +367,7 @@ fn test_aad_base_7() { // AX = 0x0506 (5*7 + 6 = 41 in base 7), result: AL = 41 let code = [ 0xd5, 0x07, // AAD 7 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0506; emu.load_code_bytes(&code); @@ -497,7 +497,11 @@ fn test_aad_preserves_high_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0x1234_5678_DEAD, "High bits of RAX should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0x1234_5678_DEAD, + "High bits of RAX should be preserved" + ); assert_eq!(emu.regs().rax & 0xFF, 25, "AL should be 25"); assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0"); } @@ -514,10 +518,23 @@ fn test_aad_all_two_digit_bcd() { let code = [0xd5, 0x0a, 0xf4]; emu.regs_mut().rax = bcd; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {} for BCD {}{}", expected, tens, ones); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0 for BCD {}{}", tens, ones); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "AL should be {} for BCD {}{}", + expected, + tens, + ones + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be 0 for BCD {}{}", + tens, + ones + ); } } } @@ -530,7 +547,7 @@ fn test_aad_al_only() { let code = [0xd5, 0x0a, 0xf4]; emu.regs_mut().rax = al_val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, al_val, "AL should remain {}", al_val); assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0"); @@ -545,9 +562,14 @@ fn test_aad_ah_only() { let code = [0xd5, 0x0a, 0xf4]; emu.regs_mut().rax = ah_val << 8; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, ah_val * 10, "AL should be {}", ah_val * 10); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + ah_val * 10, + "AL should be {}", + ah_val * 10 + ); assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0"); } } @@ -557,21 +579,31 @@ fn test_aad_with_different_bases() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = [ - (2, 3 * 2 + 4), // base 2: 3*2 + 4 = 10 - (5, 3 * 5 + 4), // base 5: 3*5 + 4 = 19 - (10, 3 * 10 + 4), // base 10: 3*10 + 4 = 34 - (12, 3 * 12 + 4), // base 12: 3*12 + 4 = 40 - (16, 3 * 16 + 4), // base 16: 3*16 + 4 = 52 + (2, 3 * 2 + 4), // base 2: 3*2 + 4 = 10 + (5, 3 * 5 + 4), // base 5: 3*5 + 4 = 19 + (10, 3 * 10 + 4), // base 10: 3*10 + 4 = 34 + (12, 3 * 12 + 4), // base 12: 3*12 + 4 = 40 + (16, 3 * 16 + 4), // base 16: 3*16 + 4 = 52 ]; for (base, expected) in test_cases.iter() { let code = [0xd5, *base, 0xf4]; emu.regs_mut().rax = 0x0304; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, *expected as u64, "AL incorrect for base {}", base); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0 for base {}", base); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + *expected as u64, + "AL incorrect for base {}", + base + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be 0 for base {}", + base + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aam.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aam.rs index e9d95c3f..82ac3fc8 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aam.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aam.rs @@ -37,7 +37,7 @@ fn test_aam_zero() { // AL = 0, result: AH = 0, AL = 0 let code = [ 0xd4, 0x0a, // AAM - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x00; emu.load_code_bytes(&code); @@ -92,7 +92,11 @@ fn test_aam_ten() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0 (10 MOD 10)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x01, "AH should be 1 (10 / 10)"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x01, + "AH should be 1 (10 / 10)" + ); assert!(emu.flags().f_zf, "ZF should be set (AL = 0)"); } @@ -179,11 +183,11 @@ fn test_aam_after_mul_3_times_4() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xb0, 0x03, // MOV AL, 3 - 0xb3, 0x04, // MOV BL, 4 - 0xf6, 0xe3, // MUL BL - 0xd4, 0x0a, // AAM - 0xf4, // HLT + 0xb0, 0x03, // MOV AL, 3 + 0xb3, 0x04, // MOV BL, 4 + 0xf6, 0xe3, // MUL BL + 0xd4, 0x0a, // AAM + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -197,11 +201,11 @@ fn test_aam_after_mul_5_times_6() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xb0, 0x05, // MOV AL, 5 - 0xb3, 0x06, // MOV BL, 6 - 0xf6, 0xe3, // MUL BL - 0xd4, 0x0a, // AAM - 0xf4, // HLT + 0xb0, 0x05, // MOV AL, 5 + 0xb3, 0x06, // MOV BL, 6 + 0xf6, 0xe3, // MUL BL + 0xd4, 0x0a, // AAM + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -215,11 +219,11 @@ fn test_aam_after_mul_7_times_8() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xb0, 0x07, // MOV AL, 7 - 0xb3, 0x08, // MOV BL, 8 - 0xf6, 0xe3, // MUL BL - 0xd4, 0x0a, // AAM - 0xf4, // HLT + 0xb0, 0x07, // MOV AL, 7 + 0xb3, 0x08, // MOV BL, 8 + 0xf6, 0xe3, // MUL BL + 0xd4, 0x0a, // AAM + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -233,11 +237,11 @@ fn test_aam_after_mul_9_times_9() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xb0, 0x09, // MOV AL, 9 - 0xb3, 0x09, // MOV BL, 9 - 0xf6, 0xe3, // MUL BL - 0xd4, 0x0a, // AAM - 0xf4, // HLT + 0xb0, 0x09, // MOV AL, 9 + 0xb3, 0x09, // MOV BL, 9 + 0xf6, 0xe3, // MUL BL + 0xd4, 0x0a, // AAM + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -251,11 +255,11 @@ fn test_aam_after_mul_8_times_7() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xb0, 0x08, // MOV AL, 8 - 0xb3, 0x07, // MOV BL, 7 - 0xf6, 0xe3, // MUL BL - 0xd4, 0x0a, // AAM - 0xf4, // HLT + 0xb0, 0x08, // MOV AL, 8 + 0xb3, 0x07, // MOV BL, 7 + 0xf6, 0xe3, // MUL BL + 0xd4, 0x0a, // AAM + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -335,7 +339,7 @@ fn test_aam_base_2() { // AL = 5, base 2: AH = 2, AL = 1 (5 = 2*2 + 1) let code = [ 0xd4, 0x02, // AAM 2 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x05; emu.load_code_bytes(&code); @@ -352,7 +356,7 @@ fn test_aam_base_8_octal() { // AL = 25 (0x19), base 8: AH = 3, AL = 1 (25 = 3*8 + 1) let code = [ 0xd4, 0x08, // AAM 8 (octal) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x19; emu.load_code_bytes(&code); @@ -369,7 +373,7 @@ fn test_aam_base_12() { // AL = 37 (0x25), base 12: AH = 3, AL = 1 (37 = 3*12 + 1) let code = [ 0xd4, 0x0c, // AAM 12 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x25; emu.load_code_bytes(&code); @@ -386,7 +390,7 @@ fn test_aam_base_16_hex() { // AL = 0xAB (171), base 16: AH = 10, AL = 11 let code = [ 0xd4, 0x10, // AAM 16 (hex) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0xAB; emu.load_code_bytes(&code); @@ -403,7 +407,7 @@ fn test_aam_base_7() { // AL = 50 (0x32), base 7: AH = 7, AL = 1 (50 = 7*7 + 1) let code = [ 0xd4, 0x07, // AAM 7 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x32; emu.load_code_bytes(&code); @@ -487,7 +491,11 @@ fn test_aam_preserves_high_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0x1234_5678_DEAD, "High bits of RAX should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0x1234_5678_DEAD, + "High bits of RAX should be preserved" + ); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5"); assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x02, "AH should be 2"); } @@ -500,10 +508,19 @@ fn test_aam_all_single_digits() { let code = [0xd4, 0x0a, 0xf4]; emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, val, "AL should remain {} for single digit", val); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be 0 for single digit"); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + val, + "AL should remain {} for single digit", + val + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be 0 for single digit" + ); } } @@ -516,10 +533,16 @@ fn test_aam_multiples_of_10() { let code = [0xd4, 0x0a, 0xf4]; emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0 for {}", val); - assert_eq!((emu.regs().rax >> 8) & 0xFF, mult as u64, "AH should be {} for {}", mult, val); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + mult as u64, + "AH should be {} for {}", + mult, + val + ); } } @@ -531,12 +554,24 @@ fn test_aam_sequential_values() { let code = [0xd4, 0x0a, 0xf4]; emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected_ah = val / 10; let expected_al = val % 10; - assert_eq!(emu.regs().rax & 0xFF, expected_al, "AL should be {} for input {}", expected_al, val); - assert_eq!((emu.regs().rax >> 8) & 0xFF, expected_ah, "AH should be {} for input {}", expected_ah, val); + assert_eq!( + emu.regs().rax & 0xFF, + expected_al, + "AL should be {} for input {}", + expected_al, + val + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + expected_ah, + "AH should be {} for input {}", + expected_ah, + val + ); } } @@ -551,7 +586,11 @@ fn test_aam_ignores_initial_ah() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 5 (25 MOD 10)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x02, "AH should be 2 (25 / 10)"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x02, + "AH should be 2 (25 / 10)" + ); } #[test] @@ -559,21 +598,31 @@ fn test_aam_with_different_bases_comprehensive() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = [ - (2, 0, 100 / 2), // base 2 - (3, 1, 100 / 3), // base 3 - (5, 0, 100 / 5), // base 5 - (10, 0, 10), // base 10 - (11, 1, 100 / 11), // base 11 - (20, 0, 5), // base 20 + (2, 0, 100 / 2), // base 2 + (3, 1, 100 / 3), // base 3 + (5, 0, 100 / 5), // base 5 + (10, 0, 10), // base 10 + (11, 1, 100 / 11), // base 11 + (20, 0, 5), // base 20 ]; for (base, expected_al, expected_ah) in test_cases.iter() { let code = [0xd4, *base, 0xf4]; emu.regs_mut().rax = 100; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, *expected_al as u64, "AL incorrect for base {}", base); - assert_eq!((emu.regs().rax >> 8) & 0xFF, *expected_ah as u64, "AH incorrect for base {}", base); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + *expected_al as u64, + "AL incorrect for base {}", + base + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + *expected_ah as u64, + "AH incorrect for base {}", + base + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aas.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aas.rs index 527892b1..b398964a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aas.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/aas.rs @@ -101,8 +101,16 @@ fn test_aas_lower_nibble_0a() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x04, "AL should be 0x04 (0x0A - 0x06 = 0x04)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x04, + "AL should be 0x04 (0x0A - 0x06 = 0x04)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -118,7 +126,11 @@ fn test_aas_lower_nibble_0b() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 0x05"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -134,7 +146,11 @@ fn test_aas_lower_nibble_0f() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x09, "AL should be 0x09"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -153,8 +169,16 @@ fn test_aas_with_upper_nibble_1x() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x04, "AL should be 0x04 (upper nibble cleared)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x04, + "AL should be 0x04 (upper nibble cleared)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -170,7 +194,11 @@ fn test_aas_with_upper_nibble_2x() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 0x05"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -186,7 +214,11 @@ fn test_aas_with_upper_nibble_fx() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x06, "AL should be 0x06"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -222,7 +254,11 @@ fn test_aas_ah_nonzero_adjust() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x07, "AL should be 0x07"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x06, "AH should be decremented to 0x06"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x06, + "AH should be decremented to 0x06" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -258,8 +294,16 @@ fn test_aas_af_set_valid_bcd() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x0F, "AL should be 0x0F (0x05 - 0x06 = 0xFF, masked = 0x0F)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFF, "AH should be decremented with borrow"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0F, + "AL should be 0x0F (0x05 - 0x06 = 0xFF, masked = 0x0F)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFF, + "AH should be decremented with borrow" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -276,7 +320,11 @@ fn test_aas_af_set_zero() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x0A, "AL should be 0x0A"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFF, "AH should be decremented with borrow"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFF, + "AH should be decremented with borrow" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -292,8 +340,16 @@ fn test_aas_af_set_nine() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x03, "AL should be 0x03 (0x09 - 0x06 = 0x03)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x00, "AH should be decremented to 0x00"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x03, + "AL should be 0x03 (0x09 - 0x06 = 0x03)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x00, + "AH should be decremented to 0x00" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -309,8 +365,8 @@ fn test_aas_after_sub_8_minus_3() { let code = [ 0xb0, 0x08, // MOV AL, 8 0x2c, 0x03, // SUB AL, 3 - 0x3f, // AAS - 0xf4, // HLT + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -328,14 +384,22 @@ fn test_aas_after_sub_3_minus_5() { let code = [ 0xb0, 0x03, // MOV AL, 3 0x2c, 0x05, // SUB AL, 5 (result: 0xFE, AF set) - 0x3f, // AAS - 0xf4, // HLT + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x08, "AL should be 0x08 (0xFE - 0x06 = 0xF8, masked = 0x08)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFF, "AH should be 0xFF (borrow)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x08, + "AL should be 0x08 (0xFE - 0x06 = 0xF8, masked = 0x08)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFF, + "AH should be 0xFF (borrow)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -347,8 +411,8 @@ fn test_aas_after_sub_9_minus_9() { let code = [ 0xb0, 0x09, // MOV AL, 9 0x2c, 0x09, // SUB AL, 9 - 0x3f, // AAS - 0xf4, // HLT + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -366,14 +430,22 @@ fn test_aas_after_sub_2_minus_7() { let code = [ 0xb0, 0x02, // MOV AL, 2 0x2c, 0x07, // SUB AL, 7 (result: 0xFB, AF set) - 0x3f, // AAS - 0xf4, // HLT + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 0x05 (0xFB - 0x06 = 0xF5, masked = 0x05)"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0xFF, "AH should be 0xFF (borrow)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x05, + "AL should be 0x05 (0xFB - 0x06 = 0xF5, masked = 0x05)" + ); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0xFF, + "AH should be 0xFF (borrow)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -389,8 +461,8 @@ fn test_aas_multidigit_78_minus_34() { let code = [ 0xb0, 0x08, // MOV AL, 8 0x2c, 0x04, // SUB AL, 4 - 0x3f, // AAS - 0xf4, // HLT + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -406,8 +478,8 @@ fn test_aas_multidigit_52_minus_37() { let code = [ 0xb0, 0x02, // MOV AL, 2 0x2c, 0x07, // SUB AL, 7 (result: 0xFB, AF set) - 0x3f, // AAS - 0xf4, // HLT + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -428,14 +500,20 @@ fn test_aas_all_lower_nibbles() { let code = [0x3f, 0xf4]; emu.regs_mut().rax = 0x0100 | val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); if val <= 9 { assert_eq!(emu.regs().rax & 0xFF, val, "AL should remain {:#04x}", val); assert!(!emu.flags().f_cf, "CF should be clear for {:#04x}", val); } else { let expected = (val.wrapping_sub(6)) & 0x0F; - assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {:#04x} for input {:#04x}", expected, val); + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "AL should be {:#04x} for input {:#04x}", + expected, + val + ); assert!(emu.flags().f_cf, "CF should be set for {:#04x}", val); } } @@ -450,7 +528,11 @@ fn test_aas_upper_bits_cleared() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xF0, 0x00, "Upper 4 bits of AL should be cleared"); + assert_eq!( + emu.regs().rax & 0xF0, + 0x00, + "Upper 4 bits of AL should be cleared" + ); } #[test] @@ -462,7 +544,11 @@ fn test_aas_preserves_high_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0x1234_5678_DEAD, "High bits of RAX should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0x1234_5678_DEAD, + "High bits of RAX should be preserved" + ); } #[test] @@ -471,10 +557,10 @@ fn test_aas_sequential_operations() { let mut emu = emu64(); let code = [ 0xb8, 0x03, 0x00, // MOV AX, 0x0003 (AH=0, AL=3) - 0x2c, 0x05, // SUB AL, 5 (result: 0xFE, borrow) - 0x3f, // AAS (result: AL=8, AH=FF) + 0x2c, 0x05, // SUB AL, 5 (result: 0xFE, borrow) + 0x3f, // AAS (result: AL=8, AH=FF) 0x80, 0xec, 0x09, // SUB AH, 9 (manually adjust tens) - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -504,9 +590,9 @@ fn test_aas_double_borrow() { let mut emu = emu64(); let code = [ 0xb8, 0x00, 0x00, // MOV AX, 0x0000 - 0x2c, 0x05, // SUB AL, 5 (result: 0xFB) - 0x3f, // AAS - 0xf4, // HLT + 0x2c, 0x05, // SUB AL, 5 (result: 0xFB) + 0x3f, // AAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -526,7 +612,11 @@ fn test_aas_with_high_ah() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x06, "AL should be 0x06"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0x98, "AH should be decremented to 0x98"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0x98, + "AH should be decremented to 0x98" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/daa.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/daa.rs index 29a4092b..0099a26f 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/daa.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/daa.rs @@ -84,9 +84,14 @@ fn test_daa_valid_bcd_values() { let code = [0x27, 0xf4]; emu.regs_mut().rax = *val as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, *val as u64, "AL should remain {:#04x}", val); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + *val as u64, + "AL should remain {:#04x}", + val + ); assert!(!emu.flags().f_cf, "CF should be clear for {:#04x}", val); assert!(!emu.flags().f_af, "AF should be clear for {:#04x}", val); } @@ -106,7 +111,11 @@ fn test_daa_lower_nibble_0a() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x10, "AL should be 0x10 (0x0A + 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x10, + "AL should be 0x10 (0x0A + 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -121,7 +130,11 @@ fn test_daa_lower_nibble_0f() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x15, "AL should be 0x15 (0x0F + 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x15, + "AL should be 0x15 (0x0F + 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -136,7 +149,11 @@ fn test_daa_lower_nibble_1c() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x22, "AL should be 0x22 (0x1C + 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x22, + "AL should be 0x22 (0x1C + 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -155,7 +172,11 @@ fn test_daa_upper_nibble_a0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0x00 (0xA0 + 0x60 = 0x100, wrapped)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x00, + "AL should be 0x00 (0xA0 + 0x60 = 0x100, wrapped)" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -169,7 +190,11 @@ fn test_daa_upper_nibble_f0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x50, "AL should be 0x50 (0xF0 + 0x60 = 0x150, wrapped)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x50, + "AL should be 0x50 (0xF0 + 0x60 = 0x150, wrapped)" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -221,13 +246,17 @@ fn test_daa_after_add_25_plus_34() { let code = [ 0xb0, 0x25, // MOV AL, 0x25 0x04, 0x34, // ADD AL, 0x34 - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x59, "Result should be 0x59 (BCD 59)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x59, + "Result should be 0x59 (BCD 59)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -238,13 +267,17 @@ fn test_daa_after_add_79_plus_35() { let code = [ 0xb0, 0x79, // MOV AL, 0x79 0x04, 0x35, // ADD AL, 0x35 (result: 0xAE) - 0x27, // DAA (should produce 0x14 with CF=1) - 0xf4, // HLT + 0x27, // DAA (should produce 0x14 with CF=1) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x14, "Result should be 0x14 (ones place of 114)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x14, + "Result should be 0x14 (ones place of 114)" + ); assert!(emu.flags().f_cf, "CF should be set (carry to next digit)"); } @@ -256,13 +289,17 @@ fn test_daa_after_add_58_plus_46() { let code = [ 0xb0, 0x58, // MOV AL, 0x58 0x04, 0x46, // ADD AL, 0x46 (result: 0x9E) - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x04, "Result should be 0x04 (ones place of 104)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x04, + "Result should be 0x04 (ones place of 104)" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -274,13 +311,17 @@ fn test_daa_after_add_99_plus_99() { let code = [ 0xb0, 0x99, // MOV AL, 0x99 0x04, 0x99, // ADD AL, 0x99 (result: 0x132, wrapped to 0x32, CF=1) - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x98, "Result should be 0x98 (ones place of 198)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x98, + "Result should be 0x98 (ones place of 198)" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -292,13 +333,17 @@ fn test_daa_after_add_15_plus_27() { let code = [ 0xb0, 0x15, // MOV AL, 0x15 0x04, 0x27, // ADD AL, 0x27 (result: 0x3C) - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "Result should be 0x42 (BCD 42)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "Result should be 0x42 (BCD 42)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -317,7 +362,11 @@ fn test_daa_af_set_valid_lower_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x2B, "AL should be 0x2B (0x25 + 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x2B, + "AL should be 0x2B (0x25 + 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -354,7 +403,11 @@ fn test_daa_cf_set_causes_upper_adjust() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x85, "AL should be 0x85 (0x25 + 0x60)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x85, + "AL should be 0x85 (0x25 + 0x60)" + ); assert!(emu.flags().f_cf, "CF should remain set"); } @@ -385,8 +438,8 @@ fn test_daa_multidigit_12_plus_34() { let code = [ 0xb0, 0x02, // MOV AL, 2 0x04, 0x04, // ADD AL, 4 - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -402,13 +455,17 @@ fn test_daa_multidigit_28_plus_37() { let code = [ 0xb0, 0x08, // MOV AL, 8 0x04, 0x07, // ADD AL, 7 (result: 0x0F) - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x15, "Result should be 0x15 (BCD 15)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x15, + "Result should be 0x15 (BCD 15)" + ); assert!(!emu.flags().f_cf, "CF should be clear (< 100)"); } @@ -424,14 +481,25 @@ fn test_daa_all_lower_nibbles() { let code = [0x27, 0xf4]; emu.regs_mut().rax = lower; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); if lower <= 9 { - assert_eq!(emu.regs().rax & 0xFF, lower, "AL should remain {:#04x}", lower); + assert_eq!( + emu.regs().rax & 0xFF, + lower, + "AL should remain {:#04x}", + lower + ); assert!(!emu.flags().f_af, "AF should be clear for {:#04x}", lower); } else { let expected = lower + 6; - assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {:#04x} for input {:#04x}", expected, lower); + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "AL should be {:#04x} for input {:#04x}", + expected, + lower + ); assert!(emu.flags().f_af, "AF should be set for {:#04x}", lower); } } @@ -446,7 +514,11 @@ fn test_daa_preserves_high_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0x1234_5678_DEAD_BE, "High bits of RAX should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0x1234_5678_DEAD_BE, + "High bits of RAX should be preserved" + ); } #[test] @@ -500,15 +572,19 @@ fn test_daa_sequential_additions() { let code = [ 0xb0, 0x15, // MOV AL, 0x15 0x04, 0x27, // ADD AL, 0x27 - 0x27, // DAA (result: 0x42) + 0x27, // DAA (result: 0x42) 0x04, 0x38, // ADD AL, 0x38 - 0x27, // DAA (result: 0x80) - 0xf4, // HLT + 0x27, // DAA (result: 0x80) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x80, "Final result should be 0x80 (BCD 80)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x80, + "Final result should be 0x80 (BCD 80)" + ); } #[test] @@ -518,8 +594,8 @@ fn test_daa_with_previous_carry() { let code = [ 0xb0, 0x99, // MOV AL, 0x99 0x04, 0x01, // ADD AL, 0x01 (result: 0x9A) - 0x27, // DAA (should produce 0x00 with CF=1) - 0xf4, // HLT + 0x27, // DAA (should produce 0x00 with CF=1) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -533,23 +609,29 @@ fn test_daa_comprehensive_packed_bcd() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = [ - (0x12, 0x34, 0x46), // 12 + 34 = 46 - (0x45, 0x23, 0x68), // 45 + 23 = 68 - (0x50, 0x49, 0x99), // 50 + 49 = 99 - (0x33, 0x44, 0x77), // 33 + 44 = 77 + (0x12, 0x34, 0x46), // 12 + 34 = 46 + (0x45, 0x23, 0x68), // 45 + 23 = 68 + (0x50, 0x49, 0x99), // 50 + 49 = 99 + (0x33, 0x44, 0x77), // 33 + 44 = 77 ]; for (a, b, expected) in test_cases.iter() { let code = [ - 0xb0, *a, // MOV AL, a + 0xb0, *a, // MOV AL, a 0x04, *b, // ADD AL, b - 0x27, // DAA - 0xf4, // HLT + 0x27, // DAA + 0xf4, // HLT ]; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, *expected as u64, - "Result of {:#04x} + {:#04x} should be {:#04x}", a, b, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + *expected as u64, + "Result of {:#04x} + {:#04x} should be {:#04x}", + a, + b, + expected + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/das.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/das.rs index aace8de8..320043e9 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/das.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/das.rs @@ -83,9 +83,14 @@ fn test_das_valid_bcd_values() { let code = [0x2f, 0xf4]; emu.regs_mut().rax = *val as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, *val as u64, "AL should remain {:#04x}", val); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + *val as u64, + "AL should remain {:#04x}", + val + ); assert!(!emu.flags().f_cf, "CF should be clear for {:#04x}", val); assert!(!emu.flags().f_af, "AF should be clear for {:#04x}", val); } @@ -105,7 +110,11 @@ fn test_das_lower_nibble_0a() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x04, "AL should be 0x04 (0x0A - 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x04, + "AL should be 0x04 (0x0A - 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -120,7 +129,11 @@ fn test_das_lower_nibble_0f() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x09, "AL should be 0x09 (0x0F - 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x09, + "AL should be 0x09 (0x0F - 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -135,7 +148,11 @@ fn test_das_lower_nibble_1c() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x16, "AL should be 0x16 (0x1C - 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x16, + "AL should be 0x16 (0x1C - 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -154,7 +171,11 @@ fn test_das_upper_nibble_a0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x40, "AL should be 0x40 (0xA0 - 0x60)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x40, + "AL should be 0x40 (0xA0 - 0x60)" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -168,7 +189,11 @@ fn test_das_upper_nibble_f0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x90, "AL should be 0x90 (0xF0 - 0x60)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x90, + "AL should be 0x90 (0xF0 - 0x60)" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -220,13 +245,17 @@ fn test_das_after_sub_79_minus_35() { let code = [ 0xb0, 0x79, // MOV AL, 0x79 0x2c, 0x35, // SUB AL, 0x35 - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x44, "Result should be 0x44 (BCD 44)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x44, + "Result should be 0x44 (BCD 44)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -237,8 +266,8 @@ fn test_das_after_sub_35_minus_47() { let code = [ 0xb0, 0x35, // MOV AL, 0x35 0x2c, 0x47, // SUB AL, 0x47 (result: 0xEE with borrow) - 0x2f, // DAS (should produce 0x88 with CF=1) - 0xf4, // HLT + 0x2f, // DAS (should produce 0x88 with CF=1) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -255,13 +284,17 @@ fn test_das_after_sub_99_minus_01() { let code = [ 0xb0, 0x99, // MOV AL, 0x99 0x2c, 0x01, // SUB AL, 0x01 (result: 0x98) - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x98, "Result should be 0x98 (BCD 98)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x98, + "Result should be 0x98 (BCD 98)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -273,13 +306,17 @@ fn test_das_after_sub_50_minus_25() { let code = [ 0xb0, 0x50, // MOV AL, 0x50 0x2c, 0x25, // SUB AL, 0x25 (result: 0x2B) - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x25, "Result should be 0x25 (BCD 25)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x25, + "Result should be 0x25 (BCD 25)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -291,8 +328,8 @@ fn test_das_after_sub_88_minus_99() { let code = [ 0xb0, 0x88, // MOV AL, 0x88 0x2c, 0x99, // SUB AL, 0x99 (result: 0xEF with borrow) - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -316,7 +353,11 @@ fn test_das_af_set_valid_lower_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x1F, "AL should be 0x1F (0x25 - 0x06)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x1F, + "AL should be 0x1F (0x25 - 0x06)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -353,7 +394,11 @@ fn test_das_cf_set_causes_upper_adjust() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xC5, "AL should be 0xC5 (0x25 - 0x60, wrapped)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xC5, + "AL should be 0xC5 (0x25 - 0x60, wrapped)" + ); assert!(emu.flags().f_cf, "CF should remain set"); } @@ -384,8 +429,8 @@ fn test_das_multidigit_85_minus_32() { let code = [ 0xb0, 0x05, // MOV AL, 5 0x2c, 0x02, // SUB AL, 2 - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -401,8 +446,8 @@ fn test_das_multidigit_52_minus_37() { let code = [ 0xb0, 0x02, // MOV AL, 2 0x2c, 0x07, // SUB AL, 7 (result: 0xFB with borrow) - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -424,14 +469,25 @@ fn test_das_all_lower_nibbles() { let code = [0x2f, 0xf4]; emu.regs_mut().rax = lower; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); if lower <= 9 { - assert_eq!(emu.regs().rax & 0xFF, lower, "AL should remain {:#04x}", lower); + assert_eq!( + emu.regs().rax & 0xFF, + lower, + "AL should remain {:#04x}", + lower + ); assert!(!emu.flags().f_af, "AF should be clear for {:#04x}", lower); } else { let expected = lower - 6; - assert_eq!(emu.regs().rax & 0xFF, expected, "AL should be {:#04x} for input {:#04x}", expected, lower); + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "AL should be {:#04x} for input {:#04x}", + expected, + lower + ); assert!(emu.flags().f_af, "AF should be set for {:#04x}", lower); } } @@ -446,7 +502,11 @@ fn test_das_preserves_high_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0x1234_5678_DEAD_BE, "High bits of RAX should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0x1234_5678_DEAD_BE, + "High bits of RAX should be preserved" + ); } #[test] @@ -500,15 +560,19 @@ fn test_das_sequential_subtractions() { let code = [ 0xb0, 0x99, // MOV AL, 0x99 0x2c, 0x15, // SUB AL, 0x15 - 0x2f, // DAS (result: 0x84) + 0x2f, // DAS (result: 0x84) 0x2c, 0x27, // SUB AL, 0x27 - 0x2f, // DAS (result: 0x57) - 0xf4, // HLT + 0x2f, // DAS (result: 0x57) + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x57, "Final result should be 0x57 (BCD 57)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x57, + "Final result should be 0x57 (BCD 57)" + ); } #[test] @@ -518,8 +582,8 @@ fn test_das_with_borrow_propagation() { let code = [ 0xb0, 0x00, // MOV AL, 0x00 0x2c, 0x01, // SUB AL, 0x01 (result: 0xFF with borrow) - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -534,24 +598,30 @@ fn test_das_comprehensive_packed_bcd() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = [ - (0x79, 0x35, 0x44), // 79 - 35 = 44 - (0x68, 0x23, 0x45), // 68 - 23 = 45 - (0x99, 0x49, 0x50), // 99 - 49 = 50 - (0x77, 0x44, 0x33), // 77 - 44 = 33 + (0x79, 0x35, 0x44), // 79 - 35 = 44 + (0x68, 0x23, 0x45), // 68 - 23 = 45 + (0x99, 0x49, 0x50), // 99 - 49 = 50 + (0x77, 0x44, 0x33), // 77 - 44 = 33 ]; for (a, b, expected) in test_cases.iter() { let code = [ - 0xb0, *a, // MOV AL, a + 0xb0, *a, // MOV AL, a 0x2c, *b, // SUB AL, b - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, *expected as u64, - "Result of {:#04x} - {:#04x} should be {:#04x}", a, b, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + *expected as u64, + "Result of {:#04x} - {:#04x} should be {:#04x}", + a, + b, + expected + ); } } @@ -560,22 +630,27 @@ fn test_das_underflow_cases() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = [ - (0x10, 0x20), // 10 - 20 (needs borrow) - (0x25, 0x50), // 25 - 50 (needs borrow) - (0x00, 0x99), // 00 - 99 (needs borrow) + (0x10, 0x20), // 10 - 20 (needs borrow) + (0x25, 0x50), // 25 - 50 (needs borrow) + (0x00, 0x99), // 00 - 99 (needs borrow) ]; for (a, b) in test_cases.iter() { let code = [ - 0xb0, *a, // MOV AL, a + 0xb0, *a, // MOV AL, a 0x2c, *b, // SUB AL, b - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert!(emu.flags().f_cf, "CF should be set for {:#04x} - {:#04x}", a, b); + emu.run(None).unwrap(); + + assert!( + emu.flags().f_cf, + "CF should be set for {:#04x} - {:#04x}", + a, + b + ); } } @@ -587,8 +662,8 @@ fn test_das_exact_zero_result() { let code = [ 0xb0, 0x45, // MOV AL, 0x45 0x2c, 0x45, // SUB AL, 0x45 - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -605,8 +680,8 @@ fn test_das_with_af_from_subtraction() { let code = [ 0xb0, 0x23, // MOV AL, 0x23 0x2c, 0x05, // SUB AL, 0x05 (result: 0x1E, AF set) - 0x2f, // DAS - 0xf4, // HLT + 0x2f, // DAS + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/mod.rs index 026db93c..5710e074 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/bcd/mod.rs @@ -13,8 +13,8 @@ // decimal arithmetic. pub mod aaa; -pub mod aas; -pub mod aam; pub mod aad; +pub mod aam; +pub mod aas; pub mod daa; pub mod das; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/cmp_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/cmp_extended.rs index 8ffb2c65..7a7d3165 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/cmp_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/cmp_extended.rs @@ -123,9 +123,14 @@ fn test_cmp_all_8bit_registers() { } emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert!(emu.flags().f_zf, "ZF should be set for R{} - R{}", reg_num, reg_num); + emu.run(None).unwrap(); + + assert!( + emu.flags().f_zf, + "ZF should be set for R{} - R{}", + reg_num, + reg_num + ); } } @@ -225,7 +230,11 @@ fn test_cmp_extended_r16() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x8000, "R10W should not be modified"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x8000, + "R10W should not be modified" + ); assert!(!emu.flags().f_cf, "CF should be clear (R10W > R11W)"); } @@ -327,7 +336,11 @@ fn test_cmp_rax_imm32_equal() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000012345678, "RAX should not be modified"); + assert_eq!( + emu.regs().rax, + 0x0000000012345678, + "RAX should not be modified" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -340,7 +353,11 @@ fn test_cmp_rax_imm32_greater() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000020000000, "RAX should not be modified"); + assert_eq!( + emu.regs().rax, + 0x0000000020000000, + "RAX should not be modified" + ); assert!(!emu.flags().f_cf, "CF should be clear (RAX > imm32)"); } @@ -353,7 +370,11 @@ fn test_cmp_rax_imm32_less() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000010000000, "RAX should not be modified"); + assert_eq!( + emu.regs().rax, + 0x0000000010000000, + "RAX should not be modified" + ); assert!(emu.flags().f_cf, "CF should be set (RAX < imm32)"); } @@ -367,8 +388,16 @@ fn test_cmp_r64_r64_equal() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x1234567890ABCDEF, "RAX should not be modified"); - assert_eq!(emu.regs().rbx, 0x1234567890ABCDEF, "RBX should not be modified"); + assert_eq!( + emu.regs().rax, + 0x1234567890ABCDEF, + "RAX should not be modified" + ); + assert_eq!( + emu.regs().rbx, + 0x1234567890ABCDEF, + "RBX should not be modified" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -408,7 +437,11 @@ fn test_cmp_r64_imm8_sign_extended() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX should not be modified"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX should not be modified" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -443,7 +476,7 @@ fn test_cmp_all_64bit_registers() { emu.regs_mut().r15 = test_val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, test_val, "RAX should not be modified"); assert!(emu.flags().f_zf, "ZF should be set for equal values"); @@ -507,7 +540,11 @@ fn test_cmp_r64_from_memory() { emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x1000000000000000, "RAX should not be modified"); + assert_eq!( + emu.regs().rax, + 0x1000000000000000, + "RAX should not be modified" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -642,7 +679,11 @@ fn test_cmp_max_unsigned_values() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX should not be modified"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX should not be modified" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -668,7 +709,11 @@ fn test_cmp_preserves_all_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xDEADBEEF12345678, "RAX should be completely unchanged"); + assert_eq!( + emu.regs().rax, + 0xDEADBEEF12345678, + "RAX should be completely unchanged" + ); assert!(emu.flags().f_zf, "ZF should be set"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/daa_das.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/daa_das.rs index c62509d4..b31913bb 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/daa_das.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/daa_das.rs @@ -72,7 +72,11 @@ fn test_daa_low_nibble_adjustment() { emu.run(None).unwrap(); // AL = 0x1F + 6 = 0x25 - assert_eq!(emu.regs().rax & 0xFF, 0x25, "AL should be 0x25 after adjustment"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x25, + "AL should be 0x25 after adjustment" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(emu.flags().f_af, "AF should be set"); } @@ -88,7 +92,11 @@ fn test_daa_high_nibble_adjustment() { emu.run(None).unwrap(); // AL = 0xA5 + 0x60 = 0x05 (with carry) - assert_eq!(emu.regs().rax & 0xFF, 0x05, "AL should be 0x05 after adjustment"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x05, + "AL should be 0x05 after adjustment" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -103,7 +111,11 @@ fn test_daa_both_nibbles_adjustment() { emu.run(None).unwrap(); // AL = 0xAF + 6 + 0x60 = 0x15 (with carry) - assert_eq!(emu.regs().rax & 0xFF, 0x15, "AL should be 0x15 after adjustment"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x15, + "AL should be 0x15 after adjustment" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -163,7 +175,11 @@ fn test_daa_bcd_addition_with_adjustment() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x62, "Result should be 0x62 (62 in BCD)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x62, + "Result should be 0x62 (62 in BCD)" + ); } #[test] @@ -202,7 +218,11 @@ fn test_daa_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0xDEADBEEF_123456, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0xDEADBEEF_123456, + "High bits should be preserved" + ); } #[test] @@ -215,11 +235,15 @@ fn test_daa_all_valid_bcd_pairs() { let code = [0x27, 0xf4]; // DAA, HLT emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // Valid BCD values should not be adjusted - assert_eq!(emu.regs().rax & 0xFF, val, - "Valid BCD 0x{:02X} should not be adjusted", val); + assert_eq!( + emu.regs().rax & 0xFF, + val, + "Valid BCD 0x{:02X} should not be adjusted", + val + ); } } } @@ -239,13 +263,20 @@ fn test_daa_boundary_values() { let code = [0x27, 0xf4]; // DAA, HLT emu.regs_mut().rax = input; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, expected, - "Wrong result for input 0x{:02X}", input); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "Wrong result for input 0x{:02X}", + input + ); if expect_cf_or_af { - assert!(emu.flags().f_cf || emu.flags().f_af, - "CF or AF should be set for input 0x{:02X}", input); + assert!( + emu.flags().f_cf || emu.flags().f_af, + "CF or AF should be set for input 0x{:02X}", + input + ); } } } @@ -283,7 +314,11 @@ fn test_das_low_nibble_adjustment() { emu.run(None).unwrap(); // AL = 0x1F - 6 = 0x19 - assert_eq!(emu.regs().rax & 0xFF, 0x19, "AL should be 0x19 after adjustment"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x19, + "AL should be 0x19 after adjustment" + ); assert!(emu.flags().f_af, "AF should be set"); } @@ -298,7 +333,11 @@ fn test_das_high_nibble_adjustment() { emu.run(None).unwrap(); // AL = 0xA5 - 0x60 = 0x45 - assert_eq!(emu.regs().rax & 0xFF, 0x45, "AL should be 0x45 after adjustment"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x45, + "AL should be 0x45 after adjustment" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -313,7 +352,11 @@ fn test_das_both_nibbles_adjustment() { emu.run(None).unwrap(); // AL = 0xAF - 6 - 0x60 = 0x49 - assert_eq!(emu.regs().rax & 0xFF, 0x49, "AL should be 0x49 after adjustment"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x49, + "AL should be 0x49 after adjustment" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_af, "AF should be set"); } @@ -398,7 +441,11 @@ fn test_das_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0xDEADBEEF_123456, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0xDEADBEEF_123456, + "High bits should be preserved" + ); } #[test] @@ -411,11 +458,15 @@ fn test_das_all_valid_bcd_pairs() { let code = [0x2F, 0xf4]; // DAS, HLT emu.regs_mut().rax = val; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // Valid BCD values should not be adjusted - assert_eq!(emu.regs().rax & 0xFF, val, - "Valid BCD 0x{:02X} should not be adjusted", val); + assert_eq!( + emu.regs().rax & 0xFF, + val, + "Valid BCD 0x{:02X} should not be adjusted", + val + ); } } } @@ -527,7 +578,10 @@ fn test_das_sign_flag() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert!(emu.flags().f_sf, "SF should be set when result has bit 7 set"); + assert!( + emu.flags().f_sf, + "SF should be set when result has bit 7 set" + ); } #[test] @@ -596,7 +650,11 @@ fn test_daa_bcd_chain_99_plus_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x00, "AL should be 0x00 (overflow to 100)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x00, + "AL should be 0x00 (overflow to 100)" + ); assert!(emu.flags().f_cf, "CF should be set (carry to next byte)"); } @@ -615,10 +673,15 @@ fn test_daa_sequential_additions() { let code = [0x27, 0xf4]; // DAA, HLT emu.regs_mut().rax = input; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, expected, - "DAA(0x{:02X}) should be 0x{:02X}", input, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "DAA(0x{:02X}) should be 0x{:02X}", + input, + expected + ); } } @@ -637,9 +700,14 @@ fn test_das_sequential_subtractions() { let code = [0x2F, 0xf4]; // DAS, HLT emu.regs_mut().rax = input; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFF, expected, - "DAS(0x{:02X}) should be 0x{:02X}", input, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "DAS(0x{:02X}) should be 0x{:02X}", + input, + expected + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/div.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/div.rs index e4407508..491cdd45 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/div.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/div.rs @@ -31,15 +31,19 @@ fn test_div_al_simple() { // AX = 100 (AH=0, AL=100) let code = [ 0xf6, 0xf3, // DIV BL (F6 /6, ModRM=11_110_011) - 0xf4, // HLT + 0xf4, // HLT ]; - emu.regs_mut().rax = 100; // AX = 100 (AH=0, AL=100) - emu.regs_mut().rbx = 10; // BL = 10 + emu.regs_mut().rax = 100; // AX = 100 (AH=0, AL=100) + emu.regs_mut().rbx = 10; // BL = 10 emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 10, "AL (quotient) = 100 / 10 = 10"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 0, "AH (remainder) = 100 % 10 = 0"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 0, + "AH (remainder) = 100 % 10 = 0" + ); } #[test] @@ -54,7 +58,11 @@ fn test_div_al_with_remainder() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 14, "AL (quotient) = 100 / 7 = 14"); - assert_eq!((emu.regs().rax >> 8) & 0xFF, 2, "AH (remainder) = 100 % 7 = 2"); + assert_eq!( + (emu.regs().rax >> 8) & 0xFF, + 2, + "AH (remainder) = 100 % 7 = 2" + ); } #[test] @@ -120,7 +128,11 @@ fn test_div_ax_simple() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 100, "AX (quotient) = 1000 / 10 = 100"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 100, + "AX (quotient) = 1000 / 10 = 100" + ); assert_eq!(emu.regs().rdx & 0xFFFF, 0, "DX (remainder) = 0"); } @@ -145,8 +157,8 @@ fn test_div_ax_dx_nonzero() { let mut emu = emu64(); // (DX:AX) = 0x00011000 (69632) / 100 = 696 remainder 32 let code = [0x66, 0xf7, 0xf3, 0xf4]; // DIV BX - emu.regs_mut().rax = 0x1000; // 4096 - emu.regs_mut().rdx = 0x0001; // High 16 bits = 1 + emu.regs_mut().rax = 0x1000; // 4096 + emu.regs_mut().rdx = 0x0001; // High 16 bits = 1 emu.regs_mut().rbx = 100; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -302,8 +314,8 @@ fn test_div_rax_rdx_nonzero() { // 2^64 / 0x100000001 = 0xFFFFFFFF remainder 1 let code = [0x48, 0xf7, 0xf3, 0xf4]; // DIV RBX emu.regs_mut().rax = 0x0000000000000000; - emu.regs_mut().rdx = 0x0000000000000001; // RDX:RAX = 2^64 - emu.regs_mut().rbx = 0x100000001; // Divisor = 2^32 + 1 = 4294967297 + emu.regs_mut().rdx = 0x0000000000000001; // RDX:RAX = 2^64 + emu.regs_mut().rbx = 0x100000001; // Divisor = 2^32 + 1 = 4294967297 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -367,9 +379,9 @@ fn test_div_cx_16bit() { let mut emu = emu64(); // DIV CX (16-bit) - ModRM 11_110_001 = 0xF1 let code = [0x66, 0xf7, 0xf1, 0xf4]; // DIV CX - emu.regs_mut().rax = 10000; // AX = 10000 - emu.regs_mut().rdx = 0; // DX = 0 (high part of dividend) - emu.regs_mut().rcx = 100; // CX = 100 (divisor) + emu.regs_mut().rax = 10000; // AX = 10000 + emu.regs_mut().rdx = 0; // DX = 0 (high part of dividend) + emu.regs_mut().rcx = 100; // CX = 100 (divisor) emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -548,8 +560,8 @@ fn test_div_result_in_upper() { // 2^33 / 0x80000000 = 4 remainder 0 let code = [0xf7, 0xf3, 0xf4]; // DIV EBX emu.regs_mut().rax = 0x00000000; - emu.regs_mut().rdx = 0x00000002; // EDX:EAX = 2 * 2^32 = 2^33 - emu.regs_mut().rbx = 0x80000000; // Divisor = 2^31 + emu.regs_mut().rdx = 0x00000002; // EDX:EAX = 2 * 2^32 = 2^33 + emu.regs_mut().rbx = 0x80000000; // Divisor = 2^31 emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/idiv.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/idiv.rs index 3b412345..3e52dbd6 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/idiv.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/idiv.rs @@ -34,10 +34,10 @@ fn test_idiv_al_positive() { let code = [ 0x66, 0x98, // CBW (sign-extend AL to AX) - needs 0x66 in 64-bit mode 0xf6, 0xfb, // IDIV BL (F6 /7) - 0xf4, // HLT + 0xf4, // HLT ]; - emu.regs_mut().rax = 100; // AL = 100 - emu.regs_mut().rbx = 10; // BL = 10 + emu.regs_mut().rax = 100; // AL = 100 + emu.regs_mut().rbx = 10; // BL = 10 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -153,7 +153,7 @@ fn test_idiv_ax_positive() { let mut emu = emu64(); // 1000 / 10 = 100 remainder 0 let code = [ - 0x66, 0x99, // CWD (sign-extend AX to DX:AX) - needs 0x66 in 64-bit mode + 0x66, 0x99, // CWD (sign-extend AX to DX:AX) - needs 0x66 in 64-bit mode 0x66, 0xf7, 0xfb, // IDIV BX (66 F7 /7) 0xf4, ]; @@ -172,7 +172,7 @@ fn test_idiv_ax_negative_dividend() { let mut emu = emu64(); // -1000 / 10 = -100 remainder 0 let code = [ - 0x66, 0x99, // CWD (needs 0x66 in 64-bit mode) + 0x66, 0x99, // CWD (needs 0x66 in 64-bit mode) 0x66, 0xf7, 0xfb, // IDIV BX 0xf4, ]; @@ -191,7 +191,7 @@ fn test_idiv_ax_with_remainder() { let mut emu = emu64(); // 1000 / 7 = 142 remainder 6 let code = [ - 0x66, 0x99, // CWD (needs 0x66 in 64-bit mode) + 0x66, 0x99, // CWD (needs 0x66 in 64-bit mode) 0x66, 0xf7, 0xfb, // IDIV BX 0xf4, ]; @@ -215,7 +215,7 @@ fn test_idiv_eax_positive() { // 1000000 / 1000 = 1000 remainder 0 // CDQ (0x99) sign-extends EAX into EDX (in 32-bit context) let code = [ - 0x99, // CDQ (sign-extend EAX to EDX:EAX in 32-bit mode) + 0x99, // CDQ (sign-extend EAX to EDX:EAX in 32-bit mode) 0xf7, 0xfb, // IDIV EBX (F7 /7) 0xf4, ]; @@ -234,7 +234,7 @@ fn test_idiv_eax_negative_dividend() { let mut emu = emu64(); // -1000000 / 1000 = -1000 remainder 0 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -253,7 +253,7 @@ fn test_idiv_eax_negative_divisor() { let mut emu = emu64(); // 1000000 / -1000 = -1000 remainder 0 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -272,7 +272,7 @@ fn test_idiv_eax_both_negative() { let mut emu = emu64(); // -1000000 / -1000 = 1000 remainder 0 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -291,7 +291,7 @@ fn test_idiv_eax_with_remainder() { let mut emu = emu64(); // 1000000 / 7 = 142857 remainder 1 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -310,7 +310,7 @@ fn test_idiv_eax_negative_dividend_remainder() { let mut emu = emu64(); // -1000000 / 7 = -142857 remainder -1 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -336,7 +336,7 @@ fn test_idiv_rax_positive() { // 1000000000000 / 1000000 = 1000000 remainder 0 // CQO (0x48 0x99) sign-extends RAX into RDX let code = [ - 0x48, 0x99, // CQO (sign-extend RAX to RDX:RAX) + 0x48, 0x99, // CQO (sign-extend RAX to RDX:RAX) 0x48, 0xf7, 0xfb, // IDIV RBX (REX.W F7 /7) 0xf4, ]; @@ -355,7 +355,7 @@ fn test_idiv_rax_negative_dividend() { let mut emu = emu64(); // -1000000000000 / 1000000 = -1000000 remainder 0 let code = [ - 0x48, 0x99, // CQO + 0x48, 0x99, // CQO 0x48, 0xf7, 0xfb, // IDIV RBX 0xf4, ]; @@ -374,7 +374,7 @@ fn test_idiv_rax_negative_divisor() { let mut emu = emu64(); // 1000000000000 / -1000000 = -1000000 remainder 0 let code = [ - 0x48, 0x99, // CQO + 0x48, 0x99, // CQO 0x48, 0xf7, 0xfb, // IDIV RBX 0xf4, ]; @@ -393,7 +393,7 @@ fn test_idiv_rax_both_negative() { let mut emu = emu64(); // -1000000000000 / -1000000 = 1000000 remainder 0 let code = [ - 0x48, 0x99, // CQO + 0x48, 0x99, // CQO 0x48, 0xf7, 0xfb, // IDIV RBX 0xf4, ]; @@ -412,7 +412,7 @@ fn test_idiv_rax_with_remainder() { let mut emu = emu64(); // 1000000000000 / 7 = 142857142857 remainder 1 let code = [ - 0x48, 0x99, // CQO + 0x48, 0x99, // CQO 0x48, 0xf7, 0xfb, // IDIV RBX 0xf4, ]; @@ -431,7 +431,7 @@ fn test_idiv_rax_negative_dividend_remainder() { let mut emu = emu64(); // -1000000000000 / 7 = -142857142857 remainder -1 let code = [ - 0x48, 0x99, // CQO + 0x48, 0x99, // CQO 0x48, 0xf7, 0xfb, // IDIV RBX 0xf4, ]; @@ -475,7 +475,7 @@ fn test_idiv_ecx_32bit() { let mut emu = emu64(); // IDIV ECX (32-bit) let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xf9, // IDIV ECX 0xf4, ]; @@ -514,7 +514,7 @@ fn test_idiv_r10d() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x99, // CDQ + 0x99, // CDQ 0x41, 0xf7, 0xfa, // IDIV R10D 0xf4, ]; @@ -531,7 +531,7 @@ fn test_idiv_r15() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x48, 0x99, // CQO + 0x48, 0x99, // CQO 0x49, 0xf7, 0xff, // IDIV R15 0xf4, ]; @@ -553,7 +553,8 @@ fn test_idiv_byte_ptr_mem() { let mut emu = emu64(); let code = [ 0x66, 0x98, // CBW (needs 0x66 in 64-bit mode) - 0xf6, 0x3d, 0xf8, 0x0f, 0x00, 0x00, // IDIV BYTE PTR [rip+0x0FF8] (DATA_ADDR=0x2000, RIP after=0x1008) + 0xf6, 0x3d, 0xf8, 0x0f, 0x00, + 0x00, // IDIV BYTE PTR [rip+0x0FF8] (DATA_ADDR=0x2000, RIP after=0x1008) 0xf4, ]; emu.load_code_bytes(&code); @@ -571,8 +572,9 @@ fn test_idiv_dword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x99, // CDQ - 0xf7, 0x3d, 0xf9, 0x0f, 0x00, 0x00, // IDIV DWORD PTR [rip+0x0FF9] (DATA_ADDR=0x2000, RIP after=0x1007) + 0x99, // CDQ + 0xf7, 0x3d, 0xf9, 0x0f, 0x00, + 0x00, // IDIV DWORD PTR [rip+0x0FF9] (DATA_ADDR=0x2000, RIP after=0x1007) 0xf4, ]; emu.load_code_bytes(&code); @@ -591,8 +593,9 @@ fn test_idiv_qword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x48, 0x99, // CQO - 0x48, 0xf7, 0x3d, 0xf7, 0x0f, 0x00, 0x00, // IDIV QWORD PTR [rip+0x0FF7] (DATA_ADDR=0x2000, RIP after=0x1009) + 0x48, 0x99, // CQO + 0x48, 0xf7, 0x3d, 0xf7, 0x0f, 0x00, + 0x00, // IDIV QWORD PTR [rip+0x0FF7] (DATA_ADDR=0x2000, RIP after=0x1009) 0xf4, ]; emu.load_code_bytes(&code); @@ -615,7 +618,7 @@ fn test_idiv_small_dividend() { let mut emu = emu64(); // 5 / 10 = 0 remainder 5 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -634,7 +637,7 @@ fn test_idiv_negative_small_dividend() { let mut emu = emu64(); // -5 / 10 = 0 remainder -5 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -655,7 +658,7 @@ fn test_idiv_power_of_two() { let mut emu = emu64(); // 1024 / 256 = 4 remainder 0 let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; @@ -674,7 +677,7 @@ fn test_idiv_max_positive() { let mut emu = emu64(); // 0x7FFFFFFF / 1 = 0x7FFFFFFF remainder 0 (max i32) let code = [ - 0x99, // CDQ + 0x99, // CDQ 0xf7, 0xfb, // IDIV EBX 0xf4, ]; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/imul.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/imul.rs index 9ec274f9..f736645c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/imul.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/imul.rs @@ -35,7 +35,7 @@ fn test_imul_al_positive_basic() { let mut emu = emu64(); let code = [ 0xf6, 0xeb, // IMUL BL (F6 /5, ModRM=11_101_011) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x05; // AL = 5 emu.regs_mut().rbx = 0x03; // BL = 3 @@ -59,7 +59,10 @@ fn test_imul_al_negative_by_positive() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0xFFF1, "-5 * 3 = -15 (0xFFF1)"); - assert!(!emu.flags().f_cf, "CF should be clear (fits in sign-extended AL)"); + assert!( + !emu.flags().f_cf, + "CF should be clear (fits in sign-extended AL)" + ); } #[test] @@ -84,12 +87,15 @@ fn test_imul_al_overflow() { // 100 * 2 = 200 (0x00C8), doesn't fit in sign-extended i8 (-128 to 127) let code = [0xf6, 0xeb, 0xf4]; // IMUL BL emu.regs_mut().rax = 100; // AL = 100 - emu.regs_mut().rbx = 2; // BL = 2 + emu.regs_mut().rbx = 2; // BL = 2 emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0x00C8, "100 * 2 = 200"); - assert!(emu.flags().f_cf, "CF should be set (doesn't fit in i8 range)"); + assert!( + emu.flags().f_cf, + "CF should be set (doesn't fit in i8 range)" + ); assert!(emu.flags().f_of, "OF should be set"); } @@ -100,7 +106,7 @@ fn test_imul_al_max_positive() { // 127 * 1 = 127 (fits in i8) let code = [0xf6, 0xeb, 0xf4]; // IMUL BL emu.regs_mut().rax = 127; // AL = 127 (max i8) - emu.regs_mut().rbx = 1; // BL = 1 + emu.regs_mut().rbx = 1; // BL = 1 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -115,7 +121,7 @@ fn test_imul_al_min_negative() { // -128 * 1 = -128 (0xFF80, fits in sign-extended i8) let code = [0xf6, 0xeb, 0xf4]; // IMUL BL emu.regs_mut().rax = 0x80; // AL = -128 (min i8) - emu.regs_mut().rbx = 1; // BL = 1 + emu.regs_mut().rbx = 1; // BL = 1 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -130,7 +136,7 @@ fn test_imul_al_overflow_negative() { // -128 * 2 = -256 (0xFF00), doesn't fit in i8 let code = [0xf6, 0xeb, 0xf4]; // IMUL BL emu.regs_mut().rax = 0x80; // AL = -128 - emu.regs_mut().rbx = 2; // BL = 2 + emu.regs_mut().rbx = 2; // BL = 2 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -165,7 +171,7 @@ fn test_imul_ax_positive_basic() { 0xf4, ]; emu.regs_mut().rax = 100; // AX = 100 - emu.regs_mut().rbx = 50; // BX = 50 + emu.regs_mut().rbx = 50; // BX = 50 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -186,8 +192,15 @@ fn test_imul_ax_negative_by_positive() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0xEC78, "AX (low word)"); - assert_eq!(emu.regs().rdx & 0xFFFF, 0xFFFF, "DX (high word, sign extension)"); - assert!(!emu.flags().f_cf, "CF should be clear (fits in sign-extended)"); + assert_eq!( + emu.regs().rdx & 0xFFFF, + 0xFFFF, + "DX (high word, sign extension)" + ); + assert!( + !emu.flags().f_cf, + "CF should be clear (fits in sign-extended)" + ); } #[test] @@ -255,7 +268,11 @@ fn test_imul_eax_negative_by_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax as i32, -2000000, "EAX: -1000 * 2000 = -2000000"); + assert_eq!( + emu.regs().rax as i32, + -2000000, + "EAX: -1000 * 2000 = -2000000" + ); assert_eq!(emu.regs().rdx, 0xFFFFFFFF, "EDX (sign extension)"); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -374,11 +391,15 @@ fn test_imul_two_op_16bit_basic() { 0xf4, ]; emu.regs_mut().rax = 100; // AX = 100 - emu.regs_mut().rbx = 50; // BX = 50 (will be overwritten with result) + emu.regs_mut().rbx = 50; // BX = 50 (will be overwritten with result) emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 5000, "BX = BX * AX = 50 * 100 = 5000"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 5000, + "BX = BX * AX = 50 * 100 = 5000" + ); assert!(!emu.flags().f_cf, "CF should be clear (no truncation)"); } @@ -393,7 +414,11 @@ fn test_imul_two_op_16bit_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rbx & 0xFFFF) as i16, -5000, "BX = -50 * 100 = -5000"); + assert_eq!( + (emu.regs().rbx & 0xFFFF) as i16, + -5000, + "BX = -50 * 100 = -5000" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -441,7 +466,11 @@ fn test_imul_two_op_32bit_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx as i32, -2000000, "EBX = -1000 * 2000 = -2000000"); + assert_eq!( + emu.regs().rbx as i32, + -2000000, + "EBX = -1000 * 2000 = -2000000" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -519,7 +548,7 @@ fn test_imul_three_op_imm8_basic() { 0xf4, ]; emu.regs_mut().rax = 50; // AX = 50 - emu.regs_mut().rbx = 0; // BX will be set to AX * 10 + emu.regs_mut().rbx = 0; // BX will be set to AX * 10 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -536,7 +565,11 @@ fn test_imul_three_op_imm8_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rbx & 0xFFFF) as i16, -500, "BX = 100 * -5 = -500"); + assert_eq!( + (emu.regs().rbx & 0xFFFF) as i16, + -500, + "BX = 100 * -5 = -500" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -617,7 +650,11 @@ fn test_imul_three_op_imm32_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx as i32, -2000000, "EBX = 2000 * -1000 = -2000000"); + assert_eq!( + emu.regs().rbx as i32, + -2000000, + "EBX = 2000 * -1000 = -2000000" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -664,7 +701,7 @@ fn test_imul_r8_one_operand() { 0xf4, ]; emu.regs_mut().rax = 20; // AL = 20 - emu.regs_mut().r8 = 5; // R8B = 5 + emu.regs_mut().r8 = 5; // R8B = 5 emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/inc_dec.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/inc_dec.rs index e5bb9e6c..02d36677 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/inc_dec.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/inc_dec.rs @@ -90,7 +90,11 @@ fn test_inc_al_memory() { emu.maps.write_byte(DATA_ADDR, 42); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 43, "INC [RBX]: 42 + 1 = 43"); + assert_eq!( + emu.maps.read_byte(DATA_ADDR).unwrap(), + 43, + "INC [RBX]: 42 + 1 = 43" + ); } // ============================================================================ @@ -165,7 +169,11 @@ fn test_dec_al_memory() { emu.maps.write_byte(DATA_ADDR, 42); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 41, "DEC [RBX]: 42 - 1 = 41"); + assert_eq!( + emu.maps.read_byte(DATA_ADDR).unwrap(), + 41, + "DEC [RBX]: 42 - 1 = 41" + ); } // ============================================================================ @@ -181,7 +189,11 @@ fn test_inc_ax_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1235, "INC AX: 0x1234 + 1 = 0x1235"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1235, + "INC AX: 0x1234 + 1 = 0x1235" + ); } #[test] @@ -226,7 +238,11 @@ fn test_dec_ax_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1233, "DEC AX: 0x1234 - 1 = 0x1233"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1233, + "DEC AX: 0x1234 - 1 = 0x1233" + ); } #[test] @@ -239,7 +255,11 @@ fn test_dec_ax_underflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xFFFF, "DEC AX: 0x0000 - 1 = 0xFFFF"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xFFFF, + "DEC AX: 0x0000 - 1 = 0xFFFF" + ); assert!(emu.flags().f_sf, "SF should be set"); } @@ -343,7 +363,11 @@ fn test_dec_eax_underflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFF, "DEC EAX: 0x00000000 - 1 = 0xFFFFFFFF"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFF, + "DEC EAX: 0x00000000 - 1 = 0xFFFFFFFF" + ); assert!(emu.flags().f_sf, "SF should be set"); } @@ -755,7 +779,7 @@ fn test_inc_as_loop_counter() { 0xff, 0xc0, // INC EAX 0xff, 0xc0, // INC EAX 0xff, 0xc0, // INC EAX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0; emu.load_code_bytes(&code); @@ -772,7 +796,7 @@ fn test_dec_as_loop_counter() { 0xff, 0xc8, // DEC EAX 0xff, 0xc8, // DEC EAX 0xff, 0xc8, // DEC EAX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 5; emu.load_code_bytes(&code); @@ -791,7 +815,11 @@ fn test_inc_preserves_high_bytes() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x79); - assert_eq!(emu.regs().rax & !0xFF, 0xDEADBEEF_12345600, "High bytes should be preserved"); + assert_eq!( + emu.regs().rax & !0xFF, + 0xDEADBEEF_12345600, + "High bytes should be preserved" + ); } #[test] @@ -804,5 +832,9 @@ fn test_dec_preserves_high_bytes() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x77); - assert_eq!(emu.regs().rax & !0xFF, 0xDEADBEEF_12345600, "High bytes should be preserved"); + assert_eq!( + emu.regs().rax & !0xFF, + 0xDEADBEEF_12345600, + "High bytes should be preserved" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mod.rs index 47996eb3..f91979d2 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mod.rs @@ -18,19 +18,19 @@ // - SUB (Integer Subtraction) // - CMP (Compare Two Operands) -pub mod neg; -pub mod inc_dec; -pub mod imul; -pub mod mul; -pub mod div; -pub mod idiv; -pub mod adcx_adox; -pub mod bcd; pub mod aaa_aas; pub mod aam_aad; -pub mod daa_das; pub mod adc_extended; -pub mod sbb_extended; +pub mod adcx_adox; pub mod add_extended; -pub mod sub_extended; +pub mod bcd; pub mod cmp_extended; +pub mod daa_das; +pub mod div; +pub mod idiv; +pub mod imul; +pub mod inc_dec; +pub mod mul; +pub mod neg; +pub mod sbb_extended; +pub mod sub_extended; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mul.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mul.rs index ba203860..c76cc657 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mul.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/mul.rs @@ -28,10 +28,10 @@ fn test_mul_al_small() { let mut emu = emu64(); let code = [ 0xf6, 0xe3, // MUL BL (F6 /4, ModRM=11_100_011) - 0xf4, // HLT + 0xf4, // HLT ]; - emu.regs_mut().rax = 5; // AL = 5 - emu.regs_mut().rbx = 3; // BL = 3 + emu.regs_mut().rax = 5; // AL = 5 + emu.regs_mut().rbx = 3; // BL = 3 emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -51,7 +51,11 @@ fn test_mul_al_max() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xFE01, "255 * 255 = 65025 (0xFE01)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xFE01, + "255 * 255 = 65025 (0xFE01)" + ); assert!(emu.flags().f_cf, "CF should be set (result in AH)"); assert!(emu.flags().f_of, "OF should be set"); } @@ -552,7 +556,6 @@ fn test_mul_vs_imul_unsigned() { assert_eq!(emu1.regs().rax, 20000, "Product is 20000"); } - // ============================================================================ // Edge cases // ============================================================================ diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/neg.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/neg.rs index e839609b..f934ef3f 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/neg.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/neg.rs @@ -28,13 +28,17 @@ fn test_neg_al_positive() { let mut emu = emu64(); let code = [ 0xf6, 0xd8, // NEG AL (F6 /3, ModRM=11_011_000) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x42; // 66 emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xBE, "NEG 0x42 (66) = 0xBE (-66 in two's complement)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xBE, + "NEG 0x42 (66) = 0xBE (-66 in two's complement)" + ); assert!(emu.flags().f_cf, "CF should be set (operand was non-zero)"); assert!(emu.flags().f_sf, "SF should be set (negative result)"); assert!(!emu.flags().f_zf, "ZF should be clear"); @@ -49,7 +53,11 @@ fn test_neg_al_one() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xFF, "NEG 1 = 0xFF (-1 in two's complement)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xFF, + "NEG 1 = 0xFF (-1 in two's complement)" + ); assert!(emu.flags().f_cf, "CF should be set"); assert!(emu.flags().f_sf, "SF should be set"); } @@ -95,7 +103,11 @@ fn test_neg_al_signed_overflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x80, "NEG 0x80 (-128) = 0x80 (overflow)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x80, + "NEG 0x80 (-128) = 0x80 (overflow)" + ); assert!(emu.flags().f_cf, "CF should be set (non-zero operand)"); assert!(emu.flags().f_of, "OF should be set (signed overflow)"); assert!(emu.flags().f_sf, "SF should be set"); @@ -155,7 +167,11 @@ fn test_neg_preserves_high_bytes_8bit() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x88, "AL: NEG 0x78 = 0x88"); - assert_eq!(emu.regs().rax & !0xFF, 0xDEADBEEF_12345600, "High bytes preserved"); + assert_eq!( + emu.regs().rax & !0xFF, + 0xDEADBEEF_12345600, + "High bytes preserved" + ); } // ============================================================================ @@ -203,7 +219,11 @@ fn test_neg_ax_signed_overflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "NEG 0x8000 = 0x8000 (overflow)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "NEG 0x8000 = 0x8000 (overflow)" + ); assert!(emu.flags().f_of, "OF should be set"); assert!(emu.flags().f_cf, "CF should be set"); } @@ -244,7 +264,11 @@ fn test_neg_preserves_high_bytes_16bit() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0xA988, "AX: NEG 0x5678"); - assert_eq!(emu.regs().rax & !0xFFFF, 0xDEADBEEF_12340000, "Upper bits preserved"); + assert_eq!( + emu.regs().rax & !0xFFFF, + 0xDEADBEEF_12340000, + "Upper bits preserved" + ); } // ============================================================================ @@ -292,7 +316,11 @@ fn test_neg_eax_signed_overflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x80000000, "NEG 0x80000000 = 0x80000000 (overflow)"); + assert_eq!( + emu.regs().rax, + 0x80000000, + "NEG 0x80000000 = 0x80000000 (overflow)" + ); assert!(emu.flags().f_of, "OF should be set"); assert!(emu.flags().f_cf, "CF should be set"); } @@ -393,7 +421,11 @@ fn test_neg_rax_signed_overflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000000000000000, "NEG 0x8000...000 = overflow"); + assert_eq!( + emu.regs().rax, + 0x8000000000000000, + "NEG 0x8000...000 = overflow" + ); assert!(emu.flags().f_of, "OF should be set"); assert!(emu.flags().f_cf, "CF should be set"); } @@ -693,7 +725,7 @@ fn test_neg_double_negation() { let code = [ 0xf6, 0xd8, // NEG AL (first time) 0xf6, 0xd8, // NEG AL (second time) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x42; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sbb_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sbb_extended.rs index aebfada6..3bf3d842 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sbb_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sbb_extended.rs @@ -38,7 +38,7 @@ fn test_sbb_al_imm8_no_borrow() { // SBB AL, 5 with CF=0 let code = [ 0x1C, 0x05, // SBB AL, 5 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0F; emu.load_code_bytes(&code); @@ -87,7 +87,7 @@ fn test_sbb_r8_r8_no_borrow() { // SBB AL, BL with CF=0 let code = [ 0x18, 0xd8, // SBB AL, BL (ModRM: 11_011_000) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x30; emu.regs_mut().rbx = 0x10; @@ -109,7 +109,11 @@ fn test_sbb_r8_r8_with_borrow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x7E, "AL should be 0x7E (128 - 1 - 1)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x7E, + "AL should be 0x7E (128 - 1 - 1)" + ); assert!(!emu.flags().f_sf, "SF should be clear (positive result)"); assert!(emu.flags().f_of, "OF should be set (signed overflow)"); } @@ -119,9 +123,9 @@ fn test_sbb_all_8bit_registers() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (0xd8, "BL"), // SBB AL, BL - (0xc8, "CL"), // SBB AL, CL - (0xd0, "DL"), // SBB AL, DL + (0xd8, "BL"), // SBB AL, BL + (0xc8, "CL"), // SBB AL, CL + (0xd0, "DL"), // SBB AL, DL ]; for (modrm, _name) in test_cases { @@ -132,7 +136,7 @@ fn test_sbb_all_8bit_registers() { emu.regs_mut().rdx = 0x07; emu.flags_mut().load(0x01); // Set CF emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // Result should include borrow assert!((emu.regs().rax & 0xFF) < 0x20, "SBB should subtract borrow"); @@ -146,7 +150,7 @@ fn test_sbb_extended_r8_registers() { // SBB R8B, R9B with CF=1 let code = [ 0x45, 0x18, 0xc8, // SBB R8B, R9B (REX.RB + 18 /r) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r8 = 0x50; emu.regs_mut().r9 = 0x20; @@ -154,7 +158,11 @@ fn test_sbb_extended_r8_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFF, 0x2F, "R8B should be 0x2F (80 - 32 - 1)"); + assert_eq!( + emu.regs().r8 & 0xFF, + 0x2F, + "R8B should be 0x2F (80 - 32 - 1)" + ); } // ============================================================================ @@ -168,7 +176,7 @@ fn test_sbb_ax_imm16_no_borrow() { // SBB AX, 0x1234 with CF=0 let code = [ 0x66, 0x1D, 0x34, 0x12, // SBB AX, 0x1234 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x5678; emu.load_code_bytes(&code); @@ -201,7 +209,7 @@ fn test_sbb_r16_r16() { // SBB AX, BX with CF=1 let code = [ 0x66, 0x19, 0xd8, // SBB AX, BX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x3000; emu.regs_mut().rbx = 0x1000; @@ -219,7 +227,7 @@ fn test_sbb_r16_imm8_sign_extended() { // SBB AX, -1 (sign-extended from imm8) let code = [ 0x66, 0x83, 0xd8, 0xFF, // SBB AX, -1 (sign-extended) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1000; emu.load_code_bytes(&code); @@ -236,7 +244,7 @@ fn test_sbb_extended_r16_registers() { // SBB R10W, R11W with CF=1 let code = [ 0x66, 0x45, 0x19, 0xda, // SBB R10W, R11W - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r10 = 0x8000; emu.regs_mut().r11 = 0x7FFF; @@ -258,7 +266,7 @@ fn test_sbb_eax_imm32_no_borrow() { // SBB EAX, 0x12345678 with CF=0 let code = [ 0x1D, 0x78, 0x56, 0x34, 0x12, // SBB EAX, 0x12345678 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x23456789; emu.load_code_bytes(&code); @@ -291,7 +299,7 @@ fn test_sbb_r32_r32() { // SBB EAX, EBX with CF=1 let code = [ 0x19, 0xd8, // SBB EAX, EBX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x80000000; emu.regs_mut().rbx = 0x7FFFFFFF; @@ -310,7 +318,7 @@ fn test_sbb_r32_imm8_sign_extended() { // SBB EAX, -1 (sign-extended from imm8) let code = [ 0x83, 0xd8, 0xFF, // SBB EAX, -1 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x10000000; emu.load_code_bytes(&code); @@ -326,7 +334,7 @@ fn test_sbb_extended_r32_registers() { // SBB R12D, R13D with CF=1 let code = [ 0x45, 0x19, 0xec, // SBB R12D, R13D - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r12 = 0x00000001; emu.regs_mut().r13 = 0x00000001; @@ -349,7 +357,7 @@ fn test_sbb_rax_imm32_no_borrow() { // SBB RAX, 0x12345678 (sign-extended to 64-bit) let code = [ 0x48, 0x1D, 0x78, 0x56, 0x34, 0x12, // SBB RAX, 0x12345678 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1111111123456789; emu.load_code_bytes(&code); @@ -370,7 +378,11 @@ fn test_sbb_rax_imm32_with_borrow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX should wrap to max u64"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX should wrap to max u64" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -381,7 +393,7 @@ fn test_sbb_r64_r64() { // SBB RAX, RBX with CF=1 let code = [ 0x48, 0x19, 0xd8, // SBB RAX, RBX - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x8000000000000000; emu.regs_mut().rbx = 0x7FFFFFFFFFFFFFFF; @@ -399,13 +411,17 @@ fn test_sbb_r64_imm8_sign_extended() { // SBB RAX, -1 (sign-extended from imm8) let code = [ 0x48, 0x83, 0xd8, 0xFF, // SBB RAX, -1 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x1000000000000000; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x1000000000000001, "RAX should be incremented"); + assert_eq!( + emu.regs().rax, + 0x1000000000000001, + "RAX should be incremented" + ); } #[test] @@ -415,7 +431,7 @@ fn test_sbb_extended_r64_registers() { // SBB R14, R15 with CF=1 let code = [ 0x4d, 0x19, 0xfe, // SBB R14, R15 - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().r14 = 0x0000000000000001; emu.regs_mut().r15 = 0x0000000000000001; @@ -438,7 +454,7 @@ fn test_sbb_byte_ptr_imm8() { // SBB BYTE PTR [mem], 0x10 with CF=1 let code = [ 0x80, 0x1D, 0xF9, 0x0F, 0x00, 0x00, 0x10, // SBB BYTE PTR [rip+0x0FF9], 0x10 - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_byte(DATA_ADDR, 0x30); @@ -457,8 +473,9 @@ fn test_sbb_word_ptr_imm16() { let mut emu = emu64(); // SBB WORD PTR [mem], 0x1000 with CF=1 let code = [ - 0x66, 0x81, 0x1D, 0xF7, 0x0F, 0x00, 0x00, 0x00, 0x10, // SBB WORD PTR [rip+0x0FF7], 0x1000 - 0xf4, // HLT + 0x66, 0x81, 0x1D, 0xF7, 0x0F, 0x00, 0x00, 0x00, + 0x10, // SBB WORD PTR [rip+0x0FF7], 0x1000 + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, 0x2000); @@ -477,7 +494,7 @@ fn test_sbb_dword_ptr_r32() { // SBB DWORD PTR [mem], EBX with CF=1 let code = [ 0x19, 0x1d, 0xFA, 0x0F, 0x00, 0x00, // SBB DWORD PTR [rip+0x0FF7], EBX - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, 0x80000000); @@ -497,7 +514,7 @@ fn test_sbb_qword_ptr_r64() { // SBB QWORD PTR [mem], RBX with CF=1 let code = [ 0x48, 0x19, 0x1d, 0xF9, 0x0F, 0x00, 0x00, // SBB QWORD PTR [rip+0x0FF6], RBX - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x3000000000000000); @@ -517,7 +534,7 @@ fn test_sbb_r64_from_memory() { // SBB RAX, QWORD PTR [mem] with CF=1 let code = [ 0x48, 0x1B, 0x05, 0xF9, 0x0F, 0x00, 0x00, // SBB RAX, QWORD PTR [rip+0x0FF6] - 0xf4, // HLT + 0xf4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x1000000000000000); @@ -526,7 +543,11 @@ fn test_sbb_r64_from_memory() { emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0FFFFFFFFFFFFFFF, "RAX should be correct difference"); + assert_eq!( + emu.regs().rax, + 0x0FFFFFFFFFFFFFFF, + "RAX should be correct difference" + ); } // ============================================================================ @@ -618,17 +639,25 @@ fn test_sbb_chain_128bit_subtraction() { let code = [ 0x48, 0x29, 0xd8, // SUB RAX, RBX (low 64 bits) 0x49, 0x19, 0xc8, // SBB R8, RCX (high 64 bits, with borrow) - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0x0000000000000000; // Low 64 bits of first number - emu.regs_mut().r8 = 0x0000000000000002; // High 64 bits of first number + emu.regs_mut().r8 = 0x0000000000000002; // High 64 bits of first number emu.regs_mut().rbx = 0x0000000000000001; // Low 64 bits of second number emu.regs_mut().rcx = 0x0000000000000001; // High 64 bits of second number emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "Low 64 bits should be max u64"); - assert_eq!(emu.regs().r8, 0x0000000000000000, "High 64 bits should be 0 (with borrow)"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "Low 64 bits should be max u64" + ); + assert_eq!( + emu.regs().r8, + 0x0000000000000000, + "High 64 bits should be 0 (with borrow)" + ); } #[test] @@ -640,7 +669,11 @@ fn test_sbb_preserves_high_bits_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0xDEADBEEF123456, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0xDEADBEEF123456, + "High bits should be preserved" + ); } #[test] @@ -652,7 +685,11 @@ fn test_sbb_preserves_high_bits_16bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 16, 0xDEADBEEF1234, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 16, + 0xDEADBEEF1234, + "High bits should be preserved" + ); } #[test] @@ -665,7 +702,11 @@ fn test_sbb_preserves_high_bits_32bit() { emu.run(None).unwrap(); // EAX operation zeros high 32 bits - assert_eq!(emu.regs().rax >> 32, 0, "High 32 bits should be zeroed for 32-bit op"); + assert_eq!( + emu.regs().rax >> 32, + 0, + "High 32 bits should be zeroed for 32-bit op" + ); } // ============================================================================ diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sub_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sub_extended.rs index 516d8681..86814750 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sub_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/arithmetic/sub_extended.rs @@ -118,7 +118,7 @@ fn test_sub_all_8bit_registers() { } emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = match reg_num { 8 => emu.regs().r8, @@ -132,7 +132,13 @@ fn test_sub_all_8bit_registers() { _ => unreachable!(), }; - assert_eq!(result & 0xFF, 0x00, "R{} - R{} should be 0", reg_num, reg_num); + assert_eq!( + result & 0xFF, + 0x00, + "R{} - R{} should be 0", + reg_num, + reg_num + ); } } @@ -295,7 +301,11 @@ fn test_sub_rax_underflow() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX should wrap to max u64"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX should wrap to max u64" + ); assert!(emu.flags().f_cf, "CF should be set"); } @@ -321,7 +331,11 @@ fn test_sub_r64_imm8_sign_extended() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x1000000000000001, "RAX should be incremented"); + assert_eq!( + emu.regs().rax, + 0x1000000000000001, + "RAX should be incremented" + ); } #[test] @@ -512,7 +526,11 @@ fn test_sub_preserves_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax >> 8, 0xDEADBEEF123456, "High bits should be preserved"); + assert_eq!( + emu.regs().rax >> 8, + 0xDEADBEEF123456, + "High bits should be preserved" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/common/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/common/mod.rs index cad7e38c..a21bc10a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/common/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/common/mod.rs @@ -26,7 +26,6 @@ pub const IDT_BASE: u64 = 0x11000; /// GDT base address pub const GDT_BASE: u64 = 0x10000; - /// Create a test CPU with the given code. /// This is a convenience wrapper for tests that prefer the TestCpu API. /* @@ -60,9 +59,7 @@ impl TestCase { .split_whitespace() .filter_map(|s| u8::from_str_radix(s, 16).ok()) .collect(); - Self { - code - } + Self { code } } /// Run the test - just check if code executes without panic @@ -74,5 +71,3 @@ impl TestCase { emu.run(None).unwrap(); } } - - diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/f2xm1.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/f2xm1.rs index a1d2234b..f6bc28f1 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/f2xm1.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/f2xm1.rs @@ -24,12 +24,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -40,12 +42,12 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_f2xm1_zero() { - let mut emu = emu64(); // 2^0 - 1 = 1 - 1 = 0 + let mut emu = emu64(); // 2^0 - 1 = 1 - 1 = 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -59,11 +61,12 @@ fn test_f2xm1_zero() { #[test] fn test_f2xm1_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -78,12 +81,12 @@ fn test_f2xm1_positive_zero() { #[test] fn test_f2xm1_negative_zero() { - let mut emu = emu64(); // 2^(-0) - 1 = 1 - 1 = -0 + let mut emu = emu64(); // 2^(-0) - 1 = 1 - 1 = -0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -102,12 +105,12 @@ fn test_f2xm1_negative_zero() { #[test] fn test_f2xm1_one() { - let mut emu = emu64(); // 2^1 - 1 = 2 - 1 = 1 + let mut emu = emu64(); // 2^1 - 1 = 2 - 1 = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -125,12 +128,12 @@ fn test_f2xm1_one() { #[test] fn test_f2xm1_half() { - let mut emu = emu64(); // 2^0.5 - 1 = sqrt(2) - 1 ≈ 0.414 + let mut emu = emu64(); // 2^0.5 - 1 = sqrt(2) - 1 ≈ 0.414 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -140,17 +143,20 @@ fn test_f2xm1_half() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(0.5) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^0.5 - 1 should be approximately 0.414"); + assert!( + (result - expected).abs() < 1e-10, + "2^0.5 - 1 should be approximately 0.414" + ); } #[test] fn test_f2xm1_quarter() { - let mut emu = emu64(); // 2^0.25 - 1 + let mut emu = emu64(); // 2^0.25 - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -165,12 +171,12 @@ fn test_f2xm1_quarter() { #[test] fn test_f2xm1_three_quarters() { - let mut emu = emu64(); // 2^0.75 - 1 + let mut emu = emu64(); // 2^0.75 - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -185,12 +191,12 @@ fn test_f2xm1_three_quarters() { #[test] fn test_f2xm1_small_positive() { - let mut emu = emu64(); // 2^0.1 - 1 + let mut emu = emu64(); // 2^0.1 - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -205,12 +211,12 @@ fn test_f2xm1_small_positive() { #[test] fn test_f2xm1_very_small_positive() { - let mut emu = emu64(); // 2^0.01 - 1 + let mut emu = emu64(); // 2^0.01 - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -229,12 +235,12 @@ fn test_f2xm1_very_small_positive() { #[test] fn test_f2xm1_negative_one() { - let mut emu = emu64(); // 2^(-1) - 1 = 0.5 - 1 = -0.5 + let mut emu = emu64(); // 2^(-1) - 1 = 0.5 - 1 = -0.5 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -248,12 +254,12 @@ fn test_f2xm1_negative_one() { #[test] fn test_f2xm1_negative_half() { - let mut emu = emu64(); // 2^(-0.5) - 1 = 1/sqrt(2) - 1 ≈ -0.293 + let mut emu = emu64(); // 2^(-0.5) - 1 = 1/sqrt(2) - 1 ≈ -0.293 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -263,17 +269,20 @@ fn test_f2xm1_negative_half() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(-0.5) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^(-0.5) - 1 calculation"); + assert!( + (result - expected).abs() < 1e-10, + "2^(-0.5) - 1 calculation" + ); } #[test] fn test_f2xm1_negative_quarter() { - let mut emu = emu64(); // 2^(-0.25) - 1 + let mut emu = emu64(); // 2^(-0.25) - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -283,17 +292,20 @@ fn test_f2xm1_negative_quarter() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(-0.25) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^(-0.25) - 1 calculation"); + assert!( + (result - expected).abs() < 1e-10, + "2^(-0.25) - 1 calculation" + ); } #[test] fn test_f2xm1_small_negative() { - let mut emu = emu64(); // 2^(-0.1) - 1 + let mut emu = emu64(); // 2^(-0.1) - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -303,17 +315,20 @@ fn test_f2xm1_small_negative() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(-0.1) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^(-0.1) - 1 calculation"); + assert!( + (result - expected).abs() < 1e-10, + "2^(-0.1) - 1 calculation" + ); } #[test] fn test_f2xm1_very_small_negative() { - let mut emu = emu64(); // 2^(-0.01) - 1 + let mut emu = emu64(); // 2^(-0.01) - 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -323,7 +338,10 @@ fn test_f2xm1_very_small_negative() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(-0.01) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^(-0.01) - 1 calculation"); + assert!( + (result - expected).abs() < 1e-10, + "2^(-0.01) - 1 calculation" + ); } // ============================================================================ @@ -332,11 +350,12 @@ fn test_f2xm1_very_small_negative() { #[test] fn test_f2xm1_upper_limit() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -346,16 +365,20 @@ fn test_f2xm1_upper_limit() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(1.0) - 1.0; - assert!((result - expected).abs() < 1e-10, "Upper limit: 2^1 - 1 = 1.0"); + assert!( + (result - expected).abs() < 1e-10, + "Upper limit: 2^1 - 1 = 1.0" + ); } #[test] fn test_f2xm1_lower_limit() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -365,16 +388,20 @@ fn test_f2xm1_lower_limit() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(-1.0) - 1.0; - assert!((result - expected).abs() < 1e-10, "Lower limit: 2^(-1) - 1 = -0.5"); + assert!( + (result - expected).abs() < 1e-10, + "Lower limit: 2^(-1) - 1 = -0.5" + ); } #[test] fn test_f2xm1_near_upper_limit() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -389,11 +416,12 @@ fn test_f2xm1_near_upper_limit() { #[test] fn test_f2xm1_near_lower_limit() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -403,7 +431,10 @@ fn test_f2xm1_near_lower_limit() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(-0.99) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^(-0.99) - 1 calculation"); + assert!( + (result - expected).abs() < 1e-10, + "2^(-0.99) - 1 calculation" + ); } // ============================================================================ @@ -412,54 +443,53 @@ fn test_f2xm1_near_lower_limit() { #[test] fn test_f2xm1_various_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; - let test_values = vec![ - -0.9, -0.75, -0.5, -0.25, -0.1, - 0.1, 0.25, 0.5, 0.75, 0.9, - ]; + let test_values = vec![-0.9, -0.75, -0.5, -0.25, -0.1, 0.1, 0.25, 0.5, 0.75, 0.9]; for val in test_values { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(val) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^{} - 1 should match", val); + assert!( + (result - expected).abs() < 1e-10, + "2^{} - 1 should match", + val + ); } } #[test] fn test_f2xm1_symmetric_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; - let test_pairs = vec![ - (0.5, -0.5), - (0.25, -0.25), - (0.75, -0.75), - ]; + let test_pairs = vec![(0.5, -0.5), (0.25, -0.25), (0.75, -0.75)]; for (pos, neg) in test_pairs { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, pos); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result_pos = emu.maps.read_f64(0x3000).unwrap(); emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, neg); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result_neg = emu.maps.read_f64(0x3000).unwrap(); let expected_pos = 2.0f64.powf(pos) - 1.0; @@ -476,14 +506,15 @@ fn test_f2xm1_symmetric_values() { #[test] fn test_f2xm1_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -507,11 +538,12 @@ fn test_f2xm1_sequence() { #[test] fn test_f2xm1_tiny_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -526,11 +558,12 @@ fn test_f2xm1_tiny_value() { #[test] fn test_f2xm1_precision_boundary() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![0.125, 0.375, 0.625, 0.875]; @@ -539,7 +572,7 @@ fn test_f2xm1_precision_boundary() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(val) - 1.0; @@ -549,11 +582,12 @@ fn test_f2xm1_precision_boundary() { #[test] fn test_f2xm1_fractional_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF0, // F2XM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF0, // F2XM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![0.2, 0.3, 0.4, 0.6, 0.7, 0.8]; @@ -562,10 +596,14 @@ fn test_f2xm1_fractional_precision() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0f64.powf(val) - 1.0; - assert!((result - expected).abs() < 1e-10, "2^{} - 1 should match", val); + assert!( + (result - expected).abs() < 1e-10, + "2^{} - 1 should match", + val + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fabs.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fabs.rs index 60f2b4a1..56ede02f 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fabs.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fabs.rs @@ -18,12 +18,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -34,15 +36,15 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fabs_positive_small() { - let mut emu = emu64(); // FLD qword [0x2000] ; D9 05 00 20 00 00 (load from address 0x2000) - // FABS ; D9 E1 - // FSTP qword [0x3000] ; DD 1D 00 30 00 00 (store to address 0x3000) - // HLT ; F4 + let mut emu = emu64(); // FLD qword [0x2000] ; D9 05 00 20 00 00 (load from address 0x2000) + // FABS ; D9 E1 + // FSTP qword [0x3000] ; DD 1D 00 30 00 00 (store to address 0x3000) + // HLT ; F4 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -56,11 +58,12 @@ fn test_fabs_positive_small() { #[test] fn test_fabs_positive_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -69,16 +72,20 @@ fn test_fabs_positive_large() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 123456789.123456789, "FABS of large positive should remain positive"); + assert_eq!( + result, 123456789.123456789, + "FABS of large positive should remain positive" + ); } #[test] fn test_fabs_positive_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -92,11 +99,12 @@ fn test_fabs_positive_one() { #[test] fn test_fabs_positive_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -110,11 +118,12 @@ fn test_fabs_positive_fraction() { #[test] fn test_fabs_positive_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -123,7 +132,10 @@ fn test_fabs_positive_very_small() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 1e-10, "FABS of very small positive should remain positive"); + assert_eq!( + result, 1e-10, + "FABS of very small positive should remain positive" + ); } // ============================================================================ @@ -132,11 +144,12 @@ fn test_fabs_positive_very_small() { #[test] fn test_fabs_negative_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -150,11 +163,12 @@ fn test_fabs_negative_small() { #[test] fn test_fabs_negative_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -163,16 +177,20 @@ fn test_fabs_negative_large() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 987654321.987654321, "FABS of large negative should be positive"); + assert_eq!( + result, 987654321.987654321, + "FABS of large negative should be positive" + ); } #[test] fn test_fabs_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -186,11 +204,12 @@ fn test_fabs_negative_one() { #[test] fn test_fabs_negative_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -204,11 +223,12 @@ fn test_fabs_negative_fraction() { #[test] fn test_fabs_negative_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -217,7 +237,10 @@ fn test_fabs_negative_very_small() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 1e-10, "FABS of very small negative should be positive"); + assert_eq!( + result, 1e-10, + "FABS of very small negative should be positive" + ); } // ============================================================================ @@ -226,11 +249,12 @@ fn test_fabs_negative_very_small() { #[test] fn test_fabs_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -245,11 +269,12 @@ fn test_fabs_positive_zero() { #[test] fn test_fabs_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -268,11 +293,12 @@ fn test_fabs_negative_zero() { #[test] fn test_fabs_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -281,17 +307,24 @@ fn test_fabs_positive_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite(), "FABS of +infinity should be +infinity"); - assert!(!result.is_sign_negative(), "Result should be positive infinity"); + assert!( + result.is_infinite(), + "FABS of +infinity should be +infinity" + ); + assert!( + !result.is_sign_negative(), + "Result should be positive infinity" + ); } #[test] fn test_fabs_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -300,8 +333,14 @@ fn test_fabs_negative_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite(), "FABS of -infinity should be +infinity"); - assert!(!result.is_sign_negative(), "Result should be positive infinity"); + assert!( + result.is_infinite(), + "FABS of -infinity should be +infinity" + ); + assert!( + !result.is_sign_negative(), + "Result should be positive infinity" + ); } // ============================================================================ @@ -310,11 +349,12 @@ fn test_fabs_negative_infinity() { #[test] fn test_fabs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -328,11 +368,12 @@ fn test_fabs_nan() { #[test] fn test_fabs_negative_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -351,11 +392,12 @@ fn test_fabs_negative_nan() { #[test] fn test_fabs_clears_sign_bit_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -370,11 +412,12 @@ fn test_fabs_clears_sign_bit_negative() { #[test] fn test_fabs_preserves_positive_sign_bit() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -393,13 +436,13 @@ fn test_fabs_preserves_positive_sign_bit() { #[test] fn test_fabs_twice() { - let mut emu = emu64(); // FABS should be idempotent - applying it twice gives same result + let mut emu = emu64(); // FABS should be idempotent - applying it twice gives same result let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xD9, 0xE1, // FABS (second time) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xD9, 0xE1, // FABS (second time) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -413,14 +456,15 @@ fn test_fabs_twice() { #[test] fn test_fabs_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -441,11 +485,12 @@ fn test_fabs_sequence() { #[test] fn test_fabs_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -459,11 +504,12 @@ fn test_fabs_max_value() { #[test] fn test_fabs_min_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -472,16 +518,21 @@ fn test_fabs_min_positive() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, f64::MIN_POSITIVE, "FABS of -MIN_POSITIVE should be MIN_POSITIVE"); + assert_eq!( + result, + f64::MIN_POSITIVE, + "FABS of -MIN_POSITIVE should be MIN_POSITIVE" + ); } #[test] fn test_fabs_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -495,11 +546,12 @@ fn test_fabs_pi() { #[test] fn test_fabs_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -513,11 +565,12 @@ fn test_fabs_e() { #[test] fn test_fabs_subnormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -527,16 +580,20 @@ fn test_fabs_subnormal() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(!result.is_sign_negative(), "FABS of subnormal should be positive"); + assert!( + !result.is_sign_negative(), + "FABS of subnormal should be positive" + ); } #[test] fn test_fabs_various_magnitudes() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![ @@ -547,7 +604,7 @@ fn test_fabs_various_magnitudes() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, val.abs(), "FABS of {} should be {}", val, val.abs()); @@ -556,13 +613,14 @@ fn test_fabs_various_magnitudes() { #[test] fn test_fabs_mixed_operations() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC9, // FMULP (multiply and pop) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC9, // FMULP (multiply and pop) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -577,11 +635,12 @@ fn test_fabs_mixed_operations() { #[test] fn test_fabs_denormal_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -591,16 +650,20 @@ fn test_fabs_denormal_positive() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, denormal, "FABS of positive denormal preserves value"); + assert_eq!( + result, denormal, + "FABS of positive denormal preserves value" + ); } #[test] fn test_fabs_denormal_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -610,16 +673,20 @@ fn test_fabs_denormal_negative() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, -denormal, "FABS of negative denormal makes it positive"); + assert_eq!( + result, -denormal, + "FABS of negative denormal makes it positive" + ); } #[test] fn test_fabs_alternating_signs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![-1.0, 2.0, -3.0, 4.0, -5.0]; @@ -629,7 +696,7 @@ fn test_fabs_alternating_signs() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, *val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, *expected, "FABS of {} should be {}", val, expected); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fadd.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fadd.rs index 90d577db..736a102e 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fadd.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fadd.rs @@ -11,23 +11,28 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f32(mem: u64, addr: u64, value: f32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -38,14 +43,12 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fadd_m32fp_basic() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 2.0 - // FADD dword ptr [0x2008] ; Add 3.0 - // FSTP qword ptr [0x3000] + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 2.0 + // FADD dword ptr [0x2008] ; Add 3.0 + // FSTP qword ptr [0x3000] let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -57,11 +60,10 @@ fn test_fadd_m32fp_basic() { #[test] fn test_fadd_m32fp_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.5); @@ -73,11 +75,10 @@ fn test_fadd_m32fp_zero() { #[test] fn test_fadd_m32fp_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -89,11 +90,10 @@ fn test_fadd_m32fp_negative() { #[test] fn test_fadd_m32fp_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -111,11 +111,10 @@ fn test_fadd_m32fp_result_zero() { #[test] fn test_fadd_m64fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -127,11 +126,10 @@ fn test_fadd_m64fp_basic() { #[test] fn test_fadd_m64fp_large_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e15); @@ -143,11 +141,10 @@ fn test_fadd_m64fp_large_values() { #[test] fn test_fadd_m64fp_small_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e-15); @@ -160,18 +157,20 @@ fn test_fadd_m64fp_small_values() { #[test] fn test_fadd_m64fp_pi_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, std::f64::consts::PI); emu.maps.write_f64(DATA_ADDR + 8, std::f64::consts::E); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_f64(0x3000).unwrap(), std::f64::consts::PI + std::f64::consts::E); + assert_eq!( + emu.maps.read_f64(0x3000).unwrap(), + std::f64::consts::PI + std::f64::consts::E + ); } // ============================================================================ @@ -180,13 +179,11 @@ fn test_fadd_m64fp_pi_e() { #[test] fn test_fadd_st0_st1() { - let mut emu = emu64(); // FLD 2.0, FLD 3.0, FADD ST(0), ST(1) -> ST(0) = 5.0 + let mut emu = emu64(); // FLD 2.0, FLD 3.0, FADD ST(0), ST(1) -> ST(0) = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xC1, // FADD ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xC1, // FADD ST(0), ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -198,13 +195,11 @@ fn test_fadd_st0_st1() { #[test] fn test_fadd_st0_st2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xD8, 0xC2, // FADD ST(0), ST(2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xD8, 0xC2, // FADD ST(0), ST(2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -221,11 +216,10 @@ fn test_fadd_st0_st2() { #[test] fn test_fadd_st1_st0() { - let mut emu = emu64(); // FLD 2.0, FLD 3.0, FADD ST(1), ST(0) -> ST(1) = 5.0 + let mut emu = emu64(); // FLD 2.0, FLD 3.0, FADD ST(1), ST(0) -> ST(1) = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0xC1, // FADD ST(1), ST(0) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0xC1, // FADD ST(1), ST(0) 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // Pop ST(0) 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // Pop ST(0) 0xf4, @@ -245,13 +239,11 @@ fn test_fadd_st1_st0() { #[test] fn test_faddp_st1_st0() { - let mut emu = emu64(); // FADDP adds and pops + let mut emu = emu64(); // FADDP adds and pops let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC1, // FADDP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC1, // FADDP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -263,13 +255,11 @@ fn test_faddp_st1_st0() { #[test] fn test_faddp_no_operand() { - let mut emu = emu64(); // FADDP with no operand = FADDP ST(1), ST(0) + let mut emu = emu64(); // FADDP with no operand = FADDP ST(1), ST(0) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 7.5); @@ -285,11 +275,10 @@ fn test_faddp_no_operand() { #[test] fn test_fiadd_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.5); @@ -301,11 +290,10 @@ fn test_fiadd_m16int_positive() { #[test] fn test_fiadd_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -317,11 +305,10 @@ fn test_fiadd_m16int_negative() { #[test] fn test_fiadd_m16int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.14159); @@ -333,11 +320,10 @@ fn test_fiadd_m16int_zero() { #[test] fn test_fiadd_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -349,11 +335,10 @@ fn test_fiadd_m16int_max() { #[test] fn test_fiadd_m16int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -369,11 +354,10 @@ fn test_fiadd_m16int_min() { #[test] fn test_fiadd_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -385,11 +369,10 @@ fn test_fiadd_m32int_positive() { #[test] fn test_fiadd_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -401,11 +384,10 @@ fn test_fiadd_m32int_negative() { #[test] fn test_fiadd_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.25); @@ -421,11 +403,10 @@ fn test_fiadd_m32int_large() { #[test] fn test_fadd_infinity_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -438,11 +419,10 @@ fn test_fadd_infinity_finite() { #[test] fn test_fadd_neg_infinity_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NEG_INFINITY); @@ -455,11 +435,10 @@ fn test_fadd_neg_infinity_finite() { #[test] fn test_fadd_same_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -472,11 +451,10 @@ fn test_fadd_same_infinity() { #[test] fn test_fadd_nan_propagation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NAN); @@ -488,11 +466,10 @@ fn test_fadd_nan_propagation() { #[test] fn test_fadd_zero_plus_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -506,11 +483,10 @@ fn test_fadd_zero_plus_zero() { #[test] fn test_fadd_negative_zero_handling() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -527,13 +503,11 @@ fn test_fadd_negative_zero_handling() { #[test] fn test_fadd_precision_accumulation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, 0xDD, 0x1C, + 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.1); @@ -548,11 +522,10 @@ fn test_fadd_precision_accumulation() { #[test] fn test_fadd_mixed_magnitude() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e100); @@ -565,18 +538,14 @@ fn test_fadd_mixed_magnitude() { #[test] fn test_fadd_commutative() { - let mut emu = emu64(); // a + b should equal b + a + let mut emu = emu64(); // a + b should equal b + a let code1 = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; let code2 = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code1); @@ -596,12 +565,10 @@ fn test_fadd_commutative() { #[test] fn test_fadd_associative_property() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -614,7 +581,8 @@ fn test_fadd_associative_property() { #[test] fn test_fadd_chain_operations() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDE, 0xC1, // FADDP @@ -622,8 +590,7 @@ fn test_fadd_chain_operations() { 0xDE, 0xC1, // FADDP 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD 4.0 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -637,7 +604,8 @@ fn test_fadd_chain_operations() { #[test] fn test_fadd_stack_preservation() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDC, 0xC1, // FADD ST(1), ST(0) ; ST(1) = 8.0, ST(0) = 3.0 @@ -656,13 +624,13 @@ fn test_fadd_stack_preservation() { #[test] fn test_fiadd_multiple_integers() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.5 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD 10 0xDA, 0x04, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIADD 20 0xDA, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FIADD 30 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/faddp_fsubp_fmulp_fdivp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/faddp_fsubp_fmulp_fdivp.rs index 63273617..37cebeee 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/faddp_fsubp_fmulp_fdivp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/faddp_fsubp_fmulp_fdivp.rs @@ -13,11 +13,13 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -28,7 +30,8 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_faddp_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 2.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 3.0 0xDE, 0xC1, // FADDP ST(1), ST(0) ; ST(1) = 5.0, pop @@ -45,12 +48,12 @@ fn test_faddp_basic() { #[test] fn test_faddp_st1_st0() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 4.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 6.0 0xDE, 0xC1, // FADDP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -62,14 +65,14 @@ fn test_faddp_st1_st0() { #[test] fn test_faddp_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDE, 0xC1, // FADDP ; ST(0) = 3.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 4.0 0xDE, 0xC1, // FADDP ; ST(0) = 7.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -86,12 +89,12 @@ fn test_faddp_chain() { #[test] fn test_fsubp_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 10.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDE, 0xE9, // FSUBP ST(1), ST(0) ; ST(1) = 10 - 3 = 7 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -103,12 +106,12 @@ fn test_fsubp_basic() { #[test] fn test_fsubp_negative_result() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 10.0 0xDE, 0xE9, // FSUBP ; 5 - 10 = -5 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -124,12 +127,12 @@ fn test_fsubp_negative_result() { #[test] fn test_fsubrp_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 10.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDE, 0xE1, // FSUBRP ST(1), ST(0) ; ST(1) = 3 - 10 = -7 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -141,12 +144,12 @@ fn test_fsubrp_basic() { #[test] fn test_fsubrp_positive_result() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 10.0 0xDE, 0xE1, // FSUBRP ; 10 - 5 = 5 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -162,12 +165,12 @@ fn test_fsubrp_positive_result() { #[test] fn test_fmulp_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 3.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 4.0 0xDE, 0xC9, // FMULP ST(1), ST(0) ; ST(1) = 12.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -179,14 +182,14 @@ fn test_fmulp_basic() { #[test] fn test_fmulp_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDE, 0xC9, // FMULP ; 6.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 5.0 0xDE, 0xC9, // FMULP ; 30.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -203,12 +206,12 @@ fn test_fmulp_chain() { #[test] fn test_fdivp_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 20.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 4.0 0xDE, 0xF9, // FDIVP ST(1), ST(0) ; ST(1) = 20 / 4 = 5 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 20.0); @@ -220,12 +223,12 @@ fn test_fdivp_basic() { #[test] fn test_fdivp_fractional() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDE, 0xF9, // FDIVP ; 1 / 3 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -242,12 +245,12 @@ fn test_fdivp_fractional() { #[test] fn test_fdivrp_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 4.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 20.0 0xDE, 0xF1, // FDIVRP ST(1), ST(0) ; ST(1) = 20 / 4 = 5 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -259,12 +262,12 @@ fn test_fdivrp_basic() { #[test] fn test_fdivrp_fractional() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 3.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 1.0 0xDE, 0xF1, // FDIVRP ; 1 / 3 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fbld_fbstp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fbld_fbstp.rs index df214da6..f6a8b032 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fbld_fbstp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fbld_fbstp.rs @@ -25,23 +25,27 @@ use std::convert::TryInto; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // Write BCD value to memory fn write_bcd(mem: u64, addr: u64, value: &[u8; 10]) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, value); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, value); } // Read BCD value from memory fn read_bcd(mem: u64, addr: u64) -> [u8; 10] { - let emu = emu64(); let mut buf = [0u8; 10]; + let emu = emu64(); + let mut buf = [0u8; 10]; emu.maps.read_bytes_buff(&mut buf, addr); buf } @@ -49,7 +53,8 @@ fn read_bcd(mem: u64, addr: u64) -> [u8; 10] { // Helper to create BCD representation from a decimal string // BCD format: bytes 0-8 contain digits (LSB first), byte 9 has sign bit fn make_bcd(value: i64) -> [u8; 10] { - let emu = emu64(); let mut bcd = [0u8; 10]; + let emu = emu64(); + let mut bcd = [0u8; 10]; let is_negative = value < 0; let mut abs_value = value.abs() as u64; @@ -68,7 +73,8 @@ fn make_bcd(value: i64) -> [u8; 10] { // Helper to extract value from BCD fn parse_bcd(bcd: &[u8; 10]) -> Option { - let emu = emu64(); let is_negative = (bcd[9] & 0x80) != 0; + let emu = emu64(); + let is_negative = (bcd[9] & 0x80) != 0; let mut value: i64 = 0; let mut multiplier: i64 = 1; @@ -99,12 +105,10 @@ fn parse_bcd(bcd: &[u8; 10]) -> Option { #[test] fn test_fbld_zero() { - let mut emu = emu64(); // FBLD tbyte ptr [0x2000] - // FSTP qword ptr [0x3000] + let mut emu = emu64(); // FBLD tbyte ptr [0x2000] + // FSTP qword ptr [0x3000] let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(0)); @@ -115,10 +119,9 @@ fn test_fbld_zero() { #[test] fn test_fbld_positive_one() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(1)); @@ -129,10 +132,9 @@ fn test_fbld_positive_one() { #[test] fn test_fbld_negative_one() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(-1)); @@ -143,10 +145,9 @@ fn test_fbld_negative_one() { #[test] fn test_fbld_positive_123() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(123)); @@ -157,10 +158,9 @@ fn test_fbld_positive_123() { #[test] fn test_fbld_negative_456() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(-456)); @@ -171,10 +171,9 @@ fn test_fbld_negative_456() { #[test] fn test_fbld_large_positive() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(123456789)); @@ -185,10 +184,9 @@ fn test_fbld_large_positive() { #[test] fn test_fbld_large_negative() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(-987654321)); @@ -199,13 +197,13 @@ fn test_fbld_large_negative() { #[test] fn test_fbld_max_digits() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); - emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(999999999999999999)); + emu.maps + .write_bytes_slice(DATA_ADDR, &make_bcd(999999999999999999)); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 999999999999999999.0); @@ -213,7 +211,7 @@ fn test_fbld_max_digits() { #[test] fn test_fbld_pushes_to_stack() { - let mut emu = emu64(); // FBLD should push value onto stack + let mut emu = emu64(); // FBLD should push value onto stack let code = [ 0xDD, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FLD existing value 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FBLD @@ -232,7 +230,8 @@ fn test_fbld_pushes_to_stack() { #[test] fn test_fbld_multiple() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FBLD 10 0xDF, 0x24, 0x25, 0x0A, 0x20, 0x00, 0x00, // FBLD 20 0xDF, 0x24, 0x25, 0x14, 0x20, 0x00, 0x00, // FBLD 30 @@ -258,11 +257,9 @@ fn test_fbld_multiple() { #[test] fn test_fbstp_zero() { - let mut emu = emu64(); // FBSTP tbyte ptr [0x3000] + let mut emu = emu64(); // FBSTP tbyte ptr [0x3000] let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -274,10 +271,9 @@ fn test_fbstp_zero() { #[test] fn test_fbstp_positive_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -289,10 +285,9 @@ fn test_fbstp_positive_one() { #[test] fn test_fbstp_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -1.0); @@ -304,10 +299,9 @@ fn test_fbstp_negative_one() { #[test] fn test_fbstp_positive_123() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.0); @@ -319,10 +313,9 @@ fn test_fbstp_positive_123() { #[test] fn test_fbstp_negative_456() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -456.0); @@ -334,10 +327,9 @@ fn test_fbstp_negative_456() { #[test] fn test_fbstp_large_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123456789.0); @@ -349,10 +341,9 @@ fn test_fbstp_large_positive() { #[test] fn test_fbstp_large_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -987654321.0); @@ -364,11 +355,9 @@ fn test_fbstp_large_negative() { #[test] fn test_fbstp_rounds_down() { - let mut emu = emu64(); // 123.4 should round to 123 + let mut emu = emu64(); // 123.4 should round to 123 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.4); @@ -380,11 +369,9 @@ fn test_fbstp_rounds_down() { #[test] fn test_fbstp_rounds_up() { - let mut emu = emu64(); // 123.6 should round to 124 + let mut emu = emu64(); // 123.6 should round to 124 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.6); @@ -396,7 +383,7 @@ fn test_fbstp_rounds_up() { #[test] fn test_fbstp_pops_stack() { - let mut emu = emu64(); // FBSTP should pop the stack + let mut emu = emu64(); // FBSTP should pop the stack let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 100 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 200 @@ -421,7 +408,7 @@ fn test_fbstp_pops_stack() { #[test] fn test_fbld_fbstp_roundtrip_positive() { - let mut emu = emu64(); // FBLD followed by FBSTP should preserve value + let mut emu = emu64(); // FBLD followed by FBSTP should preserve value let code = [ 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FBLD 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FBSTP @@ -438,10 +425,9 @@ fn test_fbld_fbstp_roundtrip_positive() { #[test] fn test_fbld_fbstp_roundtrip_negative() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let original_bcd = make_bcd(-67890); @@ -454,10 +440,9 @@ fn test_fbld_fbstp_roundtrip_negative() { #[test] fn test_fbld_fbstp_roundtrip_zero() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let original_bcd = make_bcd(0); @@ -470,10 +455,9 @@ fn test_fbld_fbstp_roundtrip_zero() { #[test] fn test_fbld_fbstp_roundtrip_large() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let original_bcd = make_bcd(999999999999); @@ -481,7 +465,10 @@ fn test_fbld_fbstp_roundtrip_large() { emu.run(None).unwrap(); let result_bcd = emu.maps.read_bytes(0x3000, 10); - assert_eq!(parse_bcd((result_bcd).try_into().unwrap()), Some(999999999999)); + assert_eq!( + parse_bcd((result_bcd).try_into().unwrap()), + Some(999999999999) + ); } // ============================================================================ @@ -490,7 +477,7 @@ fn test_fbld_fbstp_roundtrip_large() { #[test] fn test_fbld_arithmetic() { - let mut emu = emu64(); // FBLD two values and add them + let mut emu = emu64(); // FBLD two values and add them let code = [ 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FBLD 100 0xDF, 0x24, 0x25, 0x0A, 0x20, 0x00, 0x00, // FBLD 200 @@ -508,7 +495,8 @@ fn test_fbld_arithmetic() { #[test] fn test_fbstp_after_arithmetic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 50.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 30.0 0xDE, 0xC1, // FADDP (80.0) @@ -526,7 +514,8 @@ fn test_fbstp_after_arithmetic() { #[test] fn test_fbld_fbstp_sequence() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FBLD 111 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FBSTP 111 0xDF, 0x24, 0x25, 0x0A, 0x20, 0x00, 0x00, // FBLD 222 @@ -550,10 +539,9 @@ fn test_fbld_fbstp_sequence() { #[test] fn test_fbstp_very_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999999999999999.0); @@ -565,10 +553,9 @@ fn test_fbstp_very_large() { #[test] fn test_fbld_all_nines() { - let mut emu = emu64(); let code = [ - 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_bytes_slice(DATA_ADDR, &make_bcd(999999)); @@ -579,10 +566,9 @@ fn test_fbld_all_nines() { #[test] fn test_fbstp_rounding_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 99.5); @@ -594,10 +580,9 @@ fn test_fbstp_rounding_half() { #[test] fn test_fbstp_negative_rounding() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -99.7); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fchs.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fchs.rs index f1d0f766..f7527f5c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fchs.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fchs.rs @@ -19,12 +19,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,15 +37,15 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fchs_positive_to_negative_small() { - let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 - // FCHS ; D9 E0 - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 + // FCHS ; D9 E0 + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -57,11 +59,12 @@ fn test_fchs_positive_to_negative_small() { #[test] fn test_fchs_positive_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -75,11 +78,12 @@ fn test_fchs_positive_one() { #[test] fn test_fchs_positive_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -88,16 +92,20 @@ fn test_fchs_positive_large() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, -999999.999999, "FCHS of large positive should be negative"); + assert_eq!( + result, -999999.999999, + "FCHS of large positive should be negative" + ); } #[test] fn test_fchs_positive_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -111,11 +119,12 @@ fn test_fchs_positive_fraction() { #[test] fn test_fchs_positive_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -124,7 +133,10 @@ fn test_fchs_positive_very_small() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, -1e-100, "FCHS of very small positive should be negative"); + assert_eq!( + result, -1e-100, + "FCHS of very small positive should be negative" + ); } // ============================================================================ @@ -133,11 +145,12 @@ fn test_fchs_positive_very_small() { #[test] fn test_fchs_negative_to_positive_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -151,11 +164,12 @@ fn test_fchs_negative_to_positive_small() { #[test] fn test_fchs_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -169,11 +183,12 @@ fn test_fchs_negative_one() { #[test] fn test_fchs_negative_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -182,16 +197,20 @@ fn test_fchs_negative_large() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 123456789.0, "FCHS of large negative should be positive"); + assert_eq!( + result, 123456789.0, + "FCHS of large negative should be positive" + ); } #[test] fn test_fchs_negative_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -205,11 +224,12 @@ fn test_fchs_negative_fraction() { #[test] fn test_fchs_negative_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -218,7 +238,10 @@ fn test_fchs_negative_very_small() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 1e-50, "FCHS of very small negative should be positive"); + assert_eq!( + result, 1e-50, + "FCHS of very small negative should be positive" + ); } // ============================================================================ @@ -227,11 +250,12 @@ fn test_fchs_negative_very_small() { #[test] fn test_fchs_positive_zero_to_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -246,11 +270,12 @@ fn test_fchs_positive_zero_to_negative_zero() { #[test] fn test_fchs_negative_zero_to_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -269,11 +294,12 @@ fn test_fchs_negative_zero_to_positive_zero() { #[test] fn test_fchs_positive_infinity_to_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -282,18 +308,23 @@ fn test_fchs_positive_infinity_to_negative_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, f64::NEG_INFINITY, "FCHS of +infinity should be -infinity"); + assert_eq!( + result, + f64::NEG_INFINITY, + "FCHS of +infinity should be -infinity" + ); assert!(result.is_infinite(), "Result should be infinite"); assert!(result.is_sign_negative(), "Result should be negative"); } #[test] fn test_fchs_negative_infinity_to_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -302,7 +333,11 @@ fn test_fchs_negative_infinity_to_positive_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, f64::INFINITY, "FCHS of -infinity should be +infinity"); + assert_eq!( + result, + f64::INFINITY, + "FCHS of -infinity should be +infinity" + ); assert!(result.is_infinite(), "Result should be infinite"); assert!(!result.is_sign_negative(), "Result should be positive"); } @@ -313,11 +348,12 @@ fn test_fchs_negative_infinity_to_positive_infinity() { #[test] fn test_fchs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -331,11 +367,12 @@ fn test_fchs_nan() { #[test] fn test_fchs_negative_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -353,13 +390,13 @@ fn test_fchs_negative_nan() { #[test] fn test_fchs_double_negation_positive() { - let mut emu = emu64(); // FCHS twice should return to original value + let mut emu = emu64(); // FCHS twice should return to original value let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS (second time) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS (second time) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -368,17 +405,21 @@ fn test_fchs_double_negation_positive() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 42.0, "Double FCHS should return original positive value"); + assert_eq!( + result, 42.0, + "Double FCHS should return original positive value" + ); } #[test] fn test_fchs_double_negation_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS (second time) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS (second time) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -387,17 +428,21 @@ fn test_fchs_double_negation_negative() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, -42.0, "Double FCHS should return original negative value"); + assert_eq!( + result, -42.0, + "Double FCHS should return original negative value" + ); } #[test] fn test_fchs_double_negation_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS (second time) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS (second time) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -412,13 +457,14 @@ fn test_fchs_double_negation_zero() { #[test] fn test_fchs_triple_negation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS (second) - 0xD9, 0xE0, // FCHS (third) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS (second) + 0xD9, 0xE0, // FCHS (third) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -436,11 +482,12 @@ fn test_fchs_triple_negation() { #[test] fn test_fchs_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -454,11 +501,12 @@ fn test_fchs_max_value() { #[test] fn test_fchs_min_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -467,16 +515,21 @@ fn test_fchs_min_positive() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, -f64::MIN_POSITIVE, "FCHS of MIN_POSITIVE should be -MIN_POSITIVE"); + assert_eq!( + result, + -f64::MIN_POSITIVE, + "FCHS of MIN_POSITIVE should be -MIN_POSITIVE" + ); } #[test] fn test_fchs_subnormal_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -486,17 +539,21 @@ fn test_fchs_subnormal_positive() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_sign_negative(), "FCHS of positive subnormal should be negative"); + assert!( + result.is_sign_negative(), + "FCHS of positive subnormal should be negative" + ); assert_eq!(result, -subnormal, "Magnitude should be preserved"); } #[test] fn test_fchs_subnormal_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -506,7 +563,10 @@ fn test_fchs_subnormal_negative() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(!result.is_sign_negative(), "FCHS of negative subnormal should be positive"); + assert!( + !result.is_sign_negative(), + "FCHS of negative subnormal should be positive" + ); assert_eq!(result, -subnormal, "Magnitude should be preserved"); } @@ -516,11 +576,12 @@ fn test_fchs_subnormal_negative() { #[test] fn test_fchs_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -534,11 +595,12 @@ fn test_fchs_pi() { #[test] fn test_fchs_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -556,14 +618,15 @@ fn test_fchs_e() { #[test] fn test_fchs_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -580,13 +643,14 @@ fn test_fchs_sequence() { #[test] fn test_fchs_with_arithmetic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP (add and pop) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP (add and pop) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -601,11 +665,12 @@ fn test_fchs_with_arithmetic() { #[test] fn test_fchs_various_magnitudes() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![ @@ -616,7 +681,7 @@ fn test_fchs_various_magnitudes() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, -val, "FCHS of {} should be {}", val, -val); @@ -625,14 +690,15 @@ fn test_fchs_various_magnitudes() { #[test] fn test_fchs_quadruple_negation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS - 0xD9, 0xE0, // FCHS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS + 0xD9, 0xE0, // FCHS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fclex_fnclex.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fclex_fnclex.rs index 59c78bd2..ecdbe8c7 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fclex_fnclex.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fclex_fnclex.rs @@ -30,33 +30,36 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; // Status word bit definitions -const IE_BIT: u16 = 0x0001; // Invalid Operation -const DE_BIT: u16 = 0x0002; // Denormalized Operand -const ZE_BIT: u16 = 0x0004; // Zero Divide -const OE_BIT: u16 = 0x0008; // Overflow -const UE_BIT: u16 = 0x0010; // Underflow -const PE_BIT: u16 = 0x0020; // Precision -const SF_BIT: u16 = 0x0040; // Stack Fault -const ES_BIT: u16 = 0x0080; // Exception Summary Status -const B_BIT: u16 = 0x8000; // Busy +const IE_BIT: u16 = 0x0001; // Invalid Operation +const DE_BIT: u16 = 0x0002; // Denormalized Operand +const ZE_BIT: u16 = 0x0004; // Zero Divide +const OE_BIT: u16 = 0x0008; // Overflow +const UE_BIT: u16 = 0x0010; // Underflow +const PE_BIT: u16 = 0x0020; // Precision +const SF_BIT: u16 = 0x0040; // Stack Fault +const ES_BIT: u16 = 0x0080; // Exception Summary Status +const B_BIT: u16 = 0x8000; // Busy const EXCEPTION_MASK: u16 = IE_BIT | DE_BIT | ZE_BIT | OE_BIT | UE_BIT | PE_BIT; // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // ============================================================================ @@ -65,11 +68,12 @@ fn write_f64(mem: u64, addr: u64, val: f64) { #[test] fn test_fnclex_basic() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -77,16 +81,20 @@ fn test_fnclex_basic() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "Exception flags should be cleared"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "Exception flags should be cleared" + ); } #[test] fn test_fnclex_clears_exception_flags() { - let mut emu = emu64(); // FNCLEX should clear exception flags + let mut emu = emu64(); // FNCLEX should clear exception flags let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xF4, // HLT + 0xDB, 0xE2, // FNCLEX + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -94,19 +102,24 @@ fn test_fnclex_clears_exception_flags() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "FNCLEX should clear all exception flags"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "FNCLEX should clear all exception flags" + ); } #[test] fn test_fnclex_multiple_times() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX (1st time) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDB, 0xE2, // FNCLEX (2nd time) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX (1st time) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDB, 0xE2, // FNCLEX (2nd time) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -115,18 +128,26 @@ fn test_fnclex_multiple_times() { let status1 = emu.maps.read_word(0x3000).unwrap(); let status2 = emu.maps.read_word(0x3002).unwrap(); - assert_eq!(status1 & EXCEPTION_MASK, 0, "First FNCLEX should clear exceptions"); - assert_eq!(status2 & EXCEPTION_MASK, 0, "Second FNCLEX should clear exceptions"); + assert_eq!( + status1 & EXCEPTION_MASK, + 0, + "First FNCLEX should clear exceptions" + ); + assert_eq!( + status2 & EXCEPTION_MASK, + 0, + "Second FNCLEX should clear exceptions" + ); } #[test] fn test_fnclex_clears_es_bit() { - let mut emu = emu64(); // FNCLEX should clear the ES (Exception Summary Status) bit + let mut emu = emu64(); // FNCLEX should clear the ES (Exception Summary Status) bit let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -139,12 +160,12 @@ fn test_fnclex_clears_es_bit() { #[test] fn test_fnclex_clears_sf_bit() { - let mut emu = emu64(); // FNCLEX should clear the SF (Stack Fault) bit + let mut emu = emu64(); // FNCLEX should clear the SF (Stack Fault) bit let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -161,11 +182,12 @@ fn test_fnclex_clears_sf_bit() { #[test] fn test_fclex_basic() { - let mut emu = emu64(); let code = [ - 0x9B, 0xDB, 0xE2, // FCLEX (with FWAIT) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x9B, 0xDB, 0xE2, // FCLEX (with FWAIT) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -173,16 +195,20 @@ fn test_fclex_basic() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "FCLEX should clear exception flags"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "FCLEX should clear exception flags" + ); } #[test] fn test_fclex_clears_exception_flags() { - let mut emu = emu64(); // FCLEX should clear exception flags + let mut emu = emu64(); // FCLEX should clear exception flags let code = [ - 0x9B, 0xDB, 0xE2, // FCLEX (with FWAIT) - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xF4, // HLT + 0x9B, 0xDB, 0xE2, // FCLEX (with FWAIT) + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -190,7 +216,11 @@ fn test_fclex_clears_exception_flags() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "FCLEX should clear all exception flags"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "FCLEX should clear all exception flags" + ); } // ============================================================================ @@ -199,19 +229,19 @@ fn test_fclex_clears_exception_flags() { #[test] fn test_fclex_vs_fnclex() { - let mut emu = emu64(); // FCLEX and FNCLEX should have same effect in normal operation + let mut emu = emu64(); // FCLEX and FNCLEX should have same effect in normal operation let code1 = [ - 0x9B, 0xDB, 0xE2, // FCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0x9B, 0xDB, 0xE2, // FCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; let code2 = [ - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -231,13 +261,14 @@ fn test_fclex_vs_fnclex() { #[test] fn test_fnclex_then_fnstsw() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDF, 0xE0, // FNSTSW AX (2nd time) - 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDF, 0xE0, // FNSTSW AX (2nd time) + 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -246,8 +277,16 @@ fn test_fnclex_then_fnstsw() { let status1 = emu.maps.read_word(0x3000).unwrap(); let status2 = emu.maps.read_word(0x3002).unwrap(); - assert_eq!(status1 & EXCEPTION_MASK, 0, "First FNSTSW should show cleared exceptions"); - assert_eq!(status2 & EXCEPTION_MASK, 0, "Second FNSTSW should show cleared exceptions"); + assert_eq!( + status1 & EXCEPTION_MASK, + 0, + "First FNSTSW should show cleared exceptions" + ); + assert_eq!( + status2 & EXCEPTION_MASK, + 0, + "Second FNSTSW should show cleared exceptions" + ); } // ============================================================================ @@ -256,14 +295,14 @@ fn test_fnclex_then_fnstsw() { #[test] fn test_fnclex_before_operations() { - let mut emu = emu64(); // FNCLEX before FPU operations + let mut emu = emu64(); // FNCLEX before FPU operations let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDB, 0xE2, // FNCLEX + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -272,21 +311,25 @@ fn test_fnclex_before_operations() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "Exceptions should still be cleared after FLD"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "Exceptions should still be cleared after FLD" + ); } #[test] fn test_fnclex_after_operations() { - let mut emu = emu64(); // FNCLEX after FPU operations + let mut emu = emu64(); // FNCLEX after FPU operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -296,7 +339,11 @@ fn test_fnclex_after_operations() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "FNCLEX should clear exceptions after arithmetic"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "FNCLEX should clear exceptions after arithmetic" + ); } // ============================================================================ @@ -305,11 +352,12 @@ fn test_fnclex_after_operations() { #[test] fn test_fnclex_individual_exception_bits() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -331,13 +379,14 @@ fn test_fnclex_individual_exception_bits() { #[test] fn test_sequential_fnclex() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDB, 0xE2, // FNCLEX - 0xDB, 0xE2, // FNCLEX - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX + 0xDB, 0xE2, // FNCLEX + 0xDB, 0xE2, // FNCLEX + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -345,7 +394,11 @@ fn test_sequential_fnclex() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "Multiple FNCLEX should clear all exceptions"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "Multiple FNCLEX should clear all exceptions" + ); } // ============================================================================ @@ -354,17 +407,17 @@ fn test_sequential_fnclex() { #[test] fn test_fnclex_after_comparison() { - let mut emu = emu64(); // FNCLEX after comparison (condition codes should not be cleared by FNCLEX) + let mut emu = emu64(); // FNCLEX after comparison (condition codes should not be cleared by FNCLEX) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDB, 0xE2, // FNCLEX (clears exception flags, not condition codes) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDB, 0xE2, // FNCLEX (clears exception flags, not condition codes) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -374,7 +427,11 @@ fn test_fnclex_after_comparison() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "Exception flags should be cleared"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "Exception flags should be cleared" + ); } // ============================================================================ @@ -383,16 +440,17 @@ fn test_fnclex_after_comparison() { #[test] fn test_fnclex_complete_flow() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX (clear any initial exceptions) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] (before clear) - 0xDB, 0xE2, // FNCLEX - 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] (after clear) - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX (clear any initial exceptions) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] (before clear) + 0xDB, 0xE2, // FNCLEX + 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] (after clear) + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -403,23 +461,27 @@ fn test_fnclex_complete_flow() { let status_before = emu.maps.read_word(0x3000).unwrap(); let status_after = emu.maps.read_word(0x3002).unwrap(); - assert_eq!(status_after & EXCEPTION_MASK, 0, "Exceptions should be cleared after FNCLEX"); + assert_eq!( + status_after & EXCEPTION_MASK, + 0, + "Exceptions should be cleared after FNCLEX" + ); } #[test] fn test_fclex_multiple_operations() { - let mut emu = emu64(); // FCLEX with multiple operations + let mut emu = emu64(); // FCLEX with multiple operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0x9B, 0xDB, 0xE2, // FCLEX - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDE, 0xC1, // FADDP - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0x9B, 0xDB, 0xE2, // FCLEX + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDE, 0xC1, // FADDP + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -430,7 +492,11 @@ fn test_fclex_multiple_operations() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(status & EXCEPTION_MASK, 0, "Exceptions should remain cleared"); + assert_eq!( + status & EXCEPTION_MASK, + 0, + "Exceptions should remain cleared" + ); } // ============================================================================ @@ -439,10 +505,11 @@ fn test_fclex_multiple_operations() { #[test] fn test_fnclex_status_word_clean_state() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE2, // FNCLEX - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE2, // FNCLEX + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -462,14 +529,14 @@ fn test_fnclex_status_word_clean_state() { #[test] fn test_fnclex_preserves_other_bits() { - let mut emu = emu64(); // FNCLEX should only clear exception flags, not affect other FPU state + let mut emu = emu64(); // FNCLEX should only clear exception flags, not affect other FPU state let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] (before) - 0xDB, 0xE2, // FNCLEX - 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] (after) - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] (before) + 0xDB, 0xE2, // FNCLEX + 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] (after) + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcmovcc.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcmovcc.rs index 2ac2f44f..97ab6214 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcmovcc.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcmovcc.rs @@ -34,11 +34,13 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -49,7 +51,8 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fcmovb_when_cf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 -> ST(0) 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 -> ST(0), ST(1)=1.0 0xF9, // STC (set carry flag) @@ -67,7 +70,8 @@ fn test_fcmovb_when_cf_set() { #[test] fn test_fcmovb_when_cf_clear() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 -> ST(0) 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 -> ST(0), ST(1)=1.0 0xF8, // CLC (clear carry flag) @@ -85,14 +89,14 @@ fn test_fcmovb_when_cf_clear() { #[test] fn test_fcmovb_st2() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3.0 0xF9, // STC 0xDA, 0xC2, // FCMOVB ST(0), ST(2) - move ST(2)=1.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -105,15 +109,15 @@ fn test_fcmovb_st2() { #[test] fn test_fcmovb_after_cmp() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 10.0 0xB8, 0x01, 0x00, 0x00, 0x00, // MOV EAX, 1 0xBB, 0x02, 0x00, 0x00, 0x00, // MOV EBX, 2 0x39, 0xD8, // CMP EAX, EBX (1 < 2, sets CF) 0xDA, 0xC1, // FCMOVB ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -129,15 +133,15 @@ fn test_fcmovb_after_cmp() { #[test] fn test_fcmove_when_zf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x05, 0x00, 0x00, 0x00, // MOV EAX, 5 0xBB, 0x05, 0x00, 0x00, 0x00, // MOV EBX, 5 0x39, 0xD8, // CMP EAX, EBX (equal, sets ZF) 0xDA, 0xC9, // FCMOVE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -149,15 +153,15 @@ fn test_fcmove_when_zf_set() { #[test] fn test_fcmove_when_zf_clear() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x01, 0x00, 0x00, 0x00, // MOV EAX, 1 0xBB, 0x02, 0x00, 0x00, 0x00, // MOV EBX, 2 0x39, 0xD8, // CMP EAX, EBX (not equal, clears ZF) 0xDA, 0xC9, // FCMOVE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -169,7 +173,8 @@ fn test_fcmove_when_zf_clear() { #[test] fn test_fcmove_st3() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3.0 @@ -178,8 +183,7 @@ fn test_fcmove_st3() { 0xBB, 0x07, 0x00, 0x00, 0x00, // MOV EBX, 7 0x39, 0xD8, // CMP (sets ZF) 0xDA, 0xCB, // FCMOVE ST(0), ST(3) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -197,13 +201,13 @@ fn test_fcmove_st3() { #[test] fn test_fcmovbe_when_cf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xF9, // STC (CF=1) 0xDA, 0xD1, // FCMOVBE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -215,14 +219,14 @@ fn test_fcmovbe_when_cf_set() { #[test] fn test_fcmovbe_when_zf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x03, 0x00, 0x00, 0x00, // MOV EAX, 3 0x3D, 0x03, 0x00, 0x00, 0x00, // CMP EAX, 3 (sets ZF) 0xDA, 0xD1, // FCMOVBE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -234,14 +238,14 @@ fn test_fcmovbe_when_zf_set() { #[test] fn test_fcmovbe_when_neither_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x05, 0x00, 0x00, 0x00, // MOV EAX, 5 0x3D, 0x02, 0x00, 0x00, 0x00, // CMP EAX, 2 (5 > 2, CF=0, ZF=0) 0xDA, 0xD1, // FCMOVBE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -257,14 +261,14 @@ fn test_fcmovbe_when_neither_set() { #[test] fn test_fcmovu_when_pf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB0, 0x03, // MOV AL, 3 (binary 11, even parity) 0xA8, 0xFF, // TEST AL, 0xFF (sets PF=1) 0xDA, 0xD9, // FCMOVU ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -276,14 +280,14 @@ fn test_fcmovu_when_pf_set() { #[test] fn test_fcmovu_when_pf_clear() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB0, 0x07, // MOV AL, 7 (binary 111, odd parity) 0xA8, 0xFF, // TEST AL, 0xFF (sets PF=0) 0xDA, 0xD9, // FCMOVU ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -299,13 +303,13 @@ fn test_fcmovu_when_pf_clear() { #[test] fn test_fcmovnb_when_cf_clear() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xF8, // CLC (CF=0) 0xDB, 0xC1, // FCMOVNB ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -317,13 +321,13 @@ fn test_fcmovnb_when_cf_clear() { #[test] fn test_fcmovnb_when_cf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xF9, // STC (CF=1) 0xDB, 0xC1, // FCMOVNB ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -335,15 +339,15 @@ fn test_fcmovnb_when_cf_set() { #[test] fn test_fcmovnb_after_cmp_greater() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 10.0 0xB8, 0x05, 0x00, 0x00, 0x00, // MOV EAX, 5 0xBB, 0x02, 0x00, 0x00, 0x00, // MOV EBX, 2 0x39, 0xD8, // CMP EAX, EBX (5 >= 2, CF=0) 0xDB, 0xC1, // FCMOVNB ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -359,15 +363,15 @@ fn test_fcmovnb_after_cmp_greater() { #[test] fn test_fcmovne_when_zf_clear() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x01, 0x00, 0x00, 0x00, // MOV EAX, 1 0xBB, 0x02, 0x00, 0x00, 0x00, // MOV EBX, 2 0x39, 0xD8, // CMP EAX, EBX (not equal, ZF=0) 0xDB, 0xC9, // FCMOVNE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -379,15 +383,15 @@ fn test_fcmovne_when_zf_clear() { #[test] fn test_fcmovne_when_zf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x05, 0x00, 0x00, 0x00, // MOV EAX, 5 0xBB, 0x05, 0x00, 0x00, 0x00, // MOV EBX, 5 0x39, 0xD8, // CMP EAX, EBX (equal, ZF=1) 0xDB, 0xC9, // FCMOVNE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -403,14 +407,14 @@ fn test_fcmovne_when_zf_set() { #[test] fn test_fcmovnbe_when_neither_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x05, 0x00, 0x00, 0x00, // MOV EAX, 5 0x3D, 0x02, 0x00, 0x00, 0x00, // CMP EAX, 2 (5 > 2, CF=0, ZF=0) 0xDB, 0xD1, // FCMOVNBE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -422,13 +426,13 @@ fn test_fcmovnbe_when_neither_set() { #[test] fn test_fcmovnbe_when_cf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xF9, // STC (CF=1) 0xDB, 0xD1, // FCMOVNBE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -440,14 +444,14 @@ fn test_fcmovnbe_when_cf_set() { #[test] fn test_fcmovnbe_when_zf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB8, 0x03, 0x00, 0x00, 0x00, // MOV EAX, 3 0x3D, 0x03, 0x00, 0x00, 0x00, // CMP EAX, 3 (ZF=1) 0xDB, 0xD1, // FCMOVNBE ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -463,14 +467,14 @@ fn test_fcmovnbe_when_zf_set() { #[test] fn test_fcmovnu_when_pf_clear() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB0, 0x07, // MOV AL, 7 (odd parity, PF=0) 0xA8, 0xFF, // TEST AL, 0xFF 0xDB, 0xD9, // FCMOVNU ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -482,14 +486,14 @@ fn test_fcmovnu_when_pf_clear() { #[test] fn test_fcmovnu_when_pf_set() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xB0, 0x03, // MOV AL, 3 (even parity, PF=1) 0xA8, 0xFF, // TEST AL, 0xFF 0xDB, 0xD9, // FCMOVNU ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -505,7 +509,8 @@ fn test_fcmovnu_when_pf_set() { #[test] fn test_fcmov_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3.0 @@ -513,8 +518,7 @@ fn test_fcmov_chain() { 0xDA, 0xC1, // FCMOVB ST(0), ST(1) - should not move 0xF9, // STC (CF=1) 0xDB, 0xC2, // FCMOVNB ST(0), ST(2) - should not move (CF=1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -527,7 +531,8 @@ fn test_fcmov_chain() { #[test] fn test_fcmov_preserves_other_registers() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3.0 @@ -551,7 +556,8 @@ fn test_fcmov_preserves_other_registers() { #[test] fn test_fcmov_with_arithmetic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 10.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 20.0 0xB8, 0x01, 0x00, 0x00, 0x00, // MOV EAX, 1 @@ -559,8 +565,7 @@ fn test_fcmov_with_arithmetic() { 0x39, 0xD8, // CMP EAX, EBX (1 < 2, CF=1) 0xDA, 0xC1, // FCMOVB ST(0), ST(1) - move 10.0 to ST(0) 0xDE, 0xC1, // FADDP - add ST(0) + ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -572,7 +577,8 @@ fn test_fcmov_with_arithmetic() { #[test] fn test_fcmov_all_conditions() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Test FCMOVB 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 @@ -580,7 +586,6 @@ fn test_fcmov_all_conditions() { 0xDA, 0xC1, // FCMOVB 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // Store 1.0 0xDD, 0xD8, // Pop - // Test FCMOVE 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3.0 @@ -589,7 +594,6 @@ fn test_fcmov_all_conditions() { 0xDA, 0xC9, // FCMOVE 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // Store 1.0 0xDD, 0xD8, // Pop - 0xf4, ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcom.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcom.rs index 1a6ddfd0..33138568 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcom.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcom.rs @@ -30,20 +30,22 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // FPU status word bit positions for condition codes -const C0_BIT: u16 = 0x0100; // bit 8 -const C2_BIT: u16 = 0x0400; // bit 10 -const C3_BIT: u16 = 0x4000; // bit 14 +const C0_BIT: u16 = 0x0100; // bit 8 +const C2_BIT: u16 = 0x0400; // bit 10 +const C3_BIT: u16 = 0x4000; // bit 14 // Helper to extract FPU status word // Note: This is a simplified test - actual implementation would need to @@ -55,20 +57,20 @@ const C3_BIT: u16 = 0x4000; // bit 14 #[test] fn test_fcom_equal() { - let mut emu = emu64(); // FLD qword [0x2000] ; Load 5.0 into ST(0) - // FLD qword [0x2008] ; Load 5.0 into ST(0), previous ST(0) becomes ST(1) - // FCOM ST(1) ; D8 D1 - Compare ST(0) with ST(1) - // FSTP qword [0x3000] ; Store result flag test helper - // FSTP qword [0x3008] ; Clean stack - // HLT - let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) + let mut emu = emu64(); // FLD qword [0x2000] ; Load 5.0 into ST(0) + // FLD qword [0x2008] ; Load 5.0 into ST(0), previous ST(0) becomes ST(1) + // FCOM ST(1) ; D8 D1 - Compare ST(0) with ST(1) + // FSTP qword [0x3000] ; Store result flag test helper + // FSTP qword [0x3008] ; Clean stack + // HLT + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) // For testing, we'll store both values to verify they're still on stack - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -85,13 +87,14 @@ fn test_fcom_equal() { #[test] fn test_fcom_greater_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -108,13 +111,14 @@ fn test_fcom_greater_than() { #[test] fn test_fcom_less_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -131,13 +135,14 @@ fn test_fcom_less_than() { #[test] fn test_fcom_zero_equal() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xEE, // FLDZ - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0xEE, // FLDZ + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -152,21 +157,20 @@ fn test_fcom_zero_equal() { #[test] fn test_fcom_positive_negative_zero() { - let mut emu = emu64(); // +0.0 should equal -0.0 + let mut emu = emu64(); // +0.0 should equal -0.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-0.0) - 0xD9, 0xEE, // FLDZ (+0.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-0.0) + 0xD9, 0xEE, // FLDZ (+0.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, -0.0); emu.run(None).unwrap(); - } // ============================================================================ @@ -175,13 +179,14 @@ fn test_fcom_positive_negative_zero() { #[test] fn test_fcomp_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD9, // FCOMP ST(1) - compare and pop + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD9, // FCOMP ST(1) - compare and pop // After FCOMP, only one value should be on stack - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -191,17 +196,21 @@ fn test_fcomp_equal() { emu.run(None).unwrap(); let val = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(val, 5.0, "After FCOMP, ST(0) should contain the remaining value"); + assert_eq!( + val, 5.0, + "After FCOMP, ST(0) should contain the remaining value" + ); } #[test] fn test_fcomp_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) - 0xD8, 0xD9, // FCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) + 0xD8, 0xD9, // FCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -216,12 +225,13 @@ fn test_fcomp_greater() { #[test] fn test_fcomp_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xD8, 0xD9, // FCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xD8, 0xD9, // FCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -236,12 +246,13 @@ fn test_fcomp_less() { #[test] fn test_fcomp_with_constant() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD8, 0xD9, // FCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD8, 0xD9, // FCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -258,14 +269,15 @@ fn test_fcomp_with_constant() { #[test] fn test_fcompp_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xD9, // FCOMPP - compare and pop twice + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xD9, // FCOMPP - compare and pop twice // Stack should now be empty, push a marker value to verify - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -275,18 +287,22 @@ fn test_fcompp_equal() { emu.run(None).unwrap(); let marker = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(marker, 1.0, "Stack should be empty after FCOMPP, FLD1 should work"); + assert_eq!( + marker, 1.0, + "Stack should be empty after FCOMPP, FLD1 should work" + ); } #[test] fn test_fcompp_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (2.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (6.0) - 0xDE, 0xD9, // FCOMPP - 0xD9, 0xE8, // FLD1 (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (2.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (6.0) + 0xDE, 0xD9, // FCOMPP + 0xD9, 0xE8, // FLD1 (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -301,13 +317,14 @@ fn test_fcompp_greater() { #[test] fn test_fcompp_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (8.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xDE, 0xD9, // FCOMPP - 0xD9, 0xEE, // FLDZ (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (8.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xDE, 0xD9, // FCOMPP + 0xD9, 0xEE, // FLDZ (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -322,13 +339,14 @@ fn test_fcompp_less() { #[test] fn test_fcompp_with_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xE8, // FLD1 - 0xDE, 0xD9, // FCOMPP - 0xD9, 0xEB, // FLDPI (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0xE8, // FLD1 + 0xDE, 0xD9, // FCOMPP + 0xD9, 0xEB, // FLDPI (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -345,14 +363,14 @@ fn test_fcompp_with_constants() { #[test] fn test_fcom_infinity_greater() { - let mut emu = emu64(); // +infinity > finite + let mut emu = emu64(); // +infinity > finite let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -369,14 +387,14 @@ fn test_fcom_infinity_greater() { #[test] fn test_fcom_negative_infinity_less() { - let mut emu = emu64(); // -infinity < finite + let mut emu = emu64(); // -infinity < finite let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (0.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-inf) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (0.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-inf) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -393,14 +411,14 @@ fn test_fcom_negative_infinity_less() { #[test] fn test_fcom_infinities_equal() { - let mut emu = emu64(); // +inf == +inf + let mut emu = emu64(); // +inf == +inf let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -417,14 +435,14 @@ fn test_fcom_infinities_equal() { #[test] fn test_fcom_infinities_different() { - let mut emu = emu64(); // +inf > -inf + let mut emu = emu64(); // +inf > -inf let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-inf) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-inf) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -445,13 +463,14 @@ fn test_fcom_infinities_different() { #[test] fn test_fcom_nan_vs_number() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -468,13 +487,14 @@ fn test_fcom_nan_vs_number() { #[test] fn test_fcom_number_vs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -491,13 +511,14 @@ fn test_fcom_number_vs_nan() { #[test] fn test_fcom_nan_vs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -518,13 +539,14 @@ fn test_fcom_nan_vs_nan() { #[test] fn test_fcom_very_close_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -532,19 +554,18 @@ fn test_fcom_very_close_numbers() { emu.maps.write_f64(0x2008, 1.0 + 1e-15); emu.run(None).unwrap(); - } #[test] fn test_fcom_negative_numbers() { - let mut emu = emu64(); // -5.0 > -10.0 + let mut emu = emu64(); // -5.0 > -10.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -562,13 +583,14 @@ fn test_fcom_negative_numbers() { #[test] fn test_fcom_mixed_signs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-3.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-3.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -585,13 +607,14 @@ fn test_fcom_mixed_signs() { #[test] fn test_fcom_tiny_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -608,13 +631,14 @@ fn test_fcom_tiny_numbers() { #[test] fn test_fcom_huge_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -635,16 +659,17 @@ fn test_fcom_huge_numbers() { #[test] fn test_fcom_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xD8, 0xD1, // FCOM ST(1) - compare 2.0 vs 1.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xD8, 0xD1, // FCOM ST(1) - compare 3.0 vs 2.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xD8, 0xD1, // FCOM ST(1) - compare 2.0 vs 1.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xD8, 0xD1, // FCOM ST(1) - compare 3.0 vs 2.0 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -664,16 +689,17 @@ fn test_fcom_sequence() { #[test] fn test_mixed_compare_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 (1.0) - 0xD9, 0xE8, // FLD1 (1.0) - 0xD8, 0xD1, // FCOM ST(1) - 0xD9, 0xE8, // FLD1 (1.0) - 0xD8, 0xD9, // FCOMP ST(1) - pop once - 0xDE, 0xD9, // FCOMPP - pop twice - 0xD9, 0xEE, // FLDZ (marker - stack should be empty) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 (1.0) + 0xD9, 0xE8, // FLD1 (1.0) + 0xD8, 0xD1, // FCOM ST(1) + 0xD9, 0xE8, // FLD1 (1.0) + 0xD8, 0xD9, // FCOMP ST(1) - pop once + 0xDE, 0xD9, // FCOMPP - pop twice + 0xD9, 0xEE, // FLDZ (marker - stack should be empty) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -686,17 +712,18 @@ fn test_mixed_compare_operations() { #[test] fn test_fcom_with_arithmetic() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + 1 = 2) - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + 1 = 2) - 0xD8, 0xD1, // FCOM ST(1) - compare 2 vs 2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + 1 = 2) + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + 1 = 2) + 0xD8, 0xD1, // FCOM ST(1) - compare 2 vs 2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -711,13 +738,14 @@ fn test_fcom_with_arithmetic() { #[test] fn test_fcom_fractions() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -734,12 +762,13 @@ fn test_fcom_fractions() { #[test] fn test_fcomp_negative_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD9, // FCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD9, // FCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -754,13 +783,14 @@ fn test_fcomp_negative_values() { #[test] fn test_fcompp_pi_comparison() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xEB, // FLDPI - 0xDE, 0xD9, // FCOMPP - 0xD9, 0xE8, // FLD1 (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xD9, 0xEB, // FLDPI + 0xDE, 0xD9, // FCOMPP + 0xD9, 0xE8, // FLD1 (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -773,13 +803,14 @@ fn test_fcompp_pi_comparison() { #[test] fn test_fcom_denormal_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -795,13 +826,14 @@ fn test_fcom_denormal_numbers() { #[test] fn test_fcom_max_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -818,14 +850,15 @@ fn test_fcom_max_values() { #[test] fn test_fcomp_sequential() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xD8, 0xD9, // FCOMP ST(1) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xD8, 0xD9, // FCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xD8, 0xD9, // FCOMP ST(1) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xD8, 0xD9, // FCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -834,18 +867,18 @@ fn test_fcomp_sequential() { emu.maps.write_f64(0x2010, 3.0); emu.run(None).unwrap(); - } #[test] fn test_fcom_powers_of_ten() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -862,13 +895,14 @@ fn test_fcom_powers_of_ten() { #[test] fn test_fcompp_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xD9, // FCOMPP - 0xD9, 0xEB, // FLDPI (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xD9, // FCOMPP + 0xD9, 0xEB, // FLDPI (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -883,13 +917,14 @@ fn test_fcompp_negative_infinity() { #[test] fn test_fcom_epsilon() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -897,18 +932,18 @@ fn test_fcom_epsilon() { emu.maps.write_f64(0x2008, 1.0 + f64::EPSILON); emu.run(None).unwrap(); - } #[test] fn test_fcom_mixed_sign_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -925,17 +960,18 @@ fn test_fcom_mixed_sign_small() { #[test] fn test_fcompp_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (2) - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC9, // FMULP (1) - 0xDE, 0xD9, // FCOMPP (compare 2 vs 1) - 0xD9, 0xEE, // FLDZ (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (2) + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC9, // FMULP (1) + 0xDE, 0xD9, // FCOMPP (compare 2 vs 1) + 0xD9, 0xEE, // FLDZ (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -947,13 +983,14 @@ fn test_fcompp_after_arithmetic() { } #[test] fn test_fcom_constants_comparison() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xEA, // FLDL2E - 0xD8, 0xD1, // FCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xD9, 0xEA, // FLDL2E + 0xD8, 0xD1, // FCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcomi_fcomip.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcomi_fcomip.rs index f287180d..3630fb2b 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcomi_fcomip.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcomi_fcomip.rs @@ -29,19 +29,22 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // Helper function to read u64 from memory fn read_u64(mem: u64, addr: u64) -> u64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); u64::from_le_bytes(buf) } @@ -57,15 +60,16 @@ const ZF_BIT: u64 = 1 << 6; #[test] fn test_fcomi_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -86,15 +90,16 @@ fn test_fcomi_equal() { #[test] fn test_fcomi_greater_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -115,15 +120,16 @@ fn test_fcomi_greater_than() { #[test] fn test_fcomi_less_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -144,18 +150,18 @@ fn test_fcomi_less_than() { #[test] fn test_fcomi_st2() { - let mut emu = emu64(); // FCOMI with ST(2) + let mut emu = emu64(); // FCOMI with ST(2) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDB, 0xF2, // FCOMI ST(2) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDB, 0xF2, // FCOMI ST(2) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -171,20 +177,20 @@ fn test_fcomi_st2() { #[test] fn test_fcomi_st3() { - let mut emu = emu64(); // FCOMI with ST(3) + let mut emu = emu64(); // FCOMI with ST(3) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] (4.0) - 0xDB, 0xF3, // FCOMI ST(3) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] (4.0) + 0xDB, 0xF3, // FCOMI ST(3) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -201,16 +207,16 @@ fn test_fcomi_st3() { #[test] fn test_fcomi_infinity_greater() { - let mut emu = emu64(); // +infinity > finite -> ZF=0, PF=0, CF=0 + let mut emu = emu64(); // +infinity > finite -> ZF=0, PF=0, CF=0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -227,16 +233,16 @@ fn test_fcomi_infinity_greater() { #[test] fn test_fcomi_infinities_equal() { - let mut emu = emu64(); // +inf == +inf -> ZF=1, PF=0, CF=0 + let mut emu = emu64(); // +inf == +inf -> ZF=1, PF=0, CF=0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -253,16 +259,16 @@ fn test_fcomi_infinities_equal() { #[test] fn test_fcomi_positive_negative_zero() { - let mut emu = emu64(); // +0.0 == -0.0 -> ZF=1, PF=0, CF=0 + let mut emu = emu64(); // +0.0 == -0.0 -> ZF=1, PF=0, CF=0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-0.0) - 0xD9, 0xEE, // FLDZ (+0.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-0.0) + 0xD9, 0xEE, // FLDZ (+0.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -281,14 +287,15 @@ fn test_fcomi_positive_negative_zero() { #[test] fn test_fcomip_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -306,14 +313,15 @@ fn test_fcomip_equal() { #[test] fn test_fcomip_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -331,14 +339,15 @@ fn test_fcomip_greater() { #[test] fn test_fcomip_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -356,16 +365,17 @@ fn test_fcomip_less() { #[test] fn test_fcomip_st2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDF, 0xF2, // FCOMIP ST(2) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDF, 0xF2, // FCOMIP ST(2) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -389,16 +399,17 @@ fn test_fcomip_st2() { #[test] fn test_fcomi_conditional_je() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xF1, // FCOMI ST(1) - 0x74, 0x07, // JE +7 (skip if equal) - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xF1, // FCOMI ST(1) + 0x74, 0x07, // JE +7 (skip if equal) + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -410,16 +421,17 @@ fn test_fcomi_conditional_je() { #[test] fn test_fcomi_conditional_jb() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (10.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (5.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x72, 0x07, // JB +7 (jump if below) - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (10.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (5.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x72, 0x07, // JB +7 (jump if below) + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -434,16 +446,17 @@ fn test_fcomi_conditional_jb() { #[test] fn test_fcomi_conditional_ja() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x77, 0x07, // JA +7 (jump if above) - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x77, 0x07, // JA +7 (jump if above) + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -458,15 +471,16 @@ fn test_fcomi_conditional_ja() { #[test] fn test_fcomip_conditional_jne() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDF, 0xF1, // FCOMIP ST(1) - 0x75, 0x07, // JNE +7 (jump if not equal) - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDF, 0xF1, // FCOMIP ST(1) + 0x75, 0x07, // JNE +7 (jump if not equal) + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -482,20 +496,21 @@ fn test_fcomip_conditional_jne() { #[test] fn test_fcomi_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -513,18 +528,19 @@ fn test_fcomi_sequence() { #[test] fn test_fcomip_chain() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (2.0) - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (2.0) + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -542,15 +558,16 @@ fn test_fcomip_chain() { #[test] fn test_fcomi_zero_comparison() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xEE, // FLDZ - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0xEE, // FLDZ + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -563,15 +580,16 @@ fn test_fcomi_zero_comparison() { #[test] fn test_fcomi_inf_vs_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1000.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1000.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -587,14 +605,15 @@ fn test_fcomi_inf_vs_finite() { #[test] fn test_fcomip_negative_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -609,15 +628,16 @@ fn test_fcomip_negative_numbers() { #[test] fn test_fcomi_denormals() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -630,20 +650,25 @@ fn test_fcomi_denormals() { let flags = emu.maps.read_qword(0x3000).unwrap(); assert_eq!(flags & ZF_BIT, 0, "ZF should be clear"); - assert_eq!(flags & CF_BIT, 0, "CF should be clear (denormal1 > denormal2)"); + assert_eq!( + flags & CF_BIT, + 0, + "CF should be clear (denormal1 > denormal2)" + ); } #[test] fn test_fcomi_huge_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xF1, // FCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xF1, // FCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -659,14 +684,15 @@ fn test_fcomi_huge_numbers() { #[test] fn test_fcomip_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xEA, // FLDL2E - 0xDF, 0xF1, // FCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xD9, 0xEA, // FLDL2E + 0xDF, 0xF1, // FCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcos.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcos.rs index 1741ebc5..4e0f03dd 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcos.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fcos.rs @@ -19,12 +19,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,12 +37,12 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fcos_zero() { - let mut emu = emu64(); // cos(0) = 1 + let mut emu = emu64(); // cos(0) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -49,17 +51,21 @@ fn test_fcos_zero() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-10, "cos(0) should be 1.0, got {}", result); + assert!( + (result - 1.0).abs() < 1e-10, + "cos(0) should be 1.0, got {}", + result + ); } #[test] fn test_fcos_pi_over_2() { - let mut emu = emu64(); // cos(π/2) ≈ 0 + let mut emu = emu64(); // cos(π/2) ≈ 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -68,17 +74,21 @@ fn test_fcos_pi_over_2() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-10, "cos(π/2) should be ~0, got {}", result); + assert!( + result.abs() < 1e-10, + "cos(π/2) should be ~0, got {}", + result + ); } #[test] fn test_fcos_pi() { - let mut emu = emu64(); // cos(π) = -1 + let mut emu = emu64(); // cos(π) = -1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -87,17 +97,21 @@ fn test_fcos_pi() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result + 1.0).abs() < 1e-10, "cos(π) should be -1.0, got {}", result); + assert!( + (result + 1.0).abs() < 1e-10, + "cos(π) should be -1.0, got {}", + result + ); } #[test] fn test_fcos_two_pi() { - let mut emu = emu64(); // cos(2π) = 1 + let mut emu = emu64(); // cos(2π) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -106,17 +120,21 @@ fn test_fcos_two_pi() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-10, "cos(2π) should be 1.0, got {}", result); + assert!( + (result - 1.0).abs() < 1e-10, + "cos(2π) should be 1.0, got {}", + result + ); } #[test] fn test_fcos_pi_over_4() { - let mut emu = emu64(); // cos(π/4) ≈ √2/2 ≈ 0.7071 + let mut emu = emu64(); // cos(π/4) ≈ √2/2 ≈ 0.7071 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -126,17 +144,21 @@ fn test_fcos_pi_over_4() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1.0 / 2.0_f64.sqrt(); - assert!((result - expected).abs() < 1e-10, "cos(π/4) should be √2/2, got {}", result); + assert!( + (result - expected).abs() < 1e-10, + "cos(π/4) should be √2/2, got {}", + result + ); } #[test] fn test_fcos_pi_over_3() { - let mut emu = emu64(); // cos(π/3) = 0.5 + let mut emu = emu64(); // cos(π/3) = 0.5 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -145,17 +167,21 @@ fn test_fcos_pi_over_3() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 0.5).abs() < 1e-10, "cos(π/3) should be 0.5, got {}", result); + assert!( + (result - 0.5).abs() < 1e-10, + "cos(π/3) should be 0.5, got {}", + result + ); } #[test] fn test_fcos_pi_over_6() { - let mut emu = emu64(); // cos(π/6) ≈ √3/2 ≈ 0.866 + let mut emu = emu64(); // cos(π/6) ≈ √3/2 ≈ 0.866 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -165,7 +191,11 @@ fn test_fcos_pi_over_6() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 3.0_f64.sqrt() / 2.0; - assert!((result - expected).abs() < 1e-10, "cos(π/6) should be √3/2, got {}", result); + assert!( + (result - expected).abs() < 1e-10, + "cos(π/6) should be √3/2, got {}", + result + ); } // ============================================================================ @@ -174,12 +204,12 @@ fn test_fcos_pi_over_6() { #[test] fn test_fcos_negative_pi_over_2() { - let mut emu = emu64(); // cos(-π/2) ≈ 0 + let mut emu = emu64(); // cos(-π/2) ≈ 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -188,17 +218,21 @@ fn test_fcos_negative_pi_over_2() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-10, "cos(-π/2) should be ~0, got {}", result); + assert!( + result.abs() < 1e-10, + "cos(-π/2) should be ~0, got {}", + result + ); } #[test] fn test_fcos_negative_pi() { - let mut emu = emu64(); // cos(-π) = -1 + let mut emu = emu64(); // cos(-π) = -1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -207,17 +241,21 @@ fn test_fcos_negative_pi() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result + 1.0).abs() < 1e-10, "cos(-π) should be -1.0, got {}", result); + assert!( + (result + 1.0).abs() < 1e-10, + "cos(-π) should be -1.0, got {}", + result + ); } #[test] fn test_fcos_negative_pi_over_4() { - let mut emu = emu64(); // cos(-π/4) = cos(π/4) ≈ √2/2 + let mut emu = emu64(); // cos(-π/4) = cos(π/4) ≈ √2/2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -227,7 +265,11 @@ fn test_fcos_negative_pi_over_4() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1.0 / 2.0_f64.sqrt(); - assert!((result - expected).abs() < 1e-10, "cos(-π/4) should be √2/2, got {}", result); + assert!( + (result - expected).abs() < 1e-10, + "cos(-π/4) should be √2/2, got {}", + result + ); } // ============================================================================ @@ -236,12 +278,12 @@ fn test_fcos_negative_pi_over_4() { #[test] fn test_fcos_small_positive() { - let mut emu = emu64(); // cos(0.1) ≈ 0.995 + let mut emu = emu64(); // cos(0.1) ≈ 0.995 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -256,12 +298,12 @@ fn test_fcos_small_positive() { #[test] fn test_fcos_small_negative() { - let mut emu = emu64(); // cos(-0.1) ≈ 0.995 + let mut emu = emu64(); // cos(-0.1) ≈ 0.995 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -276,12 +318,12 @@ fn test_fcos_small_negative() { #[test] fn test_fcos_very_small() { - let mut emu = emu64(); // cos(0.001) ≈ 1.0 + let mut emu = emu64(); // cos(0.001) ≈ 1.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -300,31 +342,36 @@ fn test_fcos_very_small() { #[test] fn test_fcos_three_pi_over_2() { - let mut emu = emu64(); // cos(3π/2) ≈ 0 + let mut emu = emu64(); // cos(3π/2) ≈ 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-10, "cos(3π/2) should be ~0, got {}", result); + assert!( + result.abs() < 1e-10, + "cos(3π/2) should be ~0, got {}", + result + ); } #[test] fn test_fcos_four_pi() { - let mut emu = emu64(); // cos(4π) = 1 + let mut emu = emu64(); // cos(4π) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -333,17 +380,21 @@ fn test_fcos_four_pi() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-10, "cos(4π) should be 1.0, got {}", result); + assert!( + (result - 1.0).abs() < 1e-10, + "cos(4π) should be 1.0, got {}", + result + ); } #[test] fn test_fcos_six_pi() { - let mut emu = emu64(); // cos(6π) = 1 + let mut emu = emu64(); // cos(6π) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -352,7 +403,11 @@ fn test_fcos_six_pi() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-10, "cos(6π) should be 1.0, got {}", result); + assert!( + (result - 1.0).abs() < 1e-10, + "cos(6π) should be 1.0, got {}", + result + ); } // ============================================================================ @@ -361,12 +416,12 @@ fn test_fcos_six_pi() { #[test] fn test_fcos_ten() { - let mut emu = emu64(); // cos(10) + let mut emu = emu64(); // cos(10) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -381,12 +436,12 @@ fn test_fcos_ten() { #[test] fn test_fcos_hundred() { - let mut emu = emu64(); // cos(100) + let mut emu = emu64(); // cos(100) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -401,12 +456,12 @@ fn test_fcos_hundred() { #[test] fn test_fcos_thousand() { - let mut emu = emu64(); // cos(1000) + let mut emu = emu64(); // cos(1000) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -425,12 +480,12 @@ fn test_fcos_thousand() { #[test] fn test_fcos_symmetry_1() { - let mut emu = emu64(); // cos(x) = cos(-x) + let mut emu = emu64(); // cos(x) = cos(-x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let angle = 1.234; @@ -445,17 +500,20 @@ fn test_fcos_symmetry_1() { emu.run(None).unwrap(); let result_neg = emu.maps.read_f64(0x3000).unwrap(); - assert!((result_pos - result_neg).abs() < 1e-10, "cos(x) should equal cos(-x)"); + assert!( + (result_pos - result_neg).abs() < 1e-10, + "cos(x) should equal cos(-x)" + ); } #[test] fn test_fcos_symmetry_pi_3() { - let mut emu = emu64(); // cos(x) = cos(-x) for x = π/3 + let mut emu = emu64(); // cos(x) = cos(-x) for x = π/3 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let angle = std::f64::consts::FRAC_PI_3; @@ -470,7 +528,10 @@ fn test_fcos_symmetry_pi_3() { emu.run(None).unwrap(); let result_neg = emu.maps.read_f64(0x3000).unwrap(); - assert!((result_pos - result_neg).abs() < 1e-10, "cos(π/3) should equal cos(-π/3)"); + assert!( + (result_pos - result_neg).abs() < 1e-10, + "cos(π/3) should equal cos(-π/3)" + ); } // ============================================================================ @@ -479,23 +540,28 @@ fn test_fcos_symmetry_pi_3() { #[test] fn test_fcos_result_in_range() { - let mut emu = emu64(); let test_values = vec![0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0, -0.5, -1.0, -2.0]; + let mut emu = emu64(); + let test_values = vec![0.0, 0.5, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0, -0.5, -1.0, -2.0]; let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; for val in test_values { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result >= -1.0 && result <= 1.0, - "cos({}) = {} should be in range [-1, 1]", val, result); + assert!( + result >= -1.0 && result <= 1.0, + "cos({}) = {} should be in range [-1, 1]", + val, + result + ); } } @@ -505,11 +571,12 @@ fn test_fcos_result_in_range() { #[test] fn test_fcos_quadrant_1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -522,53 +589,68 @@ fn test_fcos_quadrant_1() { #[test] fn test_fcos_quadrant_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_4); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_4); emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result < 0.0 && result > -1.0, "cos(3π/4) should be in (-1, 0)"); + assert!( + result < 0.0 && result > -1.0, + "cos(3π/4) should be in (-1, 0)" + ); } #[test] fn test_fcos_quadrant_3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 5.0 * std::f64::consts::FRAC_PI_4); + emu.maps + .write_f64(0x2000, 5.0 * std::f64::consts::FRAC_PI_4); emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result < 0.0 && result > -1.0, "cos(5π/4) should be in (-1, 0)"); + assert!( + result < 0.0 && result > -1.0, + "cos(5π/4) should be in (-1, 0)" + ); } #[test] fn test_fcos_quadrant_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 7.0 * std::f64::consts::FRAC_PI_4); + emu.maps + .write_f64(0x2000, 7.0 * std::f64::consts::FRAC_PI_4); emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result > 0.0 && result < 1.0, "cos(7π/4) should be in (0, 1)"); + assert!( + result > 0.0 && result < 1.0, + "cos(7π/4) should be in (0, 1)" + ); } // ============================================================================ @@ -577,14 +659,15 @@ fn test_fcos_quadrant_4() { #[test] fn test_fcos_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -601,13 +684,13 @@ fn test_fcos_sequence() { #[test] fn test_fcos_twice() { - let mut emu = emu64(); // cos(cos(x)) + let mut emu = emu64(); // cos(cos(x)) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xD9, 0xFF, // FCOS (again) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xD9, 0xFF, // FCOS (again) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -626,12 +709,12 @@ fn test_fcos_twice() { #[test] fn test_fcos_positive_zero() { - let mut emu = emu64(); // cos(+0) = 1 + let mut emu = emu64(); // cos(+0) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -640,17 +723,20 @@ fn test_fcos_positive_zero() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-15, "cos(+0) should be exactly 1.0"); + assert!( + (result - 1.0).abs() < 1e-15, + "cos(+0) should be exactly 1.0" + ); } #[test] fn test_fcos_negative_zero() { - let mut emu = emu64(); // cos(-0) = 1 + let mut emu = emu64(); // cos(-0) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -659,16 +745,20 @@ fn test_fcos_negative_zero() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-15, "cos(-0) should be exactly 1.0"); + assert!( + (result - 1.0).abs() < 1e-15, + "cos(-0) should be exactly 1.0" + ); } #[test] fn test_fcos_various_angles() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_angles = vec![0.25, 0.75, 1.25, 2.5, 3.5, 4.5, 5.5]; @@ -676,21 +766,27 @@ fn test_fcos_various_angles() { for angle in test_angles { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, angle); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = angle.cos(); - assert!((result - expected).abs() < 1e-10, - "cos({}) mismatch: expected {}, got {}", angle, expected, result); + assert!( + (result - expected).abs() < 1e-10, + "cos({}) mismatch: expected {}, got {}", + angle, + expected, + result + ); } } #[test] fn test_fcos_arbitrary_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![0.12345, 1.98765, 2.71828, 3.33333, 5.55555]; @@ -698,10 +794,9 @@ fn test_fcos_arbitrary_values() { for val in test_values { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = val.cos(); - assert!((result - expected).abs() < 1e-10, - "cos({}) mismatch", val); + assert!((result - expected).abs() < 1e-10, "cos({}) mismatch", val); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fdiv.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fdiv.rs index 287aa5a6..da359baf 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fdiv.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fdiv.rs @@ -15,23 +15,28 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f32(mem: u64, addr: u64, value: f32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -42,11 +47,10 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fdiv_m32fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -58,11 +62,10 @@ fn test_fdiv_m32fp_basic() { #[test] fn test_fdiv_m32fp_fractional_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -75,11 +78,10 @@ fn test_fdiv_m32fp_fractional_result() { #[test] fn test_fdiv_m32fp_negative_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -10.0); @@ -91,11 +93,10 @@ fn test_fdiv_m32fp_negative_result() { #[test] fn test_fdiv_m32fp_both_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -10.0); @@ -111,11 +112,10 @@ fn test_fdiv_m32fp_both_negative() { #[test] fn test_fdiv_m64fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -127,11 +127,10 @@ fn test_fdiv_m64fp_basic() { #[test] fn test_fdiv_m64fp_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -148,12 +147,11 @@ fn test_fdiv_m64fp_precision() { #[test] fn test_fdiv_st0_st1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xF1, // FDIV ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xF1, // FDIV ST(0), ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -169,13 +167,11 @@ fn test_fdiv_st0_st1() { #[test] fn test_fdiv_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0xF9, // FDIV ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0xF9, // FDIV ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -192,12 +188,11 @@ fn test_fdiv_st1_st0() { #[test] fn test_fdivp_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xF9, // FDIVP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xF9, // FDIVP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -213,11 +208,10 @@ fn test_fdivp_st1_st0() { #[test] fn test_fidiv_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -229,11 +223,10 @@ fn test_fidiv_m16int_positive() { #[test] fn test_fidiv_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 50.0); @@ -249,11 +242,10 @@ fn test_fidiv_m16int_negative() { #[test] fn test_fidiv_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000.0); @@ -269,11 +261,10 @@ fn test_fidiv_m32int_positive() { #[test] fn test_fdivr_m32fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -285,11 +276,10 @@ fn test_fdivr_m32fp_basic() { #[test] fn test_fdivr_m32fp_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -4.0); @@ -305,11 +295,10 @@ fn test_fdivr_m32fp_negative() { #[test] fn test_fdivr_m64fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -325,12 +314,11 @@ fn test_fdivr_m64fp_basic() { #[test] fn test_fdivr_st0_st1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xF9, // FDIVR ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xF9, // FDIVR ST(0), ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -346,13 +334,11 @@ fn test_fdivr_st0_st1() { #[test] fn test_fdivr_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0xF1, // FDIVR ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0xF1, // FDIVR ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -369,12 +355,11 @@ fn test_fdivr_st1_st0() { #[test] fn test_fdivrp_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xF1, // FDIVRP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xF1, // FDIVRP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -390,11 +375,10 @@ fn test_fdivrp_st1_st0() { #[test] fn test_fidivr_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -410,11 +394,10 @@ fn test_fidivr_m16int_positive() { #[test] fn test_fidivr_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 8.0); @@ -430,11 +413,10 @@ fn test_fidivr_m32int_positive() { #[test] fn test_fdiv_infinity_by_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -447,11 +429,10 @@ fn test_fdiv_infinity_by_finite() { #[test] fn test_fdiv_finite_by_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -465,11 +446,10 @@ fn test_fdiv_finite_by_infinity() { #[test] fn test_fdiv_zero_by_nonzero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -482,11 +462,10 @@ fn test_fdiv_zero_by_nonzero() { #[test] fn test_fdiv_nan_propagation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NAN); @@ -498,11 +477,10 @@ fn test_fdiv_nan_propagation() { #[test] fn test_fdiv_sign_rules() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); @@ -524,11 +502,10 @@ fn test_fdiv_sign_rules() { #[test] fn test_fdiv_by_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); @@ -540,17 +517,16 @@ fn test_fdiv_by_one() { #[test] fn test_fdivr_vs_fdiv() { - let mut emu = emu64(); let code1 = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, // FDIV - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code1 = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, + 0x00, // FDIV + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; let code2 = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x3C, 0x25, 0x00, 0x20, 0x00, 0x00, // FDIVR - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, 0x3C, 0x25, 0x00, 0x20, 0x00, + 0x00, // FDIVR + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code1); @@ -570,13 +546,13 @@ fn test_fdivr_vs_fdiv() { #[test] fn test_fdiv_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1000.0 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, // FDIV 10.0 0xDC, 0x34, 0x25, 0x10, 0x20, 0x00, 0x00, // FDIV 5.0 0xDC, 0x34, 0x25, 0x18, 0x20, 0x00, 0x00, // FDIV 2.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000.0); @@ -590,11 +566,10 @@ fn test_fdiv_chain() { #[test] fn test_fidiv_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.5); @@ -606,11 +581,10 @@ fn test_fidiv_precision() { #[test] fn test_fidivr_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -622,11 +596,10 @@ fn test_fidivr_precision() { #[test] fn test_fdiv_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e-100); @@ -638,11 +611,10 @@ fn test_fdiv_very_small() { #[test] fn test_fdiv_very_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e100); @@ -654,14 +626,14 @@ fn test_fdiv_very_large() { #[test] fn test_fdivp_stack_behavior() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 8.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 4.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 16.0 0xDE, 0xF9, // FDIVP ST(1), ST(0) ; ST(1) = 4.0 / 16.0, pop 0xDE, 0xF9, // FDIVP ST(1), ST(0) ; ST(1) = 8.0 / 0.25, pop - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 8.0); @@ -674,12 +646,12 @@ fn test_fdivp_stack_behavior() { #[test] fn test_fdivrp_stack_behavior() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 10.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 50.0 0xDE, 0xF1, // FDIVRP ST(1), ST(0) ; ST(1) = 50.0 / 10.0, pop - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -691,12 +663,10 @@ fn test_fdivrp_stack_behavior() { #[test] fn test_fdiv_reciprocal() { - let mut emu = emu64(); // 1.0 / x gives reciprocal + let mut emu = emu64(); // 1.0 / x gives reciprocal let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -708,11 +678,11 @@ fn test_fdiv_reciprocal() { #[test] fn test_fdivr_inverse_symmetry() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, // FDIVR - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x3C, 0x25, 0x08, 0x20, 0x00, + 0x00, // FDIVR + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -724,11 +694,10 @@ fn test_fdivr_inverse_symmetry() { #[test] fn test_fdiv_zero_sign_preservation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -0.0); @@ -741,13 +710,11 @@ fn test_fdiv_zero_sign_preservation() { #[test] fn test_fdiv_self() { - let mut emu = emu64(); // x / x should equal 1.0 + let mut emu = emu64(); // x / x should equal 1.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xC0, // FLD ST(0) - duplicate + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xC0, // FLD ST(0) - duplicate 0xDE, 0xF9, // FDIVP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fiadd.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fiadd.rs index 4d65c44c..144f98c1 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fiadd.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fiadd.rs @@ -12,19 +12,23 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,7 +39,8 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fiadd_m16int_positive_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD word [0x2008] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] @@ -51,11 +56,10 @@ fn test_fiadd_m16int_positive_basic() { #[test] fn test_fiadd_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -67,11 +71,10 @@ fn test_fiadd_m16int_negative() { #[test] fn test_fiadd_m16int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.14159); @@ -83,11 +86,10 @@ fn test_fiadd_m16int_zero() { #[test] fn test_fiadd_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -99,11 +101,10 @@ fn test_fiadd_m16int_max() { #[test] fn test_fiadd_m16int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -115,11 +116,10 @@ fn test_fiadd_m16int_min() { #[test] fn test_fiadd_m16int_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -100.0); @@ -133,11 +133,10 @@ fn test_fiadd_m16int_result_zero() { #[test] fn test_fiadd_m16int_fractional_base() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.123); @@ -149,11 +148,10 @@ fn test_fiadd_m16int_fractional_base() { #[test] fn test_fiadd_m16int_large_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 30000.0); @@ -165,11 +163,10 @@ fn test_fiadd_m16int_large_positive() { #[test] fn test_fiadd_m16int_large_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -30000.0); @@ -185,11 +182,11 @@ fn test_fiadd_m16int_large_negative() { #[test] fn test_fiadd_m32int_positive_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD dword [0x2008] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, + 0x00, // FIADD dword [0x2008] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -201,11 +198,10 @@ fn test_fiadd_m32int_positive_basic() { #[test] fn test_fiadd_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -217,11 +213,10 @@ fn test_fiadd_m32int_negative() { #[test] fn test_fiadd_m32int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999.999); @@ -233,11 +228,10 @@ fn test_fiadd_m32int_zero() { #[test] fn test_fiadd_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.25); @@ -249,15 +243,15 @@ fn test_fiadd_m32int_large() { #[test] fn test_fiadd_m32int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.75); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), i32::MAX as f64 + 0.75); @@ -265,15 +259,15 @@ fn test_fiadd_m32int_max() { #[test] fn test_fiadd_m32int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.75); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MIN) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MIN) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), i32::MIN as f64 + 0.75); @@ -281,11 +275,10 @@ fn test_fiadd_m32int_min() { #[test] fn test_fiadd_m32int_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -50000.0); @@ -299,15 +292,15 @@ fn test_fiadd_m32int_result_zero() { #[test] fn test_fiadd_m32int_billion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); - emu.maps.write_dword(DATA_ADDR + 8, (1_000_000_000) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (1_000_000_000) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1_000_000_000.5); @@ -319,13 +312,13 @@ fn test_fiadd_m32int_billion() { #[test] fn test_fiadd_multiple_m16() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.5 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD 10 0xDE, 0x04, 0x25, 0x0A, 0x20, 0x00, 0x00, // FIADD 20 0xDE, 0x04, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIADD 30 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -339,13 +332,13 @@ fn test_fiadd_multiple_m16() { #[test] fn test_fiadd_multiple_m32() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.5 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD 10 0xDA, 0x04, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIADD 20 0xDA, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FIADD 30 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -359,12 +352,12 @@ fn test_fiadd_multiple_m32() { #[test] fn test_fiadd_mixed_m16_m32() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD word 100 0xDA, 0x04, 0x25, 0x0A, 0x20, 0x00, 0x00, // FIADD dword 1000 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -377,14 +370,14 @@ fn test_fiadd_mixed_m16_m32() { #[test] fn test_fiadd_alternating_signs() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 0.0 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD 100 0xDA, 0x04, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIADD -50 0xDA, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FIADD 75 0xDA, 0x04, 0x25, 0x14, 0x20, 0x00, 0x00, // FIADD -25 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -403,11 +396,10 @@ fn test_fiadd_alternating_signs() { #[test] fn test_fiadd_m32_to_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -420,11 +412,10 @@ fn test_fiadd_m32_to_infinity() { #[test] fn test_fiadd_m32_to_neg_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NEG_INFINITY); @@ -437,11 +428,10 @@ fn test_fiadd_m32_to_neg_infinity() { #[test] fn test_fiadd_m16_to_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -458,11 +448,10 @@ fn test_fiadd_m16_to_infinity() { #[test] fn test_fiadd_precision_small_int_to_large_float() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e100); @@ -475,14 +464,14 @@ fn test_fiadd_precision_small_int_to_large_float() { #[test] fn test_fiadd_precision_accumulation() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 0.1 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FIADD 1 0xDA, 0x04, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIADD 2 0xDA, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FIADD 3 0xDA, 0x04, 0x25, 0x14, 0x20, 0x00, 0x00, // FIADD 4 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.1); @@ -501,11 +490,10 @@ fn test_fiadd_precision_accumulation() { #[test] fn test_fiadd_m16_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -517,11 +505,10 @@ fn test_fiadd_m16_one() { #[test] fn test_fiadd_m32_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -533,11 +520,10 @@ fn test_fiadd_m32_one() { #[test] fn test_fiadd_m16_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -549,11 +535,10 @@ fn test_fiadd_m16_negative_one() { #[test] fn test_fiadd_m32_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -565,11 +550,10 @@ fn test_fiadd_m32_negative_one() { #[test] fn test_fiadd_very_small_float_with_large_int() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e-100); @@ -581,11 +565,10 @@ fn test_fiadd_very_small_float_with_large_int() { #[test] fn test_fiadd_negative_float_positive_int() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -3.5); @@ -597,11 +580,10 @@ fn test_fiadd_negative_float_positive_int() { #[test] fn test_fiadd_positive_float_negative_int() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.5); @@ -613,12 +595,10 @@ fn test_fiadd_positive_float_negative_int() { #[test] fn test_fiadd_commutative_with_int() { - let mut emu = emu64(); // 5.5 + 10 should equal conceptually the same as 10 + 5.5 + let mut emu = emu64(); // 5.5 + 10 should equal conceptually the same as 10 + 5.5 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.5); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ficom_ficomp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ficom_ficomp.rs index 67711db7..13a2ccaf 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ficom_ficomp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ficom_ficomp.rs @@ -15,26 +15,31 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } #[test] fn test_ficom_m16int_equal() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, // FICOM word [0x2008] 0xDF, 0xE0, // FSTSW AX @@ -53,12 +58,11 @@ fn test_ficom_m16int_equal() { #[test] fn test_ficom_m16int_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDF, 0xE0, // FSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDF, + 0xE0, // FSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 15.0); @@ -72,12 +76,11 @@ fn test_ficom_m16int_greater() { #[test] fn test_ficom_m16int_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDF, 0xE0, // FSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDF, + 0xE0, // FSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -91,12 +94,11 @@ fn test_ficom_m16int_less() { #[test] fn test_ficom_m32int_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, // FICOM dword [0x2008] - 0xDF, 0xE0, - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x14, 0x25, 0x08, 0x20, 0x00, + 0x00, // FICOM dword [0x2008] + 0xDF, 0xE0, 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000.0); @@ -109,12 +111,10 @@ fn test_ficom_m32int_equal() { #[test] fn test_ficom_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDF, 0xE0, - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x14, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDF, + 0xE0, 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -10.0); @@ -128,12 +128,12 @@ fn test_ficom_m32int_negative() { #[test] fn test_ficomp_m16int_pops_stack() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x1C, 0x25, 0x08, 0x20, 0x00, 0x00, // FICOMP word [0x2008] 0xDF, 0xE0, // FSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -146,12 +146,11 @@ fn test_ficomp_m16int_pops_stack() { #[test] fn test_ficomp_m32int_pops_stack() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x1C, 0x25, 0x08, 0x20, 0x00, 0x00, // FICOMP dword [0x2008] - 0xDF, 0xE0, - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x1C, 0x25, 0x08, 0x20, 0x00, + 0x00, // FICOMP dword [0x2008] + 0xDF, 0xE0, 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 500.0); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidiv.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidiv.rs index f3620b0d..62c7d74d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidiv.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidiv.rs @@ -12,19 +12,23 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -32,7 +36,8 @@ fn read_f64(mem: u64, addr: u64) -> f64 { // FIDIV m16int tests #[test] fn test_fidiv_m16int_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, // FIDIV word [0x2008] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] @@ -48,11 +53,10 @@ fn test_fidiv_m16int_basic() { #[test] fn test_fidiv_m16int_negative_divisor() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 15.0); @@ -64,11 +68,10 @@ fn test_fidiv_m16int_negative_divisor() { #[test] fn test_fidiv_m16int_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); @@ -80,11 +83,10 @@ fn test_fidiv_m16int_one() { #[test] fn test_fidiv_m16int_fractional_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -97,28 +99,30 @@ fn test_fidiv_m16int_fractional_result() { #[test] fn test_fidiv_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100000.0); emu.maps.write_word(DATA_ADDR + 8, (i16::MAX) as i16 as u16); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 100000.0 / i16::MAX as f64); + assert_eq!( + emu.maps.read_f64(0x3000).unwrap(), + 100000.0 / i16::MAX as f64 + ); } // FIDIV m32int tests #[test] fn test_fidiv_m32int_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, // FIDIV dword [0x2008] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, + 0x00, // FIDIV dword [0x2008] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000.0); @@ -130,11 +134,10 @@ fn test_fidiv_m32int_basic() { #[test] fn test_fidiv_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -250.0); @@ -146,11 +149,10 @@ fn test_fidiv_m32int_negative() { #[test] fn test_fidiv_m32int_large_divisor() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2000000.0); @@ -162,11 +164,10 @@ fn test_fidiv_m32int_large_divisor() { #[test] fn test_fidiv_m32int_fractional() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -179,13 +180,13 @@ fn test_fidiv_m32int_fractional() { #[test] fn test_fidiv_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1000.0 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, // FIDIV 10 0xDA, 0x34, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIDIV 5 0xDA, 0x34, 0x25, 0x10, 0x20, 0x00, 0x00, // FIDIV 2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000.0); @@ -199,11 +200,10 @@ fn test_fidiv_chain() { #[test] fn test_fidiv_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -216,11 +216,10 @@ fn test_fidiv_infinity() { #[test] fn test_fidiv_zero_dividend() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x34, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidivr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidivr.rs index 0608c435..b47468df 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidivr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fidivr.rs @@ -12,26 +12,31 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } #[test] fn test_fidivr_m16int_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, // FIDIVR word [0x2008] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] @@ -47,11 +52,10 @@ fn test_fidivr_m16int_basic() { #[test] fn test_fidivr_m16int_fractional() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -64,11 +68,10 @@ fn test_fidivr_m16int_fractional() { #[test] fn test_fidivr_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -5.0); @@ -80,11 +83,11 @@ fn test_fidivr_m16int_negative() { #[test] fn test_fidivr_m32int_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, // FIDIVR dword [0x2008] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, + 0x00, // FIDIVR dword [0x2008] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -96,11 +99,10 @@ fn test_fidivr_m32int_basic() { #[test] fn test_fidivr_m32int_zero_dividend() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x3C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fild.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fild.rs index 4889d00b..43805431 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fild.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fild.rs @@ -18,19 +18,23 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i64(mem: u64, addr: u64, value: i64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -41,12 +45,10 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fild_m16int_zero() { - let mut emu = emu64(); // FILD word ptr [0x2000] - // FSTP qword ptr [0x3000] + let mut emu = emu64(); // FILD word ptr [0x2000] + // FSTP qword ptr [0x3000] let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (0) as i16 as u16); @@ -57,10 +59,9 @@ fn test_fild_m16int_zero() { #[test] fn test_fild_m16int_positive_one() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (1) as i16 as u16); @@ -71,10 +72,9 @@ fn test_fild_m16int_positive_one() { #[test] fn test_fild_m16int_negative_one() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (-1) as i16 as u16); @@ -85,10 +85,9 @@ fn test_fild_m16int_negative_one() { #[test] fn test_fild_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (i16::MAX) as i16 as u16); @@ -99,10 +98,9 @@ fn test_fild_m16int_max() { #[test] fn test_fild_m16int_min() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (i16::MIN) as i16 as u16); @@ -113,10 +111,9 @@ fn test_fild_m16int_min() { #[test] fn test_fild_m16int_positive_100() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (100) as i16 as u16); @@ -127,10 +124,9 @@ fn test_fild_m16int_positive_100() { #[test] fn test_fild_m16int_negative_100() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (-100) as i16 as u16); @@ -141,10 +137,9 @@ fn test_fild_m16int_negative_100() { #[test] fn test_fild_m16int_1000() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (1000) as i16 as u16); @@ -155,7 +150,8 @@ fn test_fild_m16int_1000() { #[test] fn test_fild_m16int_multiple() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FILD 10 0xDF, 0x04, 0x25, 0x02, 0x20, 0x00, 0x00, // FILD 20 0xDF, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, // FILD 30 @@ -177,13 +173,11 @@ fn test_fild_m16int_multiple() { #[test] fn test_fild_m16int_arithmetic() { - let mut emu = emu64(); // FILD 5, FILD 3, FADDP -> 8 + let mut emu = emu64(); // FILD 5, FILD 3, FADDP -> 8 let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x04, 0x25, 0x02, 0x20, 0x00, 0x00, - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x04, 0x25, 0x02, 0x20, 0x00, 0x00, 0xDE, + 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (5) as i16 as u16); @@ -199,12 +193,10 @@ fn test_fild_m16int_arithmetic() { #[test] fn test_fild_m32int_zero() { - let mut emu = emu64(); // FILD dword ptr [0x2000] - // FSTP qword ptr [0x3000] + let mut emu = emu64(); // FILD dword ptr [0x2000] + // FSTP qword ptr [0x3000] let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (0) as i32 as u32); @@ -215,10 +207,9 @@ fn test_fild_m32int_zero() { #[test] fn test_fild_m32int_positive_one() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (1) as i32 as u32); @@ -229,10 +220,9 @@ fn test_fild_m32int_positive_one() { #[test] fn test_fild_m32int_negative_one() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (-1) as i32 as u32); @@ -243,10 +233,9 @@ fn test_fild_m32int_negative_one() { #[test] fn test_fild_m32int_max() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (i32::MAX) as i32 as u32); @@ -257,10 +246,9 @@ fn test_fild_m32int_max() { #[test] fn test_fild_m32int_min() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (i32::MIN) as i32 as u32); @@ -271,10 +259,9 @@ fn test_fild_m32int_min() { #[test] fn test_fild_m32int_1000000() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (1000000) as i32 as u32); @@ -285,10 +272,9 @@ fn test_fild_m32int_1000000() { #[test] fn test_fild_m32int_negative_1000000() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (-1000000) as i32 as u32); @@ -299,10 +285,9 @@ fn test_fild_m32int_negative_1000000() { #[test] fn test_fild_m32int_12345() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (12345) as i32 as u32); @@ -313,13 +298,13 @@ fn test_fild_m32int_12345() { #[test] fn test_fild_m32int_large_positive() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); - emu.maps.write_dword(DATA_ADDR, (1_000_000_000) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR, (1_000_000_000) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1_000_000_000.0); @@ -327,13 +312,13 @@ fn test_fild_m32int_large_positive() { #[test] fn test_fild_m32int_large_negative() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); - emu.maps.write_dword(DATA_ADDR, (-1_000_000_000) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR, (-1_000_000_000) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), -1_000_000_000.0); @@ -341,7 +326,8 @@ fn test_fild_m32int_large_negative() { #[test] fn test_fild_m32int_multiple() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FILD 100 0xDB, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, // FILD 200 0xDB, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FILD 300 @@ -363,13 +349,11 @@ fn test_fild_m32int_multiple() { #[test] fn test_fild_m32int_arithmetic() { - let mut emu = emu64(); // FILD 50, FILD 30, FSUBP -> 20 + let mut emu = emu64(); // FILD 50, FILD 30, FSUBP -> 20 let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, - 0xDE, 0xE9, // FSUBP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, 0xDE, + 0xE9, // FSUBP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (50) as i32 as u32); @@ -385,12 +369,10 @@ fn test_fild_m32int_arithmetic() { #[test] fn test_fild_m64int_zero() { - let mut emu = emu64(); // FILD qword ptr [0x2000] - // FSTP qword ptr [0x3000] + let mut emu = emu64(); // FILD qword ptr [0x2000] + // FSTP qword ptr [0x3000] let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (0) as i64 as u64); @@ -401,10 +383,9 @@ fn test_fild_m64int_zero() { #[test] fn test_fild_m64int_positive_one() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (1) as i64 as u64); @@ -415,10 +396,9 @@ fn test_fild_m64int_positive_one() { #[test] fn test_fild_m64int_negative_one() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (-1) as i64 as u64); @@ -429,13 +409,13 @@ fn test_fild_m64int_negative_one() { #[test] fn test_fild_m64int_large_positive() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); - emu.maps.write_qword(DATA_ADDR, (1_000_000_000_000i64) as i64 as u64); + emu.maps + .write_qword(DATA_ADDR, (1_000_000_000_000i64) as i64 as u64); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 1_000_000_000_000.0); @@ -443,13 +423,13 @@ fn test_fild_m64int_large_positive() { #[test] fn test_fild_m64int_large_negative() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); - emu.maps.write_qword(DATA_ADDR, (-1_000_000_000_000i64) as i64 as u64); + emu.maps + .write_qword(DATA_ADDR, (-1_000_000_000_000i64) as i64 as u64); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), -1_000_000_000_000.0); @@ -457,10 +437,9 @@ fn test_fild_m64int_large_negative() { #[test] fn test_fild_m64int_max_safe_integer() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let max_safe = (1i64 << 53) - 1; @@ -472,10 +451,9 @@ fn test_fild_m64int_max_safe_integer() { #[test] fn test_fild_m64int_min_safe_integer() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let min_safe = -((1i64 << 53) - 1); @@ -487,10 +465,9 @@ fn test_fild_m64int_min_safe_integer() { #[test] fn test_fild_m64int_123456789() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (123456789) as i64 as u64); @@ -501,10 +478,9 @@ fn test_fild_m64int_123456789() { #[test] fn test_fild_m64int_negative_123456789() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (-123456789) as i64 as u64); @@ -515,7 +491,8 @@ fn test_fild_m64int_negative_123456789() { #[test] fn test_fild_m64int_multiple() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FILD 1000 0xDF, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FILD 2000 0xDF, 0x2C, 0x25, 0x10, 0x20, 0x00, 0x00, // FILD 3000 @@ -537,13 +514,11 @@ fn test_fild_m64int_multiple() { #[test] fn test_fild_m64int_arithmetic() { - let mut emu = emu64(); // FILD 100, FILD 50, FMULP -> 5000 + let mut emu = emu64(); // FILD 100, FILD 50, FMULP -> 5000 let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC9, // FMULP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (100) as i64 as u64); @@ -559,7 +534,8 @@ fn test_fild_m64int_arithmetic() { #[test] fn test_fild_mixed_sizes() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FILD word 10 0xDB, 0x04, 0x25, 0x02, 0x20, 0x00, 0x00, // FILD dword 20 0xDF, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FILD qword 30 @@ -581,14 +557,14 @@ fn test_fild_mixed_sizes() { #[test] fn test_fild_all_sizes_arithmetic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FILD word 100 0xDB, 0x04, 0x25, 0x02, 0x20, 0x00, 0x00, // FILD dword 1000 0xDE, 0xC1, // FADDP 0xDF, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FILD qword 10000 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (100) as i16 as u16); @@ -605,10 +581,9 @@ fn test_fild_all_sizes_arithmetic() { #[test] fn test_fild_m16int_power_of_two() { - let mut emu = emu64(); let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (1024) as i16 as u16); @@ -619,10 +594,9 @@ fn test_fild_m16int_power_of_two() { #[test] fn test_fild_m32int_power_of_two() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (1 << 20) as i32 as u32); // 1048576 @@ -633,10 +607,9 @@ fn test_fild_m32int_power_of_two() { #[test] fn test_fild_m64int_power_of_two() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (1i64 << 40) as i64 as u64); @@ -647,11 +620,9 @@ fn test_fild_m64int_power_of_two() { #[test] fn test_fild_m16int_all_bits_set() { - let mut emu = emu64(); // -1 in two's complement + let mut emu = emu64(); // -1 in two's complement let code = [ - 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (-1) as i16 as u16); @@ -662,10 +633,9 @@ fn test_fild_m16int_all_bits_set() { #[test] fn test_fild_m32int_all_bits_set() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (-1) as i32 as u32); @@ -676,10 +646,9 @@ fn test_fild_m32int_all_bits_set() { #[test] fn test_fild_m64int_all_bits_set() { - let mut emu = emu64(); let code = [ - 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDF, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, (-1) as i64 as u64); @@ -690,7 +659,8 @@ fn test_fild_m64int_all_bits_set() { #[test] fn test_fild_stack_operations() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDF, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FILD 1 0xDF, 0x04, 0x25, 0x02, 0x20, 0x00, 0x00, // FILD 2 0xDF, 0x04, 0x25, 0x04, 0x20, 0x00, 0x00, // FILD 3 @@ -698,8 +668,7 @@ fn test_fild_stack_operations() { 0xDE, 0xC1, // FADDP ST(1), ST(0) -> 7 0xDE, 0xC1, // FADDP ST(1), ST(0) -> 9 0xDE, 0xC1, // FADDP ST(1), ST(0) -> 10 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, (1) as i16 as u16); @@ -713,10 +682,9 @@ fn test_fild_stack_operations() { #[test] fn test_fild_conversion_exact() { - let mut emu = emu64(); let code = [ - 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDB, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, (42) as i32 as u32); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fimul.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fimul.rs index 63f52ba2..8acba3ca 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fimul.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fimul.rs @@ -12,19 +12,23 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -32,7 +36,8 @@ fn read_f64(mem: u64, addr: u64) -> f64 { // FIMUL m16int tests #[test] fn test_fimul_m16int_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, // FIMUL word [0x2008] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] @@ -48,11 +53,10 @@ fn test_fimul_m16int_basic() { #[test] fn test_fimul_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -64,11 +68,10 @@ fn test_fimul_m16int_negative() { #[test] fn test_fimul_m16int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999.999); @@ -82,11 +85,10 @@ fn test_fimul_m16int_zero() { #[test] fn test_fimul_m16int_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); @@ -98,11 +100,10 @@ fn test_fimul_m16int_one() { #[test] fn test_fimul_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -114,11 +115,10 @@ fn test_fimul_m16int_max() { #[test] fn test_fimul_m16int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -130,11 +130,10 @@ fn test_fimul_m16int_min() { #[test] fn test_fimul_m16int_fractional() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.125); @@ -147,11 +146,11 @@ fn test_fimul_m16int_fractional() { // FIMUL m32int tests #[test] fn test_fimul_m32int_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, // FIMUL dword [0x2008] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, + 0x00, // FIMUL dword [0x2008] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -163,11 +162,10 @@ fn test_fimul_m32int_basic() { #[test] fn test_fimul_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -2.5); @@ -179,11 +177,10 @@ fn test_fimul_m32int_negative() { #[test] fn test_fimul_m32int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999.999); @@ -197,11 +194,10 @@ fn test_fimul_m32int_zero() { #[test] fn test_fimul_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.001); @@ -213,15 +209,15 @@ fn test_fimul_m32int_large() { #[test] fn test_fimul_m32int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 2.0 * i32::MAX as f64); @@ -229,11 +225,10 @@ fn test_fimul_m32int_max() { #[test] fn test_fimul_m32int_commutative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); @@ -245,13 +240,13 @@ fn test_fimul_m32int_commutative() { #[test] fn test_fimul_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 2.0 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, // FIMUL 3 0xDA, 0x0C, 0x25, 0x0C, 0x20, 0x00, 0x00, // FIMUL 4 0xDA, 0x0C, 0x25, 0x10, 0x20, 0x00, 0x00, // FIMUL 5 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -265,11 +260,10 @@ fn test_fimul_chain() { #[test] fn test_fimul_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -282,11 +276,10 @@ fn test_fimul_infinity() { #[test] fn test_fimul_neg_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NEG_INFINITY); @@ -299,11 +292,10 @@ fn test_fimul_neg_infinity() { #[test] fn test_fimul_negative_int_pos_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fincstp_fdecstp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fincstp_fdecstp.rs index 5f0068a5..1028b3dc 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fincstp_fdecstp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fincstp_fdecstp.rs @@ -26,12 +26,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -42,13 +44,13 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fincstp_basic() { - let mut emu = emu64(); // FINCSTP increments TOP, making what was ST(1) become ST(0) + let mut emu = emu64(); // FINCSTP increments TOP, making what was ST(1) become ST(0) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -63,11 +65,12 @@ fn test_fincstp_basic() { #[test] fn test_fincstp_single_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -81,14 +84,15 @@ fn test_fincstp_single_value() { #[test] fn test_fincstp_multiple_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -110,15 +114,15 @@ fn test_fincstp_multiple_values() { #[test] fn test_fdecstp_basic() { - let mut emu = emu64(); // FDECSTP decrements TOP, making what was ST(0) become ST(1) + let mut emu = emu64(); // FDECSTP decrements TOP, making what was ST(0) become ST(1) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -135,12 +139,13 @@ fn test_fdecstp_basic() { #[test] fn test_fdecstp_single_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -149,7 +154,10 @@ fn test_fdecstp_single_value() { emu.run(None).unwrap(); let result1 = emu.maps.read_f64(0x3008).unwrap(); - assert!(result1 == 7.0 || result1 == 0.0, "FDECSTP with single value"); + assert!( + result1 == 7.0 || result1 == 0.0, + "FDECSTP with single value" + ); } // ============================================================================ @@ -158,18 +166,19 @@ fn test_fdecstp_single_value() { #[test] fn test_fincstp_wraparound() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF7, // FINCSTP (1) - 0xD9, 0xF7, // FINCSTP (2) - 0xD9, 0xF7, // FINCSTP (3) - 0xD9, 0xF7, // FINCSTP (4) - 0xD9, 0xF7, // FINCSTP (5) - 0xD9, 0xF7, // FINCSTP (6) - 0xD9, 0xF7, // FINCSTP (7) - 0xD9, 0xF7, // FINCSTP (8) - wrap to 0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF7, // FINCSTP (1) + 0xD9, 0xF7, // FINCSTP (2) + 0xD9, 0xF7, // FINCSTP (3) + 0xD9, 0xF7, // FINCSTP (4) + 0xD9, 0xF7, // FINCSTP (5) + 0xD9, 0xF7, // FINCSTP (6) + 0xD9, 0xF7, // FINCSTP (7) + 0xD9, 0xF7, // FINCSTP (8) - wrap to 0 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -178,23 +187,27 @@ fn test_fincstp_wraparound() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 42.0, "8 FINCSTPs should wrap around to original position"); + assert_eq!( + result, 42.0, + "8 FINCSTPs should wrap around to original position" + ); } #[test] fn test_fdecstp_wraparound() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF6, // FDECSTP (1) - 0xD9, 0xF6, // FDECSTP (2) - 0xD9, 0xF6, // FDECSTP (3) - 0xD9, 0xF6, // FDECSTP (4) - 0xD9, 0xF6, // FDECSTP (5) - 0xD9, 0xF6, // FDECSTP (6) - 0xD9, 0xF6, // FDECSTP (7) - 0xD9, 0xF6, // FDECSTP (8) - wrap to 0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF6, // FDECSTP (1) + 0xD9, 0xF6, // FDECSTP (2) + 0xD9, 0xF6, // FDECSTP (3) + 0xD9, 0xF6, // FDECSTP (4) + 0xD9, 0xF6, // FDECSTP (5) + 0xD9, 0xF6, // FDECSTP (6) + 0xD9, 0xF6, // FDECSTP (7) + 0xD9, 0xF6, // FDECSTP (8) - wrap to 0 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -203,7 +216,10 @@ fn test_fdecstp_wraparound() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 99.0, "8 FDECSTPs should wrap around to original position"); + assert_eq!( + result, 99.0, + "8 FDECSTPs should wrap around to original position" + ); } // ============================================================================ @@ -212,14 +228,14 @@ fn test_fdecstp_wraparound() { #[test] fn test_fincstp_then_fdecstp() { - let mut emu = emu64(); // FINCSTP followed by FDECSTP should cancel out + let mut emu = emu64(); // FINCSTP followed by FDECSTP should cancel out let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -234,14 +250,14 @@ fn test_fincstp_then_fdecstp() { #[test] fn test_fdecstp_then_fincstp() { - let mut emu = emu64(); // FDECSTP followed by FINCSTP should cancel out + let mut emu = emu64(); // FDECSTP followed by FINCSTP should cancel out let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -256,16 +272,17 @@ fn test_fdecstp_then_fincstp() { #[test] fn test_multiple_inc_dec_pairs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -283,15 +300,15 @@ fn test_multiple_inc_dec_pairs() { #[test] fn test_fincstp_rotation() { - let mut emu = emu64(); // FINCSTP rotates stack upward + let mut emu = emu64(); // FINCSTP rotates stack upward let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3 - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3 + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -307,15 +324,15 @@ fn test_fincstp_rotation() { #[test] fn test_fdecstp_rotation() { - let mut emu = emu64(); // FDECSTP rotates stack downward + let mut emu = emu64(); // FDECSTP rotates stack downward let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -335,13 +352,13 @@ fn test_fdecstp_rotation() { #[test] fn test_fincstp_preserves_data() { - let mut emu = emu64(); // FINCSTP should not modify register contents + let mut emu = emu64(); // FINCSTP should not modify register contents let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP (restore) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP (restore) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -356,13 +373,13 @@ fn test_fincstp_preserves_data() { #[test] fn test_fdecstp_preserves_data() { - let mut emu = emu64(); // FDECSTP should not modify register contents + let mut emu = emu64(); // FDECSTP should not modify register contents let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF7, // FINCSTP (restore) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF7, // FINCSTP (restore) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -381,14 +398,15 @@ fn test_fdecstp_preserves_data() { #[test] fn test_fincstp_with_operation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -404,15 +422,16 @@ fn test_fincstp_with_operation() { #[test] fn test_fdecstp_with_operation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xD9, 0xF7, // FINCSTP (restore) - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xD9, 0xF7, // FINCSTP (restore) + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -432,15 +451,16 @@ fn test_fdecstp_with_operation() { #[test] fn test_fincstp_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -454,13 +474,14 @@ fn test_fincstp_sequence() { #[test] fn test_fdecstp_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -474,14 +495,15 @@ fn test_fdecstp_sequence() { #[test] fn test_alternating_inc_dec() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF6, // FDECSTP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF6, // FDECSTP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -490,24 +512,28 @@ fn test_alternating_inc_dec() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 789.0, "Alternating INC/DEC should maintain position"); + assert_eq!( + result, 789.0, + "Alternating INC/DEC should maintain position" + ); } #[test] fn test_fincstp_full_rotation_with_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP - 0xD9, 0xF7, // FINCSTP (full rotation) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP + 0xD9, 0xF7, // FINCSTP (full rotation) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/finit_fninit.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/finit_fninit.rs index 9304fcc2..57dd2ad4 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/finit_fninit.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/finit_fninit.rs @@ -26,46 +26,50 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; // FPU default values -const DEFAULT_CONTROL_WORD: u16 = 0x037F; // Round to nearest, all exceptions masked -const DEFAULT_STATUS_WORD: u16 = 0x0000; // No exceptions, TOP=0 -const DEFAULT_TAG_WORD: u16 = 0xFFFF; // All registers empty +const DEFAULT_CONTROL_WORD: u16 = 0x037F; // Round to nearest, all exceptions masked +const DEFAULT_STATUS_WORD: u16 = 0x0000; // No exceptions, TOP=0 +const DEFAULT_TAG_WORD: u16 = 0xFFFF; // All registers empty // Status word bit definitions -const IE_BIT: u16 = 0x0001; // Invalid Operation -const DE_BIT: u16 = 0x0002; // Denormalized Operand -const ZE_BIT: u16 = 0x0004; // Zero Divide -const OE_BIT: u16 = 0x0008; // Overflow -const UE_BIT: u16 = 0x0010; // Underflow -const PE_BIT: u16 = 0x0020; // Precision -const SF_BIT: u16 = 0x0040; // Stack Fault -const ES_BIT: u16 = 0x0080; // Exception Summary Status -const TOP_MASK: u16 = 0x3800; // TOP bits 11-13 -const C2_BIT: u16 = 0x0400; // Condition Code 2 -const C1_BIT: u16 = 0x0200; // Condition Code 1 -const C3_BIT: u16 = 0x4000; // Condition Code 3 -const C0_BIT: u16 = 0x0100; // Condition Code 0 -const B_BIT: u16 = 0x8000; // Busy +const IE_BIT: u16 = 0x0001; // Invalid Operation +const DE_BIT: u16 = 0x0002; // Denormalized Operand +const ZE_BIT: u16 = 0x0004; // Zero Divide +const OE_BIT: u16 = 0x0008; // Overflow +const UE_BIT: u16 = 0x0010; // Underflow +const PE_BIT: u16 = 0x0020; // Precision +const SF_BIT: u16 = 0x0040; // Stack Fault +const ES_BIT: u16 = 0x0080; // Exception Summary Status +const TOP_MASK: u16 = 0x3800; // TOP bits 11-13 +const C2_BIT: u16 = 0x0400; // Condition Code 2 +const C1_BIT: u16 = 0x0200; // Condition Code 1 +const C3_BIT: u16 = 0x4000; // Condition Code 3 +const C0_BIT: u16 = 0x0100; // Condition Code 0 +const B_BIT: u16 = 0x8000; // Busy // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -76,10 +80,11 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fninit_basic() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -87,17 +92,20 @@ fn test_fninit_basic() { emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(cw, DEFAULT_CONTROL_WORD, "Control word should be 037FH after FNINIT"); + assert_eq!( + cw, DEFAULT_CONTROL_WORD, + "Control word should be 037FH after FNINIT" + ); } #[test] fn test_fninit_clears_status_word() { - let mut emu = emu64(); // FNINIT should clear the status word + let mut emu = emu64(); // FNINIT should clear the status word let code = [ - 0xDB, 0xE3, // FNINIT - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDB, 0xE3, // FNINIT + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -105,17 +113,20 @@ fn test_fninit_clears_status_word() { emu.run(None).unwrap(); let sw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(sw, DEFAULT_STATUS_WORD, "Status word should be 0000H after FNINIT"); + assert_eq!( + sw, DEFAULT_STATUS_WORD, + "Status word should be 0000H after FNINIT" + ); } #[test] fn test_fninit_sets_tag_word() { - let mut emu = emu64(); // FNINIT should set tag word to FFFFH (all registers empty) + let mut emu = emu64(); // FNINIT should set tag word to FFFFH (all registers empty) let code = [ - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (load after init) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (load after init) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -129,14 +140,14 @@ fn test_fninit_sets_tag_word() { #[test] fn test_fninit_resets_top_pointer() { - let mut emu = emu64(); // FNINIT should reset TOP (Top of Stack) pointer to 0 + let mut emu = emu64(); // FNINIT should reset TOP (Top of Stack) pointer to 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (push) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (push) - 0xDB, 0xE3, // FNINIT (reset TOP) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (push) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (push) + 0xDB, 0xE3, // FNINIT (reset TOP) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -152,14 +163,15 @@ fn test_fninit_resets_top_pointer() { #[test] fn test_fninit_multiple_times() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTCW [0x3002] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTCW [0x3002] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -170,8 +182,14 @@ fn test_fninit_multiple_times() { let cw1 = emu.maps.read_word(0x3000).unwrap(); let cw2 = emu.maps.read_word(0x3002).unwrap(); - assert_eq!(cw1, DEFAULT_CONTROL_WORD, "First FNINIT should set CW to 037FH"); - assert_eq!(cw2, DEFAULT_CONTROL_WORD, "Second FNINIT should set CW to 037FH"); + assert_eq!( + cw1, DEFAULT_CONTROL_WORD, + "First FNINIT should set CW to 037FH" + ); + assert_eq!( + cw2, DEFAULT_CONTROL_WORD, + "Second FNINIT should set CW to 037FH" + ); } // ============================================================================ @@ -180,10 +198,11 @@ fn test_fninit_multiple_times() { #[test] fn test_finit_basic() { - let mut emu = emu64(); let code = [ - 0x9B, 0xDB, 0xE3, // FINIT (with FWAIT) - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x9B, 0xDB, 0xE3, // FINIT (with FWAIT) + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -191,17 +210,20 @@ fn test_finit_basic() { emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(cw, DEFAULT_CONTROL_WORD, "Control word should be 037FH after FINIT"); + assert_eq!( + cw, DEFAULT_CONTROL_WORD, + "Control word should be 037FH after FINIT" + ); } #[test] fn test_finit_clears_status_word() { - let mut emu = emu64(); // FINIT should clear the status word + let mut emu = emu64(); // FINIT should clear the status word let code = [ - 0x9B, 0xDB, 0xE3, // FINIT (with FWAIT) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0x9B, 0xDB, 0xE3, // FINIT (with FWAIT) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -209,7 +231,10 @@ fn test_finit_clears_status_word() { emu.run(None).unwrap(); let sw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(sw, DEFAULT_STATUS_WORD, "Status word should be 0000H after FINIT"); + assert_eq!( + sw, DEFAULT_STATUS_WORD, + "Status word should be 0000H after FINIT" + ); } // ============================================================================ @@ -218,17 +243,17 @@ fn test_finit_clears_status_word() { #[test] fn test_finit_vs_fninit() { - let mut emu = emu64(); // FINIT and FNINIT should have same effect in normal operation + let mut emu = emu64(); // FINIT and FNINIT should have same effect in normal operation let code1 = [ - 0x9B, 0xDB, 0xE3, // FINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0x9B, 0xDB, 0xE3, // FINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; let code2 = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -248,15 +273,15 @@ fn test_finit_vs_fninit() { #[test] fn test_fninit_after_arithmetic() { - let mut emu = emu64(); // FNINIT after arithmetic operations should reset state + let mut emu = emu64(); // FNINIT after arithmetic operations should reset state let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDB, 0xE3, // FNINIT - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDB, 0xE3, // FNINIT + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -266,20 +291,23 @@ fn test_fninit_after_arithmetic() { emu.run(None).unwrap(); let sw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(sw, DEFAULT_STATUS_WORD, "Status word should be cleared after FNINIT"); + assert_eq!( + sw, DEFAULT_STATUS_WORD, + "Status word should be cleared after FNINIT" + ); } #[test] fn test_finit_after_comparison() { - let mut emu = emu64(); // FINIT after comparison + let mut emu = emu64(); // FINIT after comparison let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0x9B, 0xDB, 0xE3, // FINIT - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0x9B, 0xDB, 0xE3, // FINIT + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -289,7 +317,10 @@ fn test_finit_after_comparison() { emu.run(None).unwrap(); let sw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(sw, DEFAULT_STATUS_WORD, "Status word should be cleared after FINIT"); + assert_eq!( + sw, DEFAULT_STATUS_WORD, + "Status word should be cleared after FINIT" + ); } // ============================================================================ @@ -298,10 +329,11 @@ fn test_finit_after_comparison() { #[test] fn test_fninit_control_word_precision() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -315,10 +347,11 @@ fn test_fninit_control_word_precision() { #[test] fn test_fninit_control_word_rounding() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -332,10 +365,11 @@ fn test_fninit_control_word_rounding() { #[test] fn test_fninit_control_word_exceptions_masked() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -353,14 +387,14 @@ fn test_fninit_control_word_exceptions_masked() { #[test] fn test_fninit_then_use_fpu() { - let mut emu = emu64(); // FPU should be usable immediately after FNINIT + let mut emu = emu64(); // FPU should be usable immediately after FNINIT let code = [ - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -375,15 +409,16 @@ fn test_fninit_then_use_fpu() { #[test] fn test_fninit_stack_operations() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -407,11 +442,12 @@ fn test_fninit_stack_operations() { #[test] fn test_fninit_clears_exception_flags() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -429,11 +465,12 @@ fn test_fninit_clears_exception_flags() { #[test] fn test_fninit_clears_stack_fault() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -450,15 +487,16 @@ fn test_fninit_clears_stack_fault() { #[test] fn test_fninit_complete_flow() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] (before init) - 0xDB, 0xE3, // FNINIT - 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] (after init) - 0xD9, 0x3C, 0x25, 0x04, 0x30, 0x00, 0x00, // FNSTCW [0x3004] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] (before init) + 0xDB, 0xE3, // FNINIT + 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] (after init) + 0xD9, 0x3C, 0x25, 0x04, 0x30, 0x00, 0x00, // FNSTCW [0x3004] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -469,19 +507,25 @@ fn test_fninit_complete_flow() { let sw_after = emu.maps.read_word(0x3002).unwrap(); let cw = emu.maps.read_word(0x3004).unwrap(); - assert_eq!(sw_after, DEFAULT_STATUS_WORD, "Status word should be default after FNINIT"); - assert_eq!(cw, DEFAULT_CONTROL_WORD, "Control word should be default after FNINIT"); + assert_eq!( + sw_after, DEFAULT_STATUS_WORD, + "Status word should be default after FNINIT" + ); + assert_eq!( + cw, DEFAULT_CONTROL_WORD, + "Control word should be default after FNINIT" + ); } #[test] fn test_finit_preserves_data() { - let mut emu = emu64(); // FINIT doesn't modify register data, just tags them as empty + let mut emu = emu64(); // FINIT doesn't modify register data, just tags them as empty let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDB, 0xE3, // FNINIT (data preserved, tagged empty) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (will use ST(0)) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDB, 0xE3, // FNINIT (data preserved, tagged empty) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (will use ST(0)) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -496,20 +540,21 @@ fn test_finit_preserves_data() { #[test] fn test_multiple_finit_cycles() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // First cycle - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] // Second cycle - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] // Third cycle - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fist_fistp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fist_fistp.rs index 278f4030..f56a6963 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fist_fistp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fist_fistp.rs @@ -21,29 +21,34 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_i16(mem: u64, addr: u64) -> i16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); i16::from_le_bytes(buf) } fn read_i32(mem: u64, addr: u64) -> i32 { - let emu = emu64(); let mut buf = [0u8; 4]; + let emu = emu64(); + let mut buf = [0u8; 4]; emu.maps.read_bytes_buff(&mut buf, addr); i32::from_le_bytes(buf) } fn read_i64(mem: u64, addr: u64) -> i64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); i64::from_le_bytes(buf) } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -54,12 +59,11 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fist_m16int_zero() { - let mut emu = emu64(); // FLD qword ptr [0x2000] - // FIST word ptr [0x3000] + let mut emu = emu64(); // FLD qword ptr [0x2000] + // FIST word ptr [0x3000] let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, // FSTP ST(0) to clean up + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, // FSTP ST(0) to clean up 0xf4, ]; emu.load_code_bytes(&code); @@ -71,11 +75,10 @@ fn test_fist_m16int_zero() { #[test] fn test_fist_m16int_positive_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); @@ -86,11 +89,10 @@ fn test_fist_m16int_positive_one() { #[test] fn test_fist_m16int_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -1.0); @@ -101,11 +103,10 @@ fn test_fist_m16int_negative_one() { #[test] fn test_fist_m16int_100() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -116,11 +117,10 @@ fn test_fist_m16int_100() { #[test] fn test_fist_m16int_negative_100() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -100.0); @@ -131,12 +131,10 @@ fn test_fist_m16int_negative_100() { #[test] fn test_fist_m16int_rounding_down() { - let mut emu = emu64(); // 2.3 should round to 2 (default rounding mode is round-to-nearest-even) + let mut emu = emu64(); // 2.3 should round to 2 (default rounding mode is round-to-nearest-even) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.3); @@ -147,12 +145,10 @@ fn test_fist_m16int_rounding_down() { #[test] fn test_fist_m16int_rounding_up() { - let mut emu = emu64(); // 2.7 should round to 3 + let mut emu = emu64(); // 2.7 should round to 3 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.7); @@ -163,12 +159,10 @@ fn test_fist_m16int_rounding_up() { #[test] fn test_fist_m16int_half_round_even() { - let mut emu = emu64(); // 2.5 should round to 2 (even) + let mut emu = emu64(); // 2.5 should round to 2 (even) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.5); @@ -179,11 +173,10 @@ fn test_fist_m16int_half_round_even() { #[test] fn test_fist_m16int_preserves_st0() { - let mut emu = emu64(); // FIST should not pop the stack + let mut emu = emu64(); // FIST should not pop the stack let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP to verify value still there + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP to verify value still there 0xf4, ]; emu.load_code_bytes(&code); @@ -200,11 +193,9 @@ fn test_fist_m16int_preserves_st0() { #[test] fn test_fistp_m16int_zero() { - let mut emu = emu64(); // FISTP word ptr [0x3000] + let mut emu = emu64(); // FISTP word ptr [0x3000] let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -215,10 +206,9 @@ fn test_fistp_m16int_zero() { #[test] fn test_fistp_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.0); @@ -229,10 +219,9 @@ fn test_fistp_m16int_positive() { #[test] fn test_fistp_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -456.0); @@ -243,10 +232,9 @@ fn test_fistp_m16int_negative() { #[test] fn test_fistp_m16int_rounding() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 99.6); @@ -257,10 +245,9 @@ fn test_fistp_m16int_rounding() { #[test] fn test_fistp_m16int_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, i16::MAX as f64); @@ -271,10 +258,9 @@ fn test_fistp_m16int_max_value() { #[test] fn test_fistp_m16int_min_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, i16::MIN as f64); @@ -289,11 +275,10 @@ fn test_fistp_m16int_min_value() { #[test] fn test_fist_m32int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -304,11 +289,10 @@ fn test_fist_m32int_zero() { #[test] fn test_fist_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 12345.0); @@ -319,11 +303,10 @@ fn test_fist_m32int_positive() { #[test] fn test_fist_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -67890.0); @@ -334,11 +317,10 @@ fn test_fist_m32int_negative() { #[test] fn test_fist_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000000.0); @@ -349,11 +331,10 @@ fn test_fist_m32int_large() { #[test] fn test_fist_m32int_rounding() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1234.8); @@ -364,11 +345,10 @@ fn test_fist_m32int_rounding() { #[test] fn test_fist_m32int_preserves_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x04, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x04, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 9999.0); @@ -384,10 +364,9 @@ fn test_fist_m32int_preserves_st0() { #[test] fn test_fistp_m32int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -398,10 +377,9 @@ fn test_fistp_m32int_zero() { #[test] fn test_fistp_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 987654.0); @@ -412,10 +390,9 @@ fn test_fistp_m32int_positive() { #[test] fn test_fistp_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -123456.0); @@ -426,10 +403,9 @@ fn test_fistp_m32int_negative() { #[test] fn test_fistp_m32int_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, i32::MAX as f64); @@ -440,10 +416,9 @@ fn test_fistp_m32int_max_value() { #[test] fn test_fistp_m32int_min_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, i32::MIN as f64); @@ -458,10 +433,9 @@ fn test_fistp_m32int_min_value() { #[test] fn test_fistp_m64int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -472,10 +446,9 @@ fn test_fistp_m64int_zero() { #[test] fn test_fistp_m64int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123456789.0); @@ -486,10 +459,9 @@ fn test_fistp_m64int_positive() { #[test] fn test_fistp_m64int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -987654321.0); @@ -500,24 +472,25 @@ fn test_fistp_m64int_negative() { #[test] fn test_fistp_m64int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1_000_000_000_000.0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(0x3000).unwrap() as i64, 1_000_000_000_000); + assert_eq!( + emu.maps.read_qword(0x3000).unwrap() as i64, + 1_000_000_000_000 + ); } #[test] fn test_fistp_m64int_rounding() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999999.9); @@ -528,10 +501,9 @@ fn test_fistp_m64int_rounding() { #[test] fn test_fistp_m64int_max_safe_integer() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let max_safe = (1i64 << 53) - 1; @@ -543,10 +515,9 @@ fn test_fistp_m64int_max_safe_integer() { #[test] fn test_fistp_m64int_min_safe_integer() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDF, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let min_safe = -((1i64 << 53) - 1); @@ -562,7 +533,7 @@ fn test_fistp_m64int_min_safe_integer() { #[test] fn test_fist_does_not_pop() { - let mut emu = emu64(); // FIST should preserve stack + let mut emu = emu64(); // FIST should preserve stack let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FIST @@ -580,7 +551,7 @@ fn test_fist_does_not_pop() { #[test] fn test_fistp_pops_stack() { - let mut emu = emu64(); // FISTP should pop the stack + let mut emu = emu64(); // FISTP should pop the stack let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 100 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 200 @@ -603,7 +574,8 @@ fn test_fistp_pops_stack() { #[test] fn test_fistp_all_sizes() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 0xD9, 0xC0, // FLD ST(0) - duplicate 0xD9, 0xC0, // FLD ST(0) - duplicate again @@ -623,7 +595,8 @@ fn test_fistp_all_sizes() { #[test] fn test_fist_fistp_mixed() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 500 0xDB, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FIST (preserve) 0xDB, 0x1C, 0x25, 0x04, 0x30, 0x00, 0x00, // FISTP (pop) @@ -643,47 +616,57 @@ fn test_fist_fistp_mixed() { #[test] fn test_fistp_round_to_nearest_even_positive() { - let mut emu = emu64(); let test_cases = vec![ - (0.5, 0), // 0.5 rounds to 0 (even) - (1.5, 2), // 1.5 rounds to 2 (even) - (2.5, 2), // 2.5 rounds to 2 (even) - (3.5, 4), // 3.5 rounds to 4 (even) + let mut emu = emu64(); + let test_cases = vec![ + (0.5, 0), // 0.5 rounds to 0 (even) + (1.5, 2), // 1.5 rounds to 2 (even) + (2.5, 2), // 2.5 rounds to 2 (even) + (3.5, 4), // 3.5 rounds to 4 (even) ]; for (input, expected) in test_cases { let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, input); - emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(0x3000).unwrap() as i32, expected, "Failed for input {}", input); + emu.run(None).unwrap(); + assert_eq!( + emu.maps.read_dword(0x3000).unwrap() as i32, + expected, + "Failed for input {}", + input + ); } } #[test] fn test_fistp_round_to_nearest_even_negative() { - let mut emu = emu64(); let test_cases = vec![ - (-0.5, 0), // -0.5 rounds to 0 (even) - (-1.5, -2), // -1.5 rounds to -2 (even) - (-2.5, -2), // -2.5 rounds to -2 (even) - (-3.5, -4), // -3.5 rounds to -4 (even) + let mut emu = emu64(); + let test_cases = vec![ + (-0.5, 0), // -0.5 rounds to 0 (even) + (-1.5, -2), // -1.5 rounds to -2 (even) + (-2.5, -2), // -2.5 rounds to -2 (even) + (-3.5, -4), // -3.5 rounds to -4 (even) ]; for (input, expected) in test_cases { let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, input); - emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(0x3000).unwrap() as i32, expected, "Failed for input {}", input); + emu.run(None).unwrap(); + assert_eq!( + emu.maps.read_dword(0x3000).unwrap() as i32, + expected, + "Failed for input {}", + input + ); } } @@ -693,7 +676,8 @@ fn test_fistp_round_to_nearest_even_negative() { #[test] fn test_fistp_after_arithmetic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 10.5 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 20.3 0xDE, 0xC1, // FADDP (30.8) @@ -710,7 +694,8 @@ fn test_fistp_after_arithmetic() { #[test] fn test_fistp_sequential() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3 diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisub.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisub.rs index c88f6312..35cfbaa4 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisub.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisub.rs @@ -12,19 +12,23 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,7 +39,8 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fisub_m16int_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUB word [0x2008] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] @@ -51,11 +56,10 @@ fn test_fisub_m16int_basic() { #[test] fn test_fisub_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -67,11 +71,10 @@ fn test_fisub_m16int_negative() { #[test] fn test_fisub_m16int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.14159); @@ -83,27 +86,28 @@ fn test_fisub_m16int_zero() { #[test] fn test_fisub_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 40000.0); emu.maps.write_word(DATA_ADDR + 8, (i16::MAX) as i16 as u16); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 40000.0 - i16::MAX as f64); + assert_eq!( + emu.maps.read_f64(0x3000).unwrap(), + 40000.0 - i16::MAX as f64 + ); } #[test] fn test_fisub_m16int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -115,11 +119,10 @@ fn test_fisub_m16int_min() { #[test] fn test_fisub_m16int_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -133,11 +136,10 @@ fn test_fisub_m16int_result_zero() { #[test] fn test_fisub_m16int_result_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -153,11 +155,11 @@ fn test_fisub_m16int_result_negative() { #[test] fn test_fisub_m32int_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUB dword [0x2008] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, + 0x00, // FISUB dword [0x2008] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1001.5); @@ -169,11 +171,10 @@ fn test_fisub_m32int_basic() { #[test] fn test_fisub_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -185,11 +186,10 @@ fn test_fisub_m32int_negative() { #[test] fn test_fisub_m32int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999.999); @@ -201,11 +201,10 @@ fn test_fisub_m32int_zero() { #[test] fn test_fisub_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2000000.25); @@ -217,15 +216,15 @@ fn test_fisub_m32int_large() { #[test] fn test_fisub_m32int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5e9); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 5e9 - i32::MAX as f64); @@ -233,15 +232,15 @@ fn test_fisub_m32int_max() { #[test] fn test_fisub_m32int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.75); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MIN) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MIN) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), 0.75 - i32::MIN as f64); @@ -249,11 +248,10 @@ fn test_fisub_m32int_min() { #[test] fn test_fisub_m32int_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 50000.0); @@ -271,13 +269,13 @@ fn test_fisub_m32int_result_zero() { #[test] fn test_fisub_chain_m32() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 100.5 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUB 10 0xDA, 0x24, 0x25, 0x0C, 0x20, 0x00, 0x00, // FISUB 20 0xDA, 0x24, 0x25, 0x10, 0x20, 0x00, 0x00, // FISUB 30 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.5); @@ -291,13 +289,13 @@ fn test_fisub_chain_m32() { #[test] fn test_fisub_alternating_signs() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 100.0 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUB 50 0xDA, 0x24, 0x25, 0x0C, 0x20, 0x00, 0x00, // FISUB -25 0xDA, 0x24, 0x25, 0x10, 0x20, 0x00, 0x00, // FISUB 10 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -315,11 +313,10 @@ fn test_fisub_alternating_signs() { #[test] fn test_fisub_from_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -332,11 +329,10 @@ fn test_fisub_from_infinity() { #[test] fn test_fisub_from_neg_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NEG_INFINITY); @@ -353,11 +349,10 @@ fn test_fisub_from_neg_infinity() { #[test] fn test_fisub_precision_large_minus_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e100); @@ -370,11 +365,10 @@ fn test_fisub_precision_large_minus_small() { #[test] fn test_fisub_fractional_preservation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.123); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisubr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisubr.rs index fd5c092d..344bcb48 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisubr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fisubr.rs @@ -12,19 +12,23 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,14 +39,15 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fisubr_m16int_basic() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUBR word [0x2008] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] 0xf4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(DATA_ADDR, 2.5); // ST(0) + emu.maps.write_f64(DATA_ADDR, 2.5); // ST(0) emu.maps.write_word(DATA_ADDR + 8, (10) as i16 as u16); // Integer operand emu.run(None).unwrap(); @@ -51,11 +56,10 @@ fn test_fisubr_m16int_basic() { #[test] fn test_fisubr_m16int_negative_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 15.0); @@ -67,11 +71,10 @@ fn test_fisubr_m16int_negative_result() { #[test] fn test_fisubr_m16int_negative_operand() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -83,11 +86,10 @@ fn test_fisubr_m16int_negative_operand() { #[test] fn test_fisubr_m16int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.14159); @@ -99,11 +101,10 @@ fn test_fisubr_m16int_zero() { #[test] fn test_fisubr_m16int_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -117,11 +118,10 @@ fn test_fisubr_m16int_result_zero() { #[test] fn test_fisubr_m16int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -133,11 +133,10 @@ fn test_fisubr_m16int_max() { #[test] fn test_fisubr_m16int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -153,11 +152,11 @@ fn test_fisubr_m16int_min() { #[test] fn test_fisubr_m32int_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUBR dword [0x2008] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, + 0x00, // FISUBR dword [0x2008] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -169,11 +168,10 @@ fn test_fisubr_m32int_basic() { #[test] fn test_fisubr_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 150.0); @@ -185,11 +183,10 @@ fn test_fisubr_m32int_negative() { #[test] fn test_fisubr_m32int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 999.999); @@ -201,11 +198,10 @@ fn test_fisubr_m32int_zero() { #[test] fn test_fisubr_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.25); @@ -217,15 +213,15 @@ fn test_fisubr_m32int_large() { #[test] fn test_fisubr_m32int_max() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.75); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MAX) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), i32::MAX as f64 - 0.75); @@ -233,15 +229,15 @@ fn test_fisubr_m32int_max() { #[test] fn test_fisubr_m32int_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.75); - emu.maps.write_dword(DATA_ADDR + 8, (i32::MIN) as i32 as u32); + emu.maps + .write_dword(DATA_ADDR + 8, (i32::MIN) as i32 as u32); emu.run(None).unwrap(); assert_eq!(emu.maps.read_f64(0x3000).unwrap(), i32::MIN as f64 - 0.75); @@ -249,11 +245,10 @@ fn test_fisubr_m32int_min() { #[test] fn test_fisubr_m32int_result_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 50000.0); @@ -271,12 +266,12 @@ fn test_fisubr_m32int_result_zero() { #[test] fn test_fisubr_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FISUBR 100 ; ST(0) = 95 0xDA, 0x2C, 0x25, 0x0C, 0x20, 0x00, 0x00, // FISUBR 200 ; ST(0) = 105 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -293,11 +288,10 @@ fn test_fisubr_chain() { #[test] fn test_fisubr_from_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -310,11 +304,10 @@ fn test_fisubr_from_infinity() { #[test] fn test_fisubr_from_neg_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NEG_INFINITY); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld.rs index c59b4a89..ed2e4b6a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld.rs @@ -19,17 +19,20 @@ const DATA_ADDR: u64 = 0x2000; // Helper to write f32 to memory fn write_f32(mem: u64, addr: u64, value: f32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } // Helper to write f64 to memory fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } // Helper to read ST(0) as f64 from memory after FSTP fn read_st0_as_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -40,9 +43,9 @@ fn read_st0_as_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fld_m32fp_positive_one() { - let mut emu = emu64(); // FLD dword ptr [0x2000] - // FSTP qword ptr [0x3000] ; Store to verify - // HLT + let mut emu = emu64(); // FLD dword ptr [0x2000] + // FSTP qword ptr [0x3000] ; Store to verify + // HLT let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] @@ -58,7 +61,8 @@ fn test_fld_m32fp_positive_one() { #[test] fn test_fld_m32fp_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -73,7 +77,8 @@ fn test_fld_m32fp_zero() { #[test] fn test_fld_m32fp_negative_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -88,7 +93,8 @@ fn test_fld_m32fp_negative_zero() { #[test] fn test_fld_m32fp_negative_one() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -103,7 +109,8 @@ fn test_fld_m32fp_negative_one() { #[test] fn test_fld_m32fp_large_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -118,7 +125,8 @@ fn test_fld_m32fp_large_positive() { #[test] fn test_fld_m32fp_large_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -133,7 +141,8 @@ fn test_fld_m32fp_large_negative() { #[test] fn test_fld_m32fp_small_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -148,7 +157,8 @@ fn test_fld_m32fp_small_positive() { #[test] fn test_fld_m32fp_small_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -163,7 +173,8 @@ fn test_fld_m32fp_small_negative() { #[test] fn test_fld_m32fp_infinity_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -178,7 +189,8 @@ fn test_fld_m32fp_infinity_positive() { #[test] fn test_fld_m32fp_infinity_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -193,7 +205,8 @@ fn test_fld_m32fp_infinity_negative() { #[test] fn test_fld_m32fp_nan() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -208,7 +221,8 @@ fn test_fld_m32fp_nan() { #[test] fn test_fld_m32fp_pi() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -227,9 +241,9 @@ fn test_fld_m32fp_pi() { #[test] fn test_fld_m64fp_positive_one() { - let mut emu = emu64(); // FLD qword ptr [0x2000] - // FSTP qword ptr [0x3000] - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] + // FSTP qword ptr [0x3000] + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] @@ -245,7 +259,8 @@ fn test_fld_m64fp_positive_one() { #[test] fn test_fld_m64fp_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -260,7 +275,8 @@ fn test_fld_m64fp_zero() { #[test] fn test_fld_m64fp_negative_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -275,7 +291,8 @@ fn test_fld_m64fp_negative_zero() { #[test] fn test_fld_m64fp_negative_one() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -290,7 +307,8 @@ fn test_fld_m64fp_negative_one() { #[test] fn test_fld_m64fp_large_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -305,7 +323,8 @@ fn test_fld_m64fp_large_positive() { #[test] fn test_fld_m64fp_large_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -320,7 +339,8 @@ fn test_fld_m64fp_large_negative() { #[test] fn test_fld_m64fp_small_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -335,7 +355,8 @@ fn test_fld_m64fp_small_positive() { #[test] fn test_fld_m64fp_small_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -350,7 +371,8 @@ fn test_fld_m64fp_small_negative() { #[test] fn test_fld_m64fp_infinity_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -365,7 +387,8 @@ fn test_fld_m64fp_infinity_positive() { #[test] fn test_fld_m64fp_infinity_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -380,7 +403,8 @@ fn test_fld_m64fp_infinity_negative() { #[test] fn test_fld_m64fp_nan() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -395,7 +419,8 @@ fn test_fld_m64fp_nan() { #[test] fn test_fld_m64fp_pi() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -410,7 +435,8 @@ fn test_fld_m64fp_pi() { #[test] fn test_fld_m64fp_e() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -429,11 +455,11 @@ fn test_fld_m64fp_e() { #[test] fn test_fld_st0_duplicate_top() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) - // FLD ST(0) ; Duplicate ST(0) - // FSTP qword ptr [0x3000] ; Store top (should be 1.0) - // FSTP qword ptr [0x4000] ; Store next (should also be 1.0) - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) + // FLD ST(0) ; Duplicate ST(0) + // FSTP qword ptr [0x3000] ; Store top (should be 1.0) + // FSTP qword ptr [0x4000] ; Store next (should also be 1.0) + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0xC0, // FLD ST(0) @@ -453,11 +479,11 @@ fn test_fld_st0_duplicate_top() { #[test] fn test_fld_st1() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) - // FLD qword ptr [0x2008] ; Load 2.0 into ST(0), 1.0 is now ST(1) - // FLD ST(1) ; Push ST(1) (1.0) onto stack - // FSTP qword ptr [0x3000] ; Store top (should be 1.0) - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) + // FLD qword ptr [0x2008] ; Load 2.0 into ST(0), 1.0 is now ST(1) + // FLD ST(1) ; Push ST(1) (1.0) onto stack + // FSTP qword ptr [0x3000] ; Store top (should be 1.0) + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] @@ -476,7 +502,8 @@ fn test_fld_st1() { #[test] fn test_fld_st2() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] ; 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] ; 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword ptr [0x2010] ; 3.0 @@ -500,7 +527,8 @@ fn test_fld_st2() { #[test] fn test_fld_stack_push_behavior() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] ; 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] ; 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword ptr [0x2010] ; 3.0 @@ -522,11 +550,11 @@ fn test_fld_stack_push_behavior() { #[test] fn test_fld_multiple_formats() { - let mut emu = emu64(); // FLD dword ptr [0x2000] ; Load f32 - // FLD qword ptr [0x2008] ; Load f64 - // FSTP qword ptr [0x3000] ; Store f64 value - // FSTP qword ptr [0x3008] ; Store f32 value (converted to f64) - // HLT + let mut emu = emu64(); // FLD dword ptr [0x2000] ; Load f32 + // FLD qword ptr [0x2008] ; Load f64 + // FSTP qword ptr [0x3000] ; Store f64 value + // FSTP qword ptr [0x3008] ; Store f32 value (converted to f64) + // HLT let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] @@ -549,7 +577,8 @@ fn test_fld_multiple_formats() { #[test] fn test_fld_max_f32() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -564,7 +593,8 @@ fn test_fld_max_f32() { #[test] fn test_fld_min_positive_f32() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -579,7 +609,8 @@ fn test_fld_min_positive_f32() { #[test] fn test_fld_max_f64() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -594,7 +625,8 @@ fn test_fld_max_f64() { #[test] fn test_fld_min_positive_f64() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -609,7 +641,8 @@ fn test_fld_min_positive_f64() { #[test] fn test_fld_various_fractions() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -620,7 +653,7 @@ fn test_fld_various_fractions() { emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.fpu_mut().get_st(0); assert_eq!(result, val, "Test value {} failed", i); } @@ -628,7 +661,8 @@ fn test_fld_various_fractions() { #[test] fn test_fld_denormal_f32() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD dword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -644,7 +678,8 @@ fn test_fld_denormal_f32() { #[test] fn test_fld_denormal_f64() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -660,10 +695,9 @@ fn test_fld_denormal_f64() { #[test] fn test_fld_m32fp_subnormal() { - let mut emu = emu64(); let code = [ - 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xD9, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let subnormal = f32::from_bits(0x00000001); // Smallest positive subnormal @@ -676,10 +710,9 @@ fn test_fld_m32fp_subnormal() { #[test] fn test_fld_m64fp_subnormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); let subnormal = f64::from_bits(0x0000000000000001); // Smallest positive subnormal @@ -692,14 +725,14 @@ fn test_fld_m64fp_subnormal() { #[test] fn test_fld_st_all_registers() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 3.0 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD 4.0 0xD9, 0xC3, // FLD ST(3) ; Push 1.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld_constants.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld_constants.rs index 3e311de7..0072e895 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld_constants.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fld_constants.rs @@ -34,7 +34,8 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -45,13 +46,13 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fld1_basic() { - let mut emu = emu64(); // FLD1 ; D9 E8 - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLD1 ; D9 E8 + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -64,12 +65,13 @@ fn test_fld1_basic() { #[test] fn test_fld1_multiple() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -84,13 +86,13 @@ fn test_fld1_multiple() { #[test] fn test_fld1_arithmetic() { - let mut emu = emu64(); // FLD1 + FLD1 = 2.0 + let mut emu = emu64(); // FLD1 + FLD1 = 2.0 let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -103,10 +105,11 @@ fn test_fld1_arithmetic() { #[test] fn test_fld1_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -123,13 +126,13 @@ fn test_fld1_precision() { #[test] fn test_fldz_basic() { - let mut emu = emu64(); // FLDZ ; D9 EE - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLDZ ; D9 EE + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -143,12 +146,13 @@ fn test_fldz_basic() { #[test] fn test_fldz_multiple() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -163,13 +167,13 @@ fn test_fldz_multiple() { #[test] fn test_fldz_arithmetic() { - let mut emu = emu64(); // FLDZ + FLD1 = 1.0 + let mut emu = emu64(); // FLDZ + FLD1 = 1.0 let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEE, // FLDZ + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -182,10 +186,11 @@ fn test_fldz_arithmetic() { #[test] fn test_fldz_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -193,7 +198,11 @@ fn test_fldz_precision() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result.to_bits(), 0.0_f64.to_bits(), "FLDZ should be exact positive zero"); + assert_eq!( + result.to_bits(), + 0.0_f64.to_bits(), + "FLDZ should be exact positive zero" + ); } // ============================================================================ @@ -202,13 +211,13 @@ fn test_fldz_precision() { #[test] fn test_fldpi_basic() { - let mut emu = emu64(); // FLDPI ; D9 EB - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLDPI ; D9 EB + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xEB, // FLDPI - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEB, // FLDPI + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -217,15 +226,19 @@ fn test_fldpi_basic() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::PI; - assert!((result - expected).abs() < 1e-15, "FLDPI should load π accurately"); + assert!( + (result - expected).abs() < 1e-15, + "FLDPI should load π accurately" + ); } #[test] fn test_fldpi_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -234,16 +247,21 @@ fn test_fldpi_precision() { let result = emu.maps.read_f64(0x3000).unwrap(); // PI should be very close to standard library value - assert!((result - std::f64::consts::PI).abs() < 1e-15, - "FLDPI precision check: got {}, expected {}", result, std::f64::consts::PI); + assert!( + (result - std::f64::consts::PI).abs() < 1e-15, + "FLDPI precision check: got {}, expected {}", + result, + std::f64::consts::PI + ); } #[test] fn test_fldpi_range() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -251,20 +269,23 @@ fn test_fldpi_range() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result > 3.14159 && result < 3.14160, "FLDPI should be approximately 3.14159"); + assert!( + result > 3.14159 && result < 3.14160, + "FLDPI should be approximately 3.14159" + ); } #[test] fn test_fldpi_arithmetic() { - let mut emu = emu64(); // 2 * π + let mut emu = emu64(); // 2 * π let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + 1 = 2) - 0xDE, 0xC9, // FMULP (π * 2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEB, // FLDPI + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + 1 = 2) + 0xDE, 0xC9, // FMULP (π * 2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -282,13 +303,13 @@ fn test_fldpi_arithmetic() { #[test] fn test_fldl2e_basic() { - let mut emu = emu64(); // FLDL2E ; D9 EA - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLDL2E ; D9 EA + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xEA, // FLDL2E - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEA, // FLDL2E + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -297,15 +318,19 @@ fn test_fldl2e_basic() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::LOG2_E; - assert!((result - expected).abs() < 1e-15, "FLDL2E should load log₂(e)"); + assert!( + (result - expected).abs() < 1e-15, + "FLDL2E should load log₂(e)" + ); } #[test] fn test_fldl2e_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEA, // FLDL2E - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEA, // FLDL2E + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -313,16 +338,21 @@ fn test_fldl2e_precision() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - std::f64::consts::LOG2_E).abs() < 1e-15, - "FLDL2E precision: got {}, expected {}", result, std::f64::consts::LOG2_E); + assert!( + (result - std::f64::consts::LOG2_E).abs() < 1e-15, + "FLDL2E precision: got {}, expected {}", + result, + std::f64::consts::LOG2_E + ); } #[test] fn test_fldl2e_range() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEA, // FLDL2E - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEA, // FLDL2E + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -330,7 +360,10 @@ fn test_fldl2e_range() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result > 1.442 && result < 1.443, "FLDL2E should be approximately 1.4427"); + assert!( + result > 1.442 && result < 1.443, + "FLDL2E should be approximately 1.4427" + ); } // ============================================================================ @@ -339,13 +372,13 @@ fn test_fldl2e_range() { #[test] fn test_fldl2t_basic() { - let mut emu = emu64(); // FLDL2T ; D9 E9 - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLDL2T ; D9 E9 + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xE9, // FLDL2T - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE9, // FLDL2T + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -354,15 +387,19 @@ fn test_fldl2t_basic() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::LOG2_10; - assert!((result - expected).abs() < 1e-15, "FLDL2T should load log₂(10)"); + assert!( + (result - expected).abs() < 1e-15, + "FLDL2T should load log₂(10)" + ); } #[test] fn test_fldl2t_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE9, // FLDL2T - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE9, // FLDL2T + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -370,16 +407,21 @@ fn test_fldl2t_precision() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - std::f64::consts::LOG2_10).abs() < 1e-15, - "FLDL2T precision: got {}, expected {}", result, std::f64::consts::LOG2_10); + assert!( + (result - std::f64::consts::LOG2_10).abs() < 1e-15, + "FLDL2T precision: got {}, expected {}", + result, + std::f64::consts::LOG2_10 + ); } #[test] fn test_fldl2t_range() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE9, // FLDL2T - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE9, // FLDL2T + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -387,7 +429,10 @@ fn test_fldl2t_range() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result > 3.321 && result < 3.322, "FLDL2T should be approximately 3.3219"); + assert!( + result > 3.321 && result < 3.322, + "FLDL2T should be approximately 3.3219" + ); } // ============================================================================ @@ -396,13 +441,13 @@ fn test_fldl2t_range() { #[test] fn test_fldlg2_basic() { - let mut emu = emu64(); // FLDLG2 ; D9 EC - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLDLG2 ; D9 EC + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xEC, // FLDLG2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEC, // FLDLG2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -411,15 +456,19 @@ fn test_fldlg2_basic() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::LOG10_2; - assert!((result - expected).abs() < 1e-15, "FLDLG2 should load log₁₀(2)"); + assert!( + (result - expected).abs() < 1e-15, + "FLDLG2 should load log₁₀(2)" + ); } #[test] fn test_fldlg2_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEC, // FLDLG2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEC, // FLDLG2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -427,16 +476,21 @@ fn test_fldlg2_precision() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - std::f64::consts::LOG10_2).abs() < 1e-15, - "FLDLG2 precision: got {}, expected {}", result, std::f64::consts::LOG10_2); + assert!( + (result - std::f64::consts::LOG10_2).abs() < 1e-15, + "FLDLG2 precision: got {}, expected {}", + result, + std::f64::consts::LOG10_2 + ); } #[test] fn test_fldlg2_range() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEC, // FLDLG2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEC, // FLDLG2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -444,18 +498,21 @@ fn test_fldlg2_range() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result > 0.301 && result < 0.302, "FLDLG2 should be approximately 0.30103"); + assert!( + result > 0.301 && result < 0.302, + "FLDLG2 should be approximately 0.30103" + ); } #[test] fn test_fldlg2_fldl2t_reciprocal() { - let mut emu = emu64(); // log₁₀(2) * log₂(10) should equal 1 + let mut emu = emu64(); // log₁₀(2) * log₂(10) should equal 1 let code = [ - 0xD9, 0xEC, // FLDLG2 - 0xD9, 0xE9, // FLDL2T - 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEC, // FLDLG2 + 0xD9, 0xE9, // FLDL2T + 0xDE, 0xC9, // FMULP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -463,7 +520,10 @@ fn test_fldlg2_fldl2t_reciprocal() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-14, "log₁₀(2) * log₂(10) should equal 1"); + assert!( + (result - 1.0).abs() < 1e-14, + "log₁₀(2) * log₂(10) should equal 1" + ); } // ============================================================================ @@ -472,13 +532,13 @@ fn test_fldlg2_fldl2t_reciprocal() { #[test] fn test_fldln2_basic() { - let mut emu = emu64(); // FLDLN2 ; D9 ED - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLDLN2 ; D9 ED + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xD9, 0xED, // FLDLN2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xED, // FLDLN2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -487,15 +547,19 @@ fn test_fldln2_basic() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::LN_2; - assert!((result - expected).abs() < 1e-15, "FLDLN2 should load ln(2)"); + assert!( + (result - expected).abs() < 1e-15, + "FLDLN2 should load ln(2)" + ); } #[test] fn test_fldln2_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0xED, // FLDLN2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xED, // FLDLN2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -503,16 +567,21 @@ fn test_fldln2_precision() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - std::f64::consts::LN_2).abs() < 1e-15, - "FLDLN2 precision: got {}, expected {}", result, std::f64::consts::LN_2); + assert!( + (result - std::f64::consts::LN_2).abs() < 1e-15, + "FLDLN2 precision: got {}, expected {}", + result, + std::f64::consts::LN_2 + ); } #[test] fn test_fldln2_range() { - let mut emu = emu64(); let code = [ - 0xD9, 0xED, // FLDLN2 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xED, // FLDLN2 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -520,7 +589,10 @@ fn test_fldln2_range() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result > 0.693 && result < 0.694, "FLDLN2 should be approximately 0.69315"); + assert!( + result > 0.693 && result < 0.694, + "FLDLN2 should be approximately 0.69315" + ); } // ============================================================================ @@ -529,22 +601,23 @@ fn test_fldln2_range() { #[test] fn test_all_constants_loaded() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xD9, 0xEB, // FLDPI - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xD9, 0xEA, // FLDL2E - 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] - 0xD9, 0xE9, // FLDL2T - 0xDD, 0x1C, 0x25, 0x20, 0x30, 0x00, 0x00, // FSTP qword [0x3020] - 0xD9, 0xEC, // FLDLG2 - 0xDD, 0x1C, 0x25, 0x28, 0x30, 0x00, 0x00, // FSTP qword [0x3028] - 0xD9, 0xED, // FLDLN2 - 0xDD, 0x1C, 0x25, 0x30, 0x30, 0x00, 0x00, // FSTP qword [0x3030] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xD9, 0xEB, // FLDPI + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xD9, 0xEA, // FLDL2E + 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] + 0xD9, 0xE9, // FLDL2T + 0xDD, 0x1C, 0x25, 0x20, 0x30, 0x00, 0x00, // FSTP qword [0x3020] + 0xD9, 0xEC, // FLDLG2 + 0xDD, 0x1C, 0x25, 0x28, 0x30, 0x00, 0x00, // FSTP qword [0x3028] + 0xD9, 0xED, // FLDLN2 + 0xDD, 0x1C, 0x25, 0x30, 0x30, 0x00, 0x00, // FSTP qword [0x3030] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -570,14 +643,15 @@ fn test_all_constants_loaded() { #[test] fn test_constant_stack_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xEB, // FLDPI - 0xD9, 0xEA, // FLDL2E - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] (L2E) - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] (PI) - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] (1) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xEB, // FLDPI + 0xD9, 0xEA, // FLDL2E + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] (L2E) + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] (PI) + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] (1) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -595,24 +669,25 @@ fn test_constant_stack_operations() { #[test] fn test_pi_circle_circumference() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + π, but we want 2) - 0xD9, 0xEE, // FLDZ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + 1) - 0xD9, 0xE0, // FCHS (negate to clear stack) - 0xDD, 0xD8, // FSTP ST(0) (pop) + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + π, but we want 2) + 0xD9, 0xEE, // FLDZ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + 1) + 0xD9, 0xE0, // FCHS (negate to clear stack) + 0xDD, 0xD8, // FSTP ST(0) (pop) // Restart: 2 * π - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (2) - 0xD9, 0xEB, // FLDPI - 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (2) + 0xD9, 0xEB, // FLDPI + 0xDE, 0xC9, // FMULP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -621,17 +696,21 @@ fn test_pi_circle_circumference() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0 * std::f64::consts::PI; - assert!((result - expected).abs() < 1e-14, "2π calculation from constants"); + assert!( + (result - expected).abs() < 1e-14, + "2π calculation from constants" + ); } #[test] fn test_e_from_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xED, // FLDLN2 (ln(2)) - 0xD9, 0xEA, // FLDL2E (log₂(e)) - 0xDE, 0xC9, // FMULP (ln(2) * log₂(e)) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xED, // FLDLN2 (ln(2)) + 0xD9, 0xEA, // FLDL2E (log₂(e)) + 0xDE, 0xC9, // FMULP (ln(2) * log₂(e)) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -640,17 +719,21 @@ fn test_e_from_constants() { let result = emu.maps.read_f64(0x3000).unwrap(); // ln(2) * log₂(e) = ln(e) = 1 - assert!((result - 1.0).abs() < 1e-14, "ln(2) * log₂(e) should equal 1"); + assert!( + (result - 1.0).abs() < 1e-14, + "ln(2) * log₂(e) should equal 1" + ); } #[test] fn test_constant_combinations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEA, // FLDL2E - 0xD9, 0xED, // FLDLN2 - 0xDE, 0xF9, // FDIVP (log₂(e) / ln(2)) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEA, // FLDL2E + 0xD9, 0xED, // FLDLN2 + 0xDE, 0xF9, // FDIVP (log₂(e) / ln(2)) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -665,13 +748,13 @@ fn test_constant_combinations() { #[test] fn test_fld1_fldz_subtraction() { - let mut emu = emu64(); // 1 - 0 = 1 + let mut emu = emu64(); // 1 - 0 = 1 let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xEE, // FLDZ - 0xDE, 0xE9, // FSUBP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE8, // FLD1 + 0xD9, 0xEE, // FLDZ + 0xDE, 0xE9, // FSUBP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -684,15 +767,15 @@ fn test_fld1_fldz_subtraction() { #[test] fn test_fldpi_divided_by_2() { - let mut emu = emu64(); // π / 2 + let mut emu = emu64(); // π / 2 let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (2) - 0xDE, 0xF9, // FDIVP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEB, // FLDPI + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (2) + 0xDE, 0xF9, // FDIVP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -706,13 +789,13 @@ fn test_fldpi_divided_by_2() { #[test] fn test_constant_multiply_by_zero() { - let mut emu = emu64(); // π * 0 = 0 + let mut emu = emu64(); // π * 0 = 0 let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xEE, // FLDZ - 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xEB, // FLDPI + 0xD9, 0xEE, // FLDZ + 0xDE, 0xC9, // FMULP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -725,13 +808,13 @@ fn test_constant_multiply_by_zero() { #[test] fn test_fld1_squared() { - let mut emu = emu64(); // 1 * 1 = 1 + let mut emu = emu64(); // 1 * 1 = 1 let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC9, // FMULP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -744,16 +827,17 @@ fn test_fld1_squared() { #[test] fn test_all_logs_positive() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEA, // FLDL2E - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xD9, 0xE9, // FLDL2T - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xD9, 0xEC, // FLDLG2 - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xD9, 0xED, // FLDLN2 - 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEA, // FLDL2E + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xD9, 0xE9, // FLDL2T + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xD9, 0xEC, // FLDLG2 + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xD9, 0xED, // FLDLN2 + 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldcw_fstcw.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldcw_fstcw.rs index 07d9ab86..d725c6c7 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldcw_fstcw.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldcw_fstcw.rs @@ -31,24 +31,28 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -73,9 +77,10 @@ const CW_ROUNDING_TRUNC: u16 = 0x0C00; #[test] fn test_fnstcw_basic() { - let mut emu = emu64(); let code = [ - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -88,10 +93,11 @@ fn test_fnstcw_basic() { #[test] fn test_fnstcw_twice() { - let mut emu = emu64(); let code = [ - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xD9, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTCW [0x3002] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xD9, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTCW [0x3002] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -109,10 +115,11 @@ fn test_fnstcw_twice() { #[test] fn test_fldcw_basic() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -127,19 +134,20 @@ fn test_fldcw_basic() { #[test] fn test_fldcw_different_values() { - let mut emu = emu64(); let test_values = vec![0x027F, 0x037F, 0x047F, 0x0C7F]; + let mut emu = emu64(); + let test_values = vec![0x027F, 0x037F, 0x047F, 0x0C7F]; for test_cw in test_values { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); assert_eq!(cw, test_cw, "Control word 0x{:04X} should match", test_cw); @@ -152,12 +160,13 @@ fn test_fldcw_different_values() { #[test] fn test_rounding_mode_nearest() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -172,12 +181,13 @@ fn test_rounding_mode_nearest() { #[test] fn test_rounding_mode_down() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -192,12 +202,13 @@ fn test_rounding_mode_down() { #[test] fn test_rounding_mode_up() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -212,12 +223,13 @@ fn test_rounding_mode_up() { #[test] fn test_rounding_mode_truncate() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -232,12 +244,13 @@ fn test_rounding_mode_truncate() { #[test] fn test_rounding_mode_truncate_negative() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -256,10 +269,11 @@ fn test_rounding_mode_truncate_negative() { #[test] fn test_exception_mask_all_set() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -274,10 +288,11 @@ fn test_exception_mask_all_set() { #[test] fn test_exception_mask_invalid() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -287,7 +302,11 @@ fn test_exception_mask_invalid() { emu.run(None).unwrap(); let result_cw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(result_cw & CW_MASK_INVALID, 0, "Invalid mask should be clear"); + assert_eq!( + result_cw & CW_MASK_INVALID, + 0, + "Invalid mask should be clear" + ); } // ============================================================================ @@ -296,22 +315,20 @@ fn test_exception_mask_invalid() { #[test] fn test_fldcw_fnstcw_roundtrip() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; - let test_values = vec![ - 0x027F, 0x037F, 0x047F, 0x067F, - 0x0B7F, 0x0C7F, 0x0F7F, - ]; + let test_values = vec![0x027F, 0x037F, 0x047F, 0x067F, 0x0B7F, 0x0C7F, 0x0F7F]; for test_cw in test_values { emu.load_code_bytes(&code); emu.maps.write_word(0x2000, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_word(0x3000).unwrap(); assert_eq!(result, test_cw, "Round trip failed for 0x{:04X}", test_cw); @@ -320,11 +337,12 @@ fn test_fldcw_fnstcw_roundtrip() { #[test] fn test_multiple_fldcw() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x2C, 0x25, 0x02, 0x20, 0x00, 0x00, // FLDCW [0x2002] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x2C, 0x25, 0x02, 0x20, 0x00, 0x00, // FLDCW [0x2002] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -343,12 +361,13 @@ fn test_multiple_fldcw() { #[test] fn test_rounding_modes_with_different_values() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![ @@ -363,21 +382,26 @@ fn test_rounding_modes_with_different_values() { emu.maps.write_word(0x2000, 0x037F | mode); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, expected, "Rounding mode 0x{:04X} with input {}", mode, input); + assert_eq!( + result, expected, + "Rounding mode 0x{:04X} with input {}", + mode, input + ); } } #[test] fn test_rounding_negative_values() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![ @@ -391,10 +415,14 @@ fn test_rounding_negative_values() { emu.maps.write_word(0x2000, 0x037F | mode); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, expected, "Rounding mode 0x{:04X} with negative input {}", mode, input); + assert_eq!( + result, expected, + "Rounding mode 0x{:04X} with negative input {}", + mode, input + ); } } @@ -404,15 +432,16 @@ fn test_rounding_negative_values() { #[test] fn test_control_word_persists_across_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDE, 0xC1, // FADDP - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xD9, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTCW [0x3002] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDE, 0xC1, // FADDP + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xD9, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTCW [0x3002] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -433,10 +462,11 @@ fn test_control_word_persists_across_operations() { #[test] fn test_control_word_all_zeros() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -450,10 +480,11 @@ fn test_control_word_all_zeros() { #[test] fn test_control_word_all_ones() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -471,14 +502,15 @@ fn test_control_word_all_ones() { #[test] fn test_fstcw_fnstcw_equivalence() { - let mut emu = emu64(); let code1 = [ - 0x9B, 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code1 = [ + 0x9B, 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTCW [0x3000] + 0xF4, // HLT ]; let code2 = [ - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -498,19 +530,19 @@ fn test_fstcw_fnstcw_equivalence() { #[test] fn test_changing_rounding_modes_dynamically() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Round 2.5 with nearest (should be 2.0) - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - nearest - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - nearest + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] // Round 2.5 with up (should be 3.0) - 0xD9, 0x2C, 0x25, 0x02, 0x20, 0x00, 0x00, // FLDCW [0x2002] - up - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x02, 0x20, 0x00, 0x00, // FLDCW [0x2002] - up + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -528,14 +560,15 @@ fn test_changing_rounding_modes_dynamically() { #[test] fn test_control_word_with_arithmetic() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDE, 0xC1, // FADDP - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDE, 0xC1, // FADDP + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldenv_fstenv.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldenv_fstenv.rs index d465e769..9f9d90c5 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldenv_fstenv.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fldenv_fstenv.rs @@ -31,37 +31,41 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // FPU Environment offsets (28 bytes in protected mode) -const ENV_FCW: usize = 0; // FPU Control Word (2 bytes) -const ENV_FSW: usize = 2; // FPU Status Word (2 bytes) -const ENV_FTW: usize = 4; // FPU Tag Word (2 bytes) -const ENV_FIP: usize = 6; // Instruction Pointer (2 bytes) -const ENV_FCS: usize = 8; // Code Segment (2 bytes) -const ENV_FDP: usize = 10; // Data Pointer (2 bytes) -const ENV_FDS: usize = 12; // Data Segment (2 bytes) -const ENV_SIZE: usize = 28; // Total environment size +const ENV_FCW: usize = 0; // FPU Control Word (2 bytes) +const ENV_FSW: usize = 2; // FPU Status Word (2 bytes) +const ENV_FTW: usize = 4; // FPU Tag Word (2 bytes) +const ENV_FIP: usize = 6; // Instruction Pointer (2 bytes) +const ENV_FCS: usize = 8; // Code Segment (2 bytes) +const ENV_FDP: usize = 10; // Data Pointer (2 bytes) +const ENV_FDS: usize = 12; // Data Segment (2 bytes) +const ENV_SIZE: usize = 28; // Total environment size // Status word bit definitions const IE_BIT: u16 = 0x0001; @@ -80,9 +84,10 @@ const TOP_MASK: u16 = 0x3800; #[test] fn test_fnstenv_basic() { - let mut emu = emu64(); let code = [ - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -95,11 +100,11 @@ fn test_fnstenv_basic() { #[test] fn test_fnstenv_saves_control_word() { - let mut emu = emu64(); // FNSTENV should save the control word + let mut emu = emu64(); // FNSTENV should save the control word let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -113,12 +118,12 @@ fn test_fnstenv_saves_control_word() { #[test] fn test_fnstenv_saves_status_word() { - let mut emu = emu64(); // FNSTENV should save the status word + let mut emu = emu64(); // FNSTENV should save the status word let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -132,12 +137,12 @@ fn test_fnstenv_saves_status_word() { #[test] fn test_fnstenv_saves_tag_word() { - let mut emu = emu64(); // FNSTENV should save the tag word + let mut emu = emu64(); // FNSTENV should save the tag word let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -151,12 +156,13 @@ fn test_fnstenv_saves_tag_word() { #[test] fn test_fnstenv_multiple_times() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xD9, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTENV [0x3200] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xD9, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTENV [0x3200] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -166,7 +172,10 @@ fn test_fnstenv_multiple_times() { let fcw1 = emu.maps.read_word(0x3000 + ENV_FCW as u64).unwrap(); let fcw2 = emu.maps.read_word(0x3200 + ENV_FCW as u64).unwrap(); - assert_eq!(fcw1, fcw2, "Multiple FNSTENV should produce same control word"); + assert_eq!( + fcw1, fcw2, + "Multiple FNSTENV should produce same control word" + ); } // ============================================================================ @@ -175,9 +184,10 @@ fn test_fnstenv_multiple_times() { #[test] fn test_fstenv_basic() { - let mut emu = emu64(); let code = [ - 0x9B, 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTENV [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x9B, 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -190,11 +200,11 @@ fn test_fstenv_basic() { #[test] fn test_fstenv_saves_control_word() { - let mut emu = emu64(); // FSTENV should save the control word + let mut emu = emu64(); // FSTENV should save the control word let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x9B, 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTENV [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x9B, 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -212,15 +222,15 @@ fn test_fstenv_saves_control_word() { #[test] fn test_fstenv_vs_fnstenv() { - let mut emu = emu64(); // FSTENV and FNSTENV should produce same result in normal operation + let mut emu = emu64(); // FSTENV and FNSTENV should produce same result in normal operation let code1 = [ - 0x9B, 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTENV [0x3000] - 0xF4, // HLT + 0x9B, 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTENV [0x3000] + 0xF4, // HLT ]; let code2 = [ - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -240,10 +250,11 @@ fn test_fstenv_vs_fnstenv() { #[test] fn test_fldenv_basic() { - let mut emu = emu64(); let code = [ - 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -257,11 +268,11 @@ fn test_fldenv_basic() { #[test] fn test_fldenv_loads_control_word() { - let mut emu = emu64(); // FLDENV should load the control word + let mut emu = emu64(); // FLDENV should load the control word let code = [ - 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -275,12 +286,12 @@ fn test_fldenv_loads_control_word() { #[test] fn test_fldenv_loads_status_word() { - let mut emu = emu64(); // FLDENV should load the status word + let mut emu = emu64(); // FLDENV should load the status word let code = [ - 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -298,14 +309,14 @@ fn test_fldenv_loads_status_word() { #[test] fn test_fnstenv_fldenv_roundtrip() { - let mut emu = emu64(); // FNSTENV followed by FLDENV should preserve environment + let mut emu = emu64(); // FNSTENV followed by FLDENV should preserve environment let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] (set CW) - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] (save) - 0xD9, 0x2C, 0x25, 0x02, 0x20, 0x00, 0x00, // FLDCW [0x2002] (change CW) - 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] (restore) - 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] (set CW) + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] (save) + 0xD9, 0x2C, 0x25, 0x02, 0x20, 0x00, 0x00, // FLDCW [0x2002] (change CW) + 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] (restore) + 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -315,21 +326,24 @@ fn test_fnstenv_fldenv_roundtrip() { emu.run(None).unwrap(); let restored_cw = emu.maps.read_word(0x4000).unwrap(); - assert_eq!(restored_cw, 0x037F, "CW should be restored to original value"); + assert_eq!( + restored_cw, 0x037F, + "CW should be restored to original value" + ); } #[test] fn test_fnstenv_fldenv_preserves_all_fields() { - let mut emu = emu64(); // FNSTENV/FLDENV should preserve all environment fields + let mut emu = emu64(); // FNSTENV/FLDENV should preserve all environment fields let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDB, 0xE3, // FNINIT - 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] - 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x02, 0x40, 0x00, 0x00, // MOV word [0x4002], AX - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDB, 0xE3, // FNINIT + 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] + 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x02, 0x40, 0x00, 0x00, // MOV word [0x4002], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -349,14 +363,14 @@ fn test_fnstenv_fldenv_preserves_all_fields() { #[test] fn test_fnstenv_after_arithmetic() { - let mut emu = emu64(); // FNSTENV after arithmetic operations + let mut emu = emu64(); // FNSTENV after arithmetic operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -371,14 +385,14 @@ fn test_fnstenv_after_arithmetic() { #[test] fn test_fldenv_then_arithmetic() { - let mut emu = emu64(); // FLDENV followed by arithmetic + let mut emu = emu64(); // FLDENV followed by arithmetic let code = [ - 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] - 0xDD, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FLD qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // FLD qword [0x3008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] + 0xDD, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FLD qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // FLD qword [0x3008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -399,20 +413,20 @@ fn test_fldenv_then_arithmetic() { #[test] fn test_fnstenv_different_control_words() { - let mut emu = emu64(); // FNSTENV should preserve different control word values + let mut emu = emu64(); // FNSTENV should preserve different control word values let test_cws = vec![0x037F, 0x027F, 0x0C7F]; for test_cw in test_cws { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let saved_cw = emu.maps.read_word(0x3000 + ENV_FCW as u64).unwrap(); assert_eq!(saved_cw, test_cw, "CW 0x{:04X} should be saved", test_cw); @@ -421,20 +435,20 @@ fn test_fnstenv_different_control_words() { #[test] fn test_fldenv_different_control_words() { - let mut emu = emu64(); // FLDENV should load different control word values + let mut emu = emu64(); // FLDENV should load different control word values let test_cws = vec![0x037F, 0x027F, 0x0C7F]; for test_cw in test_cws { let code = [ - 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000 + ENV_FCW as u64, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); assert_eq!(cw, test_cw, "CW 0x{:04X} should be loaded", test_cw); @@ -447,11 +461,12 @@ fn test_fldenv_different_control_words() { #[test] fn test_fnstenv_all_fields_valid() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -474,12 +489,13 @@ fn test_fnstenv_all_fields_valid() { #[test] fn test_sequential_fnstenv() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xD9, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTENV [0x3200] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xD9, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTENV [0x3200] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -489,16 +505,20 @@ fn test_sequential_fnstenv() { let fcw1 = emu.maps.read_word(0x3000 + ENV_FCW as u64).unwrap(); let fcw2 = emu.maps.read_word(0x3200 + ENV_FCW as u64).unwrap(); - assert_eq!(fcw1, fcw2, "Sequential FNSTENV should save identical values"); + assert_eq!( + fcw1, fcw2, + "Sequential FNSTENV should save identical values" + ); } #[test] fn test_sequential_fldenv() { - let mut emu = emu64(); let code = [ - 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] - 0xD9, 0x24, 0x25, 0x22, 0x20, 0x00, 0x00, // FLDENV [0x2022] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDENV [0x2000] + 0xD9, 0x24, 0x25, 0x22, 0x20, 0x00, 0x00, // FLDENV [0x2022] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -517,22 +537,23 @@ fn test_sequential_fldenv() { #[test] fn test_fnstenv_fldenv_complete_flow() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Set up a custom control word (truncate toward zero = 0x0F7F) - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] // Load a value - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] // Save environment - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] // Initialize FPU (resets control word to 0x037F) - 0xDB, 0xE3, // FNINIT + 0xDB, 0xE3, // FNINIT // Store control word after FNINIT (should be 0x037F) - 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] + 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] // Restore saved environment - 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] + 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] // Store control word after FLDENV (should be 0x0F7F again) - 0xD9, 0x3C, 0x25, 0x02, 0x40, 0x00, 0x00, // FNSTCW [0x4002] - 0xF4, // HLT + 0xD9, 0x3C, 0x25, 0x02, 0x40, 0x00, 0x00, // FNSTCW [0x4002] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -543,26 +564,33 @@ fn test_fnstenv_fldenv_complete_flow() { let cw_after_fninit = emu.maps.read_word(0x4000).unwrap(); let cw_after_fldenv = emu.maps.read_word(0x4002).unwrap(); - assert_eq!(cw_after_fninit, 0x037F, "Control word after FNINIT should be default"); - assert_eq!(cw_after_fldenv, 0x0F7F, "FLDENV should restore saved control word"); + assert_eq!( + cw_after_fninit, 0x037F, + "Control word after FNINIT should be default" + ); + assert_eq!( + cw_after_fldenv, 0x0F7F, + "FLDENV should restore saved control word" + ); } #[test] fn test_fnstenv_fldenv_multiple_cycles() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Cycle 1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDB, 0xE3, // FNINIT - 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDB, 0xE3, // FNINIT + 0xD9, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FLDENV [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] // Cycle 2 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTENV [0x3200] - 0xDB, 0xE3, // FNINIT - 0xD9, 0x24, 0x25, 0x00, 0x32, 0x00, 0x00, // FLDENV [0x3200] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTENV [0x3200] + 0xDB, 0xE3, // FNINIT + 0xD9, 0x24, 0x25, 0x00, 0x32, 0x00, 0x00, // FLDENV [0x3200] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fmul.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fmul.rs index e29a4e32..b2b6dea8 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fmul.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fmul.rs @@ -11,23 +11,28 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f32(mem: u64, addr: u64, value: f32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -38,11 +43,10 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fmul_m32fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.5); @@ -54,11 +58,10 @@ fn test_fmul_m32fp_basic() { #[test] fn test_fmul_m32fp_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.5); @@ -72,11 +75,10 @@ fn test_fmul_m32fp_zero() { #[test] fn test_fmul_m32fp_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -88,11 +90,10 @@ fn test_fmul_m32fp_negative() { #[test] fn test_fmul_m32fp_both_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -3.0); @@ -108,11 +109,10 @@ fn test_fmul_m32fp_both_negative() { #[test] fn test_fmul_m64fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -124,11 +124,10 @@ fn test_fmul_m64fp_basic() { #[test] fn test_fmul_m64fp_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e10); @@ -140,11 +139,10 @@ fn test_fmul_m64fp_large() { #[test] fn test_fmul_m64fp_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e-10); @@ -160,12 +158,11 @@ fn test_fmul_m64fp_small() { #[test] fn test_fmul_st0_st1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xC9, // FMUL ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xC9, // FMUL ST(0), ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -177,13 +174,11 @@ fn test_fmul_st0_st1() { #[test] fn test_fmul_st0_st2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xD8, 0xCA, // FMUL ST(0), ST(2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xD8, 0xCA, // FMUL ST(0), ST(2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -200,13 +195,11 @@ fn test_fmul_st0_st2() { #[test] fn test_fmul_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0xC9, // FMUL ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0xC9, // FMUL ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -223,12 +216,11 @@ fn test_fmul_st1_st0() { #[test] fn test_fmulp_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC9, // FMULP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC9, // FMULP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -240,13 +232,10 @@ fn test_fmulp_st1_st0() { #[test] fn test_fmulp_no_operand() { - let mut emu = emu64(); // FMULP with no operand = FMULP ST(1), ST(0) + let mut emu = emu64(); // FMULP with no operand = FMULP ST(1), ST(0) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC9, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC9, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 4.0); @@ -262,11 +251,10 @@ fn test_fmulp_no_operand() { #[test] fn test_fimul_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.5); @@ -278,11 +266,10 @@ fn test_fimul_m16int_positive() { #[test] fn test_fimul_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -294,11 +281,10 @@ fn test_fimul_m16int_negative() { #[test] fn test_fimul_m16int_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); @@ -316,11 +302,10 @@ fn test_fimul_m16int_zero() { #[test] fn test_fimul_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.5); @@ -332,11 +317,10 @@ fn test_fimul_m32int_positive() { #[test] fn test_fimul_m32int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.5); @@ -348,11 +332,10 @@ fn test_fimul_m32int_negative() { #[test] fn test_fimul_m32int_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); @@ -368,11 +351,10 @@ fn test_fimul_m32int_large() { #[test] fn test_fmul_infinity_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -385,11 +367,10 @@ fn test_fmul_infinity_finite() { #[test] fn test_fmul_neg_infinity_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NEG_INFINITY); @@ -402,11 +383,10 @@ fn test_fmul_neg_infinity_finite() { #[test] fn test_fmul_infinity_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -419,11 +399,10 @@ fn test_fmul_infinity_negative() { #[test] fn test_fmul_nan_propagation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NAN); @@ -435,11 +414,10 @@ fn test_fmul_nan_propagation() { #[test] fn test_fmul_sign_rules() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); @@ -461,12 +439,10 @@ fn test_fmul_sign_rules() { #[test] fn test_fmul_zero_sign() { - let mut emu = emu64(); // 0.0 * x should preserve sign based on XOR rule + let mut emu = emu64(); // 0.0 * x should preserve sign based on XOR rule let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.0); @@ -480,11 +456,10 @@ fn test_fmul_zero_sign() { #[test] fn test_fmul_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -0.0); @@ -497,18 +472,14 @@ fn test_fmul_negative_zero() { #[test] fn test_fmul_commutative() { - let mut emu = emu64(); // a * b should equal b * a + let mut emu = emu64(); // a * b should equal b * a let code1 = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; let code2 = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code1); @@ -528,12 +499,10 @@ fn test_fmul_commutative() { #[test] fn test_fmul_associative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0x0C, 0x25, 0x10, 0x20, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -546,11 +515,10 @@ fn test_fmul_associative() { #[test] fn test_fmul_by_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 123.456); @@ -562,7 +530,8 @@ fn test_fmul_by_one() { #[test] fn test_fmul_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDE, 0xC9, // FMULP @@ -570,8 +539,7 @@ fn test_fmul_chain() { 0xDE, 0xC9, // FMULP 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD 5.0 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -585,11 +553,10 @@ fn test_fmul_chain() { #[test] fn test_fimul_preserves_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.5); @@ -601,11 +568,10 @@ fn test_fimul_preserves_fraction() { #[test] fn test_fmul_small_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e-100); @@ -617,14 +583,14 @@ fn test_fmul_small_large() { #[test] fn test_fmulp_stack_behavior() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 2.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 3.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 4.0 0xDE, 0xC9, // FMULP ST(1), ST(0) ; ST(1) = 3.0 * 4.0, pop 0xDE, 0xC9, // FMULP ST(1), ST(0) ; ST(1) = 2.0 * 12.0, pop - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 2.0); @@ -637,11 +603,10 @@ fn test_fmulp_stack_behavior() { #[test] fn test_fmul_fractions() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x0C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 0.5); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fninit_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fninit_extended.rs index e9becd37..fae86cb7 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fninit_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fninit_extended.rs @@ -23,30 +23,35 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } #[test] fn test_fninit_basic() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -54,12 +59,13 @@ fn test_fninit_basic() { #[test] fn test_fninit_clears_stack() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 (should work on empty stack) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 (should work on empty stack) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 99.99); @@ -70,11 +76,12 @@ fn test_fninit_clears_stack() { #[test] fn test_fninit_resets_control_word() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, 0x0C7F); @@ -85,18 +92,13 @@ fn test_fninit_resets_control_word() { #[test] fn test_fninit_with_full_stack() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 x8 - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 x8 + 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xDB, + 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] 0xF4, ]; emu.load_code_bytes(&code); @@ -107,13 +109,13 @@ fn test_fninit_with_full_stack() { #[test] fn test_fninit_multiple_times() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -123,14 +125,13 @@ fn test_fninit_multiple_times() { #[test] fn test_fninit_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC1, // FADDP - 0xDB, 0xE3, // FNINIT - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC1, // FADDP + 0xDB, 0xE3, // FNINIT + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 10.0); @@ -142,13 +143,13 @@ fn test_fninit_after_arithmetic() { #[test] fn test_fninit_clears_status() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xD1, // FCOM - 0xDB, 0xE3, // FNINIT - 0xDF, 0xE0, // FNSTSW AX - 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], EAX + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xD1, // FCOM + 0xDB, 0xE3, // FNINIT + 0xDF, 0xE0, // FNSTSW AX + 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], EAX 0xF4, ]; emu.load_code_bytes(&code); @@ -162,14 +163,14 @@ fn test_fninit_clears_status() { // Tests with different pre-init states #[test] fn test_fninit_after_division_by_zero() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xEE, // FLDZ - 0xDE, 0xF9, // FDIVP (may set exception) - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xEE, // FLDZ + 0xDE, 0xF9, // FDIVP (may set exception) + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -179,13 +180,12 @@ fn test_fninit_after_division_by_zero() { #[test] fn test_fninit_after_sqrt_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFA, // FSQRT (may produce NaN) - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFA, // FSQRT (may produce NaN) + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, -1.0); @@ -196,14 +196,14 @@ fn test_fninit_after_sqrt_negative() { #[test] fn test_fninit_sequence_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD - 0xDB, 0xE3, // FNINIT - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD + 0xDB, 0xE3, // FNINIT + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 42.0); @@ -217,87 +217,113 @@ macro_rules! fninit_state_test { ($name:ident, $setup:expr) => { #[test] fn $name() { - let mut emu = emu64(); let mut code = Vec::from($setup); + let mut emu = emu64(); + let mut code = Vec::from($setup); code.extend_from_slice(&[ - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP [0x3000] - 0xF4, // HLT + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP [0x3000] + 0xF4, // HLT ]); emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 100.0); emu.maps.write_f64(0x2008, 200.0); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, 1.0, "Stack should be cleared"); } }; } -fninit_state_test!(test_fninit_after_fld, &[ +fninit_state_test!( + test_fninit_after_fld, + &[ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD -]); - -fninit_state_test!(test_fninit_after_fadd, &[ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP -]); - -fninit_state_test!(test_fninit_after_fmul, &[ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xC9, // FMULP -]); - -fninit_state_test!(test_fninit_after_fsub, &[ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xE9, // FSUBP -]); - -fninit_state_test!(test_fninit_after_fdiv, &[ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xF9, // FDIVP -]); - -fninit_state_test!(test_fninit_after_fsqrt, &[ +] +); + +fninit_state_test!( + test_fninit_after_fadd, + &[ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP + ] +); + +fninit_state_test!( + test_fninit_after_fmul, + &[ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xC9, // FMULP + ] +); + +fninit_state_test!( + test_fninit_after_fsub, + &[ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xE9, // FSUBP + ] +); + +fninit_state_test!( + test_fninit_after_fdiv, + &[ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xF9, // FDIVP + ] +); + +fninit_state_test!( + test_fninit_after_fsqrt, + &[ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFA, // FSQRT -]); +] +); -fninit_state_test!(test_fninit_after_fabs, &[ +fninit_state_test!( + test_fninit_after_fabs, + &[ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xE1, // FABS -]); +] +); -fninit_state_test!(test_fninit_after_fchs, &[ +fninit_state_test!( + test_fninit_after_fchs, + &[ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xE0, // FCHS -]); - -fninit_state_test!(test_fninit_after_fcom, &[ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xD1, // FCOM -]); - -fninit_state_test!(test_fninit_after_fxch, &[ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xC9, // FXCH -]); +] +); + +fninit_state_test!( + test_fninit_after_fcom, + &[ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xD1, // FCOM + ] +); + +fninit_state_test!( + test_fninit_after_fxch, + &[ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD9, + 0xC9, // FXCH + ] +); // Tests with constants #[test] fn test_fninit_after_fldpi() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -307,12 +333,12 @@ fn test_fninit_after_fldpi() { #[test] fn test_fninit_after_fldz() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -322,14 +348,14 @@ fn test_fninit_after_fldz() { #[test] fn test_fninit_after_fld1() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDB, 0xE3, // FNINIT - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDB, 0xE3, // FNINIT + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -340,12 +366,10 @@ fn test_fninit_after_fld1() { // Edge cases #[test] fn test_fninit_with_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0xE3, - 0xD9, 0xE8, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0xE3, 0xD9, 0xE8, 0xDD, 0x1C, 0x25, 0x00, + 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, f64::INFINITY); @@ -356,12 +380,10 @@ fn test_fninit_with_infinity() { #[test] fn test_fninit_with_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDB, 0xE3, - 0xD9, 0xE8, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDB, 0xE3, 0xD9, 0xE8, 0xDD, 0x1C, 0x25, 0x00, + 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, f64::NAN); @@ -373,11 +395,12 @@ fn test_fninit_with_nan() { // Consistency tests #[test] fn test_fninit_idempotent() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xDB, 0xE3, // FNINIT again - 0xD9, 0x3C, 0x25, 0x08, 0x30, 0x00, 0x00, // FNSTCW [0x3008] + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xDB, 0xE3, // FNINIT again + 0xD9, 0x3C, 0x25, 0x08, 0x30, 0x00, 0x00, // FNSTCW [0x3008] 0xF4, ]; emu.load_code_bytes(&code); @@ -389,15 +412,16 @@ fn test_fninit_idempotent() { #[test] fn test_fninit_after_complex_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xEB, // FLDPI - 0xDE, 0xC1, // FADDP - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC9, // FMULP - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xEB, // FLDPI + 0xDE, 0xC1, // FADDP + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC9, // FMULP + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP 0xF4, ]; emu.load_code_bytes(&code); @@ -410,15 +434,10 @@ fn test_fninit_after_complex_operations() { // Stress tests #[test] fn test_fninit_rapid_succession() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, - 0xDB, 0xE3, - 0xDB, 0xE3, - 0xDB, 0xE3, - 0xDB, 0xE3, - 0xD9, 0xE8, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, 0xDB, 0xE3, 0xDB, 0xE3, 0xDB, 0xE3, 0xDB, 0xE3, 0xD9, 0xE8, 0xDD, 0x1C, 0x25, + 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -428,16 +447,16 @@ fn test_fninit_rapid_succession() { #[test] fn test_fninit_alternating_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDB, 0xE3, // FNINIT - 0xD9, 0xEE, // FLDZ - 0xDB, 0xE3, // FNINIT - 0xD9, 0xEB, // FLDPI - 0xDB, 0xE3, // FNINIT - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDB, 0xE3, // FNINIT + 0xD9, 0xEE, // FLDZ + 0xDB, 0xE3, // FNINIT + 0xD9, 0xEB, // FLDPI + 0xDB, 0xE3, // FNINIT + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnop.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnop.rs index 1563cf74..bcc53082 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnop.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnop.rs @@ -18,12 +18,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -34,12 +36,12 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fnop_basic() { - let mut emu = emu64(); // FNOP should do nothing + let mut emu = emu64(); // FNOP should do nothing let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -53,14 +55,14 @@ fn test_fnop_basic() { #[test] fn test_fnop_preserves_value() { - let mut emu = emu64(); // FNOP should preserve the current value on the stack + let mut emu = emu64(); // FNOP should preserve the current value on the stack let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -74,12 +76,12 @@ fn test_fnop_preserves_value() { #[test] fn test_fnop_zero() { - let mut emu = emu64(); // FNOP with zero on stack + let mut emu = emu64(); // FNOP with zero on stack let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -93,12 +95,12 @@ fn test_fnop_zero() { #[test] fn test_fnop_negative() { - let mut emu = emu64(); // FNOP with negative value + let mut emu = emu64(); // FNOP with negative value let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -116,14 +118,14 @@ fn test_fnop_negative() { #[test] fn test_fnop_multiple_stack_values() { - let mut emu = emu64(); // FNOP should not affect any stack values + let mut emu = emu64(); // FNOP should not affect any stack values let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; ST(0) - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; ST(1) - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; ST(0) + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; ST(1) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -140,12 +142,12 @@ fn test_fnop_multiple_stack_values() { #[test] fn test_fnop_does_not_push() { - let mut emu = emu64(); // FNOP should not push onto the stack + let mut emu = emu64(); // FNOP should not push onto the stack let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -159,14 +161,14 @@ fn test_fnop_does_not_push() { #[test] fn test_fnop_does_not_pop() { - let mut emu = emu64(); // FNOP should not pop from the stack + let mut emu = emu64(); // FNOP should not pop from the stack let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -187,14 +189,14 @@ fn test_fnop_does_not_pop() { #[test] fn test_fnop_between_arithmetic() { - let mut emu = emu64(); // FNOP between arithmetic operations + let mut emu = emu64(); // FNOP between arithmetic operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -209,13 +211,13 @@ fn test_fnop_between_arithmetic() { #[test] fn test_fnop_before_operation() { - let mut emu = emu64(); // FNOP before an operation + let mut emu = emu64(); // FNOP before an operation let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xD9, 0xE0, // FCHS (negate) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xD9, 0xE0, // FCHS (negate) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -229,13 +231,13 @@ fn test_fnop_before_operation() { #[test] fn test_fnop_after_operation() { - let mut emu = emu64(); // FNOP after an operation + let mut emu = emu64(); // FNOP after an operation let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -253,12 +255,12 @@ fn test_fnop_after_operation() { #[test] fn test_fnop_infinity() { - let mut emu = emu64(); // FNOP with infinity + let mut emu = emu64(); // FNOP with infinity let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -267,17 +269,20 @@ fn test_fnop_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite() && !result.is_sign_negative(), "FNOP should preserve infinity"); + assert!( + result.is_infinite() && !result.is_sign_negative(), + "FNOP should preserve infinity" + ); } #[test] fn test_fnop_neg_infinity() { - let mut emu = emu64(); // FNOP with negative infinity + let mut emu = emu64(); // FNOP with negative infinity let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -286,17 +291,20 @@ fn test_fnop_neg_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite() && result.is_sign_negative(), "FNOP should preserve -infinity"); + assert!( + result.is_infinite() && result.is_sign_negative(), + "FNOP should preserve -infinity" + ); } #[test] fn test_fnop_nan() { - let mut emu = emu64(); // FNOP with NaN + let mut emu = emu64(); // FNOP with NaN let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -310,12 +318,12 @@ fn test_fnop_nan() { #[test] fn test_fnop_negative_zero() { - let mut emu = emu64(); // FNOP with negative zero + let mut emu = emu64(); // FNOP with negative zero let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -325,7 +333,10 @@ fn test_fnop_negative_zero() { let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, 0.0, "FNOP should preserve -0.0"); - assert!(result.is_sign_negative(), "Sign of -0.0 should be preserved"); + assert!( + result.is_sign_negative(), + "Sign of -0.0 should be preserved" + ); } // ============================================================================ @@ -334,15 +345,16 @@ fn test_fnop_negative_zero() { #[test] fn test_fnop_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -356,16 +368,16 @@ fn test_fnop_sequence() { #[test] fn test_fnop_interleaved() { - let mut emu = emu64(); // FNOP interleaved with operations + let mut emu = emu64(); // FNOP interleaved with operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xD0, // FNOP - 0xDE, 0xC9, // FMULP - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xD0, // FNOP + 0xDE, 0xC9, // FMULP + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -375,7 +387,10 @@ fn test_fnop_interleaved() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 42.0, "Interleaved FNOPs should not affect operations"); + assert_eq!( + result, 42.0, + "Interleaved FNOPs should not affect operations" + ); } // ============================================================================ @@ -384,12 +399,12 @@ fn test_fnop_interleaved() { #[test] fn test_fnop_very_small() { - let mut emu = emu64(); // FNOP with very small value + let mut emu = emu64(); // FNOP with very small value let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -403,12 +418,12 @@ fn test_fnop_very_small() { #[test] fn test_fnop_very_large() { - let mut emu = emu64(); // FNOP with very large value + let mut emu = emu64(); // FNOP with very large value let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -422,12 +437,12 @@ fn test_fnop_very_large() { #[test] fn test_fnop_irrational() { - let mut emu = emu64(); // FNOP with irrational number + let mut emu = emu64(); // FNOP with irrational number let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -441,12 +456,12 @@ fn test_fnop_irrational() { #[test] fn test_fnop_preserves_precision() { - let mut emu = emu64(); // FNOP should preserve full precision + let mut emu = emu64(); // FNOP should preserve full precision let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -461,17 +476,17 @@ fn test_fnop_preserves_precision() { #[test] fn test_fnop_in_loop_context() { - let mut emu = emu64(); // FNOP in a context simulating a loop (multiple operations) + let mut emu = emu64(); // FNOP in a context simulating a loop (multiple operations) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP (iteration 1) - 0xD9, 0xD0, // FNOP (iteration 2) - 0xD9, 0xD0, // FNOP (iteration 3) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xD0, // FNOP - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP (iteration 1) + 0xD9, 0xD0, // FNOP (iteration 2) + 0xD9, 0xD0, // FNOP (iteration 3) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xD0, // FNOP + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnsave_fnop.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnsave_fnop.rs index cf607d39..a2bef09c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnsave_fnop.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fnsave_fnop.rs @@ -4,7 +4,7 @@ //! Extended FNOP - Extended NOP operations //! //! FNSAVE saves the entire FPU state to a 94 or 108 byte memory area, -//! then reinitializes the FPU. The instruction does not check for +//! then reinitializes the FPU. The instruction does not check for //! unmasked floating-point exceptions. //! //! Opcodes: @@ -17,21 +17,25 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -39,9 +43,10 @@ fn read_f64(mem: u64, addr: u64) -> f64 { // FNSAVE tests #[test] fn test_fnsave_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x34, 0x25, 0x00, 0x20, 0x00, 0x00, // FNSAVE [0x2000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x34, 0x25, 0x00, 0x20, 0x00, 0x00, // FNSAVE [0x2000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -51,10 +56,11 @@ fn test_fnsave_basic() { #[test] fn test_fnsave_with_data() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1.5); @@ -65,12 +71,13 @@ fn test_fnsave_with_data() { #[test] fn test_fnsave_reinitializes() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xD9, 0xE8, // FLD1 (should work on empty stack) - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xD9, 0xE8, // FLD1 (should work on empty stack) + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 2.5); @@ -82,9 +89,10 @@ fn test_fnsave_reinitializes() { // FNOP tests #[test] fn test_fnop_basic() { - let mut emu = emu64(); let code = [ - 0xD9, 0xD0, // FNOP - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xD0, // FNOP + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -92,11 +100,12 @@ fn test_fnop_basic() { #[test] fn test_fnop_preserves_stack() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 3.14); @@ -107,11 +116,12 @@ fn test_fnop_preserves_stack() { #[test] fn test_fnop_sequence() { - let mut emu = emu64(); let code = [ - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xD9, 0xD0, // FNOP - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xD9, 0xD0, // FNOP + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -120,11 +130,12 @@ fn test_fnop_sequence() { // Additional FNSAVE tests #[test] fn test_fnsave_multiple_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1.0); @@ -134,14 +145,15 @@ fn test_fnsave_multiple_values() { #[test] fn test_fnop_with_arithmetic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xD0, // FNOP - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xD0, // FNOP - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xD0, // FNOP + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xD0, // FNOP + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1.0); @@ -153,12 +165,13 @@ fn test_fnop_with_arithmetic() { #[test] fn test_fnsave_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); @@ -169,14 +182,14 @@ macro_rules! fnsave_test { ($name:ident, $val:expr) => { #[test] fn $name() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, $val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); } }; } @@ -196,15 +209,14 @@ macro_rules! fnop_test { ($name:ident, $val:expr) => { #[test] fn $name() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xD0, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xD0, 0xDD, 0x1C, 0x25, 0x00, 0x30, + 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, $val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, $val); } @@ -224,9 +236,9 @@ fnop_test!(test_fnop_min, f64::MIN); #[test] fn test_fnsave_stack_depth() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -235,14 +247,12 @@ fn test_fnsave_stack_depth() { #[test] fn test_fnop_doesnt_affect_flags() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xD1, // FCOM - 0xD9, 0xD0, // FNOP - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xD1, // FCOM + 0xD9, 0xD0, // FNOP + 0xDD, 0xD8, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1.0); @@ -252,12 +262,10 @@ fn test_fnop_doesnt_affect_flags() { #[test] fn test_fnsave_consistency() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xD9, 0xE8, - 0xDD, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, 0xD9, 0xE8, 0xDD, 0x34, 0x25, 0x00, + 0x31, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fpatan.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fpatan.rs index 420e84f6..92a3cf8a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fpatan.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fpatan.rs @@ -27,12 +27,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -43,117 +45,124 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fpatan_first_quadrant_45deg() { - let mut emu = emu64(); // FLD qword [0x2000] ; Load X (ST(0)) - // FLD qword [0x2008] ; Load Y (ST(0), X becomes ST(1)) - // FPATAN ; ST(1) = arctan(ST(1)/ST(0)), pop - // FSTP qword [0x3000] ; Store result - // HLT + let mut emu = emu64(); // FLD qword [0x2000] ; Load X (ST(0)) + // FLD qword [0x2008] ; Load Y (ST(0), X becomes ST(1)) + // FPATAN ; ST(1) = arctan(ST(1)/ST(0)), pop + // FSTP qword [0x3000] ; Store result + // HLT let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF3, // FPATAN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF3, // FPATAN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(1/1) should be π/4, got {} expected {}", result, expected); + assert!( + (result - expected).abs() < 1e-15, + "arctan(1/1) should be π/4, got {} expected {}", + result, + expected + ); } #[test] fn test_fpatan_first_quadrant_30deg() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF3, // FPATAN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF3, // FPATAN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0_f64.sqrt()); // X = sqrt(3) - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, 3.0_f64.sqrt()); // X = sqrt(3) + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_6; - assert!((result - expected).abs() < 1e-14, - "arctan(1/sqrt(3)) should be π/6"); + assert!( + (result - expected).abs() < 1e-14, + "arctan(1/sqrt(3)) should be π/6" + ); } #[test] fn test_fpatan_first_quadrant_60deg() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, 3.0_f64.sqrt()); // Y = sqrt(3) + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, 3.0_f64.sqrt()); // Y = sqrt(3) emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_3; - assert!((result - expected).abs() < 1e-14, - "arctan(sqrt(3)/1) should be π/3"); + assert!( + (result - expected).abs() < 1e-14, + "arctan(sqrt(3)/1) should be π/3" + ); } #[test] fn test_fpatan_first_quadrant_small_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, 0.1); // Y = 0.1 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, 0.1); // Y = 0.1 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (0.1_f64).atan(); - assert!((result - expected).abs() < 1e-15, - "arctan(0.1/1.0) should match Rust atan"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(0.1/1.0) should match Rust atan" + ); } #[test] fn test_fpatan_first_quadrant_large_ratio() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, 10.0); // Y = 10.0 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, 10.0); // Y = 10.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (10.0_f64).atan(); - assert!((result - expected).abs() < 1e-14, - "arctan(10.0/1.0) should match Rust atan"); + assert!( + (result - expected).abs() < 1e-14, + "arctan(10.0/1.0) should match Rust atan" + ); } // ============================================================================ @@ -162,68 +171,68 @@ fn test_fpatan_first_quadrant_large_ratio() { #[test] fn test_fpatan_second_quadrant_135deg() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 3.0 * std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(1/-1) should be 3π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(1/-1) should be 3π/4" + ); } #[test] fn test_fpatan_second_quadrant_near_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, 0.1); // Y = 0.1 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, 0.1); // Y = 0.1 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (0.1_f64).atan2(-1.0); - assert!((result - expected).abs() < 1e-15, - "arctan(0.1/-1.0) should match atan2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(0.1/-1.0) should match atan2" + ); } #[test] fn test_fpatan_second_quadrant_large_y() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, 10.0); // Y = 10.0 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, 10.0); // Y = 10.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (10.0_f64).atan2(-1.0); - assert!((result - expected).abs() < 1e-14, - "arctan(10.0/-1.0) should match atan2"); + assert!( + (result - expected).abs() < 1e-14, + "arctan(10.0/-1.0) should match atan2" + ); } // ============================================================================ @@ -232,68 +241,68 @@ fn test_fpatan_second_quadrant_large_y() { #[test] fn test_fpatan_third_quadrant_225deg() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -3.0 * std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(-1/-1) should be -3π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-1/-1) should be -3π/4" + ); } #[test] fn test_fpatan_third_quadrant_near_minus_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, -0.1); // Y = -0.1 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, -0.1); // Y = -0.1 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (-0.1_f64).atan2(-1.0); - assert!((result - expected).abs() < 1e-15, - "arctan(-0.1/-1.0) should match atan2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-0.1/-1.0) should match atan2" + ); } #[test] fn test_fpatan_third_quadrant_large_y() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, -10.0); // Y = -10.0 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, -10.0); // Y = -10.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (-10.0_f64).atan2(-1.0); - assert!((result - expected).abs() < 1e-14, - "arctan(-10.0/-1.0) should match atan2"); + assert!( + (result - expected).abs() < 1e-14, + "arctan(-10.0/-1.0) should match atan2" + ); } // ============================================================================ @@ -302,68 +311,68 @@ fn test_fpatan_third_quadrant_large_y() { #[test] fn test_fpatan_fourth_quadrant_minus_45deg() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(-1/1) should be -π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-1/1) should be -π/4" + ); } #[test] fn test_fpatan_fourth_quadrant_small_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, -0.1); // Y = -0.1 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, -0.1); // Y = -0.1 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (-0.1_f64).atan(); - assert!((result - expected).abs() < 1e-15, - "arctan(-0.1/1.0) should match Rust atan"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-0.1/1.0) should match Rust atan" + ); } #[test] fn test_fpatan_fourth_quadrant_large_y() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, -10.0); // Y = -10.0 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, -10.0); // Y = -10.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (-10.0_f64).atan(); - assert!((result - expected).abs() < 1e-14, - "arctan(-10.0/1.0) should match Rust atan"); + assert!( + (result - expected).abs() < 1e-14, + "arctan(-10.0/1.0) should match Rust atan" + ); } // ============================================================================ @@ -372,176 +381,176 @@ fn test_fpatan_fourth_quadrant_large_y() { #[test] fn test_fpatan_positive_zero_positive_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, 0.0); // Y = +0.0 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, 0.0); // Y = +0.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-15 && !result.is_sign_negative(), - "arctan(+0/+X) should be +0"); + assert!( + result.abs() < 1e-15 && !result.is_sign_negative(), + "arctan(+0/+X) should be +0" + ); } #[test] fn test_fpatan_negative_zero_positive_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, -0.0); // Y = -0.0 + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, -0.0); // Y = -0.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-15 && result.is_sign_negative(), - "arctan(-0/+X) should be -0"); + assert!( + result.abs() < 1e-15 && result.is_sign_negative(), + "arctan(-0/+X) should be -0" + ); } #[test] fn test_fpatan_positive_zero_negative_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, 0.0); // Y = +0.0 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, 0.0); // Y = +0.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::PI; - assert!((result - expected).abs() < 1e-15, - "arctan(+0/-X) should be +π"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+0/-X) should be +π" + ); } #[test] fn test_fpatan_negative_zero_negative_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, -0.0); // Y = -0.0 + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, -0.0); // Y = -0.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::PI; - assert!((result - expected).abs() < 1e-15, - "arctan(-0/-X) should be -π"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-0/-X) should be -π" + ); } #[test] fn test_fpatan_positive_y_positive_zero_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.0); // X = +0.0 - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, 0.0); // X = +0.0 + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(+Y/+0) should be +π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+Y/+0) should be +π/2" + ); } #[test] fn test_fpatan_negative_y_positive_zero_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.0); // X = +0.0 - emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 + emu.maps.write_f64(0x2000, 0.0); // X = +0.0 + emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(-Y/+0) should be -π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-Y/+0) should be -π/2" + ); } #[test] fn test_fpatan_positive_y_negative_zero_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -0.0); // X = -0.0 - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, -0.0); // X = -0.0 + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(+Y/-0) should be +π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+Y/-0) should be +π/2" + ); } #[test] fn test_fpatan_negative_y_negative_zero_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -0.0); // X = -0.0 - emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 + emu.maps.write_f64(0x2000, -0.0); // X = -0.0 + emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(-Y/-0) should be -π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-Y/-0) should be -π/2" + ); } // ============================================================================ @@ -550,264 +559,264 @@ fn test_fpatan_negative_y_negative_zero_x() { #[test] fn test_fpatan_positive_infinity_positive_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(+∞/+X) should be +π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+∞/+X) should be +π/2" + ); } #[test] fn test_fpatan_negative_infinity_positive_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // X = 1.0 - emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ + emu.maps.write_f64(0x2000, 1.0); // X = 1.0 + emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(-∞/+X) should be -π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-∞/+X) should be -π/2" + ); } #[test] fn test_fpatan_positive_infinity_negative_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(+∞/-X) should be +π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+∞/-X) should be +π/2" + ); } #[test] fn test_fpatan_negative_infinity_negative_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -1.0); // X = -1.0 - emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ + emu.maps.write_f64(0x2000, -1.0); // X = -1.0 + emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::FRAC_PI_2; - assert!((result - expected).abs() < 1e-15, - "arctan(-∞/-X) should be -π/2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-∞/-X) should be -π/2" + ); } #[test] fn test_fpatan_positive_y_positive_infinity_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-15 && !result.is_sign_negative(), - "arctan(+Y/+∞) should be +0"); + assert!( + result.abs() < 1e-15 && !result.is_sign_negative(), + "arctan(+Y/+∞) should be +0" + ); } #[test] fn test_fpatan_negative_y_positive_infinity_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ - emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 + emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ + emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() < 1e-15 && result.is_sign_negative(), - "arctan(-Y/+∞) should be -0"); + assert!( + result.abs() < 1e-15 && result.is_sign_negative(), + "arctan(-Y/+∞) should be -0" + ); } #[test] fn test_fpatan_positive_y_negative_infinity_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ - emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 + emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ + emu.maps.write_f64(0x2008, 1.0); // Y = 1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::PI; - assert!((result - expected).abs() < 1e-15, - "arctan(+Y/-∞) should be +π"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+Y/-∞) should be +π" + ); } #[test] fn test_fpatan_negative_y_negative_infinity_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ - emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 + emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ + emu.maps.write_f64(0x2008, -1.0); // Y = -1.0 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::PI; - assert!((result - expected).abs() < 1e-15, - "arctan(-Y/-∞) should be -π"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-Y/-∞) should be -π" + ); } #[test] fn test_fpatan_positive_infinity_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ - emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ + emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ + emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(+∞/+∞) should be +π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+∞/+∞) should be +π/4" + ); } #[test] fn test_fpatan_positive_infinity_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ - emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ + emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ + emu.maps.write_f64(0x2008, f64::INFINITY); // Y = +∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 3.0 * std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(+∞/-∞) should be +3π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(+∞/-∞) should be +3π/4" + ); } #[test] fn test_fpatan_negative_infinity_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ - emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ + emu.maps.write_f64(0x2000, f64::INFINITY); // X = +∞ + emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(-∞/+∞) should be -π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-∞/+∞) should be -π/4" + ); } #[test] fn test_fpatan_negative_infinity_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ - emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ + emu.maps.write_f64(0x2000, f64::NEG_INFINITY); // X = -∞ + emu.maps.write_f64(0x2008, f64::NEG_INFINITY); // Y = -∞ emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -3.0 * std::f64::consts::FRAC_PI_4; - assert!((result - expected).abs() < 1e-15, - "arctan(-∞/-∞) should be -3π/4"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(-∞/-∞) should be -3π/4" + ); } // ============================================================================ @@ -816,44 +825,44 @@ fn test_fpatan_negative_infinity_negative_infinity() { #[test] fn test_fpatan_large_x_small_y() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1000.0); // X = 1000.0 - emu.maps.write_f64(0x2008, 0.001); // Y = 0.001 + emu.maps.write_f64(0x2000, 1000.0); // X = 1000.0 + emu.maps.write_f64(0x2008, 0.001); // Y = 0.001 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (0.001_f64).atan2(1000.0); - assert!((result - expected).abs() < 1e-15, - "arctan(0.001/1000.0) should match atan2"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(0.001/1000.0) should match atan2" + ); } #[test] fn test_fpatan_fractional_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF3, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xF3, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.25); // X = 0.25 - emu.maps.write_f64(0x2008, 0.5); // Y = 0.5 + emu.maps.write_f64(0x2000, 0.25); // X = 0.25 + emu.maps.write_f64(0x2008, 0.5); // Y = 0.5 emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0_f64.atan(); - assert!((result - expected).abs() < 1e-15, - "arctan(0.5/0.25) should equal arctan(2)"); + assert!( + (result - expected).abs() < 1e-15, + "arctan(0.5/0.25) should equal arctan(2)" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem.rs index fa05fa8f..3452a0d6 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem.rs @@ -22,12 +22,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -38,13 +40,13 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fprem_basic_positive() { - let mut emu = emu64(); // 7.0 % 3.0 = 1.0 + let mut emu = emu64(); // 7.0 % 3.0 = 1.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor (3.0) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend (7.0) - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; result - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor (3.0) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend (7.0) + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; result + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -59,13 +61,13 @@ fn test_fprem_basic_positive() { #[test] fn test_fprem_exact_division() { - let mut emu = emu64(); // 9.0 % 3.0 = 0.0 + let mut emu = emu64(); // 9.0 % 3.0 = 0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -80,13 +82,13 @@ fn test_fprem_exact_division() { #[test] fn test_fprem_small_dividend() { - let mut emu = emu64(); // 2.0 % 5.0 = 2.0 + let mut emu = emu64(); // 2.0 % 5.0 = 2.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -101,13 +103,13 @@ fn test_fprem_small_dividend() { #[test] fn test_fprem_fractional() { - let mut emu = emu64(); // 5.5 % 2.0 = 1.5 + let mut emu = emu64(); // 5.5 % 2.0 = 1.5 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -126,13 +128,13 @@ fn test_fprem_fractional() { #[test] fn test_fprem_negative_dividend() { - let mut emu = emu64(); // -7.0 % 3.0 = -1.0 (sign follows dividend) + let mut emu = emu64(); // -7.0 % 3.0 = -1.0 (sign follows dividend) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -147,13 +149,13 @@ fn test_fprem_negative_dividend() { #[test] fn test_fprem_negative_divisor() { - let mut emu = emu64(); // 7.0 % -3.0 = 1.0 (sign follows dividend) + let mut emu = emu64(); // 7.0 % -3.0 = 1.0 (sign follows dividend) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -168,13 +170,13 @@ fn test_fprem_negative_divisor() { #[test] fn test_fprem_both_negative() { - let mut emu = emu64(); // -7.0 % -3.0 = -1.0 + let mut emu = emu64(); // -7.0 % -3.0 = -1.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -193,13 +195,13 @@ fn test_fprem_both_negative() { #[test] fn test_fprem_zero_dividend() { - let mut emu = emu64(); // 0.0 % 5.0 = 0.0 + let mut emu = emu64(); // 0.0 % 5.0 = 0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -215,13 +217,13 @@ fn test_fprem_zero_dividend() { #[test] fn test_fprem_negative_zero_dividend() { - let mut emu = emu64(); // -0.0 % 5.0 = -0.0 + let mut emu = emu64(); // -0.0 % 5.0 = -0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -241,13 +243,13 @@ fn test_fprem_negative_zero_dividend() { #[test] fn test_fprem_divisor_one() { - let mut emu = emu64(); // 5.5 % 1.0 = 0.5 + let mut emu = emu64(); // 5.5 % 1.0 = 0.5 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -262,13 +264,13 @@ fn test_fprem_divisor_one() { #[test] fn test_fprem_small_divisor() { - let mut emu = emu64(); // 10.0 % 0.5 = 0.0 + let mut emu = emu64(); // 10.0 % 0.5 = 0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -283,13 +285,13 @@ fn test_fprem_small_divisor() { #[test] fn test_fprem_large_divisor() { - let mut emu = emu64(); // 5.0 % 10.0 = 5.0 + let mut emu = emu64(); // 5.0 % 10.0 = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -304,13 +306,13 @@ fn test_fprem_large_divisor() { #[test] fn test_fprem_fractional_divisor() { - let mut emu = emu64(); // 7.0 % 1.5 = 1.0 + let mut emu = emu64(); // 7.0 % 1.5 = 1.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -329,13 +331,13 @@ fn test_fprem_fractional_divisor() { #[test] fn test_fprem_finite_mod_infinity() { - let mut emu = emu64(); // 5.0 % infinity = 5.0 + let mut emu = emu64(); // 5.0 % infinity = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -354,12 +356,13 @@ fn test_fprem_finite_mod_infinity() { #[test] fn test_fprem_pi_modulo() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -375,13 +378,13 @@ fn test_fprem_pi_modulo() { #[test] fn test_fprem_angle_reduction() { - let mut emu = emu64(); // 10.0 % (2*PI) for angle reduction + let mut emu = emu64(); // 10.0 % (2*PI) for angle reduction let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -393,7 +396,10 @@ fn test_fprem_angle_reduction() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result >= 0.0 && result < two_pi, "Angle should be reduced to [0, 2π)"); + assert!( + result >= 0.0 && result < two_pi, + "Angle should be reduced to [0, 2π)" + ); } // ============================================================================ @@ -402,16 +408,17 @@ fn test_fprem_angle_reduction() { #[test] fn test_fprem_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -434,12 +441,13 @@ fn test_fprem_sequence() { #[test] fn test_fprem_very_large_dividend() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -454,12 +462,13 @@ fn test_fprem_very_large_dividend() { #[test] fn test_fprem_very_small_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -475,13 +484,13 @@ fn test_fprem_very_small_values() { #[test] fn test_fprem_same_values() { - let mut emu = emu64(); // x % x = 0 + let mut emu = emu64(); // x % x = 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -495,14 +504,14 @@ fn test_fprem_same_values() { #[test] fn test_fprem_preserves_divisor() { - let mut emu = emu64(); // FPREM only modifies ST(0), ST(1) (divisor) remains unchanged + let mut emu = emu64(); // FPREM only modifies ST(0), ST(1) (divisor) remains unchanged let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; remainder - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; divisor - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; remainder + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; divisor + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -523,12 +532,13 @@ fn test_fprem_preserves_divisor() { #[test] fn test_fprem_completion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -547,12 +557,13 @@ fn test_fprem_completion() { #[test] fn test_fprem_power_of_two_divisor() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -567,12 +578,13 @@ fn test_fprem_power_of_two_divisor() { #[test] fn test_fprem_various_divisors() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![ @@ -588,49 +600,57 @@ fn test_fprem_various_divisors() { emu.maps.write_f64(0x2000, dividend); emu.maps.write_f64(0x2008, divisor); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, expected, "{} % {} should be {}", dividend, divisor, expected); + assert_eq!( + result, expected, + "{} % {} should be {}", + dividend, divisor, expected + ); } } #[test] fn test_fprem_decimal_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; - let test_cases = vec![ - (3.14, 1.0, 0.14), - (2.71, 0.5, 0.21), - (9.99, 2.0, 1.99), - ]; + let test_cases = vec![(3.14, 1.0, 0.14), (2.71, 0.5, 0.21), (9.99, 2.0, 1.99)]; for (dividend, divisor, expected) in test_cases { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, dividend); emu.maps.write_f64(0x2008, divisor); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - expected).abs() < 1e-10, "{} % {} should be approximately {}", dividend, divisor, expected); + assert!( + (result - expected).abs() < 1e-10, + "{} % {} should be approximately {}", + dividend, + divisor, + expected + ); } } #[test] fn test_fprem_irrational_dividend() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF8, // FPREM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF8, // FPREM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem1.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem1.rs index 79f6927d..d6d0d5ab 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem1.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fprem1.rs @@ -22,12 +22,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -38,13 +40,13 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fprem1_basic_positive() { - let mut emu = emu64(); // 7.0 % 3.0 (IEEE) - rounds to nearest + let mut emu = emu64(); // 7.0 % 3.0 (IEEE) - rounds to nearest let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor (3.0) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend (7.0) - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; result - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor (3.0) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend (7.0) + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; result + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -59,13 +61,13 @@ fn test_fprem1_basic_positive() { #[test] fn test_fprem1_exact_division() { - let mut emu = emu64(); // 9.0 % 3.0 = 0.0 + let mut emu = emu64(); // 9.0 % 3.0 = 0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -80,13 +82,13 @@ fn test_fprem1_exact_division() { #[test] fn test_fprem1_small_dividend() { - let mut emu = emu64(); // 2.0 % 5.0 = 2.0 + let mut emu = emu64(); // 2.0 % 5.0 = 2.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -101,13 +103,13 @@ fn test_fprem1_small_dividend() { #[test] fn test_fprem1_fractional() { - let mut emu = emu64(); // 5.5 % 2.0 = -0.5 (rounds to nearest, Q=3) + let mut emu = emu64(); // 5.5 % 2.0 = -0.5 (rounds to nearest, Q=3) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -127,13 +129,13 @@ fn test_fprem1_fractional() { #[test] fn test_fprem1_ieee_rounding_case1() { - let mut emu = emu64(); // 5.0 % 3.0: Q rounds to 2 (nearest), remainder = 5.0 - 2*3.0 = -1.0 + let mut emu = emu64(); // 5.0 % 3.0: Q rounds to 2 (nearest), remainder = 5.0 - 2*3.0 = -1.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -149,13 +151,13 @@ fn test_fprem1_ieee_rounding_case1() { #[test] fn test_fprem1_ieee_rounding_case2() { - let mut emu = emu64(); // 7.5 % 4.0: Q = 1.875 rounds to 2, remainder = 7.5 - 2*4.0 = -0.5 + let mut emu = emu64(); // 7.5 % 4.0: Q = 1.875 rounds to 2, remainder = 7.5 - 2*4.0 = -0.5 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -170,14 +172,14 @@ fn test_fprem1_ieee_rounding_case2() { #[test] fn test_fprem1_magnitude_less_than_half() { - let mut emu = emu64(); // IEEE remainder magnitude should be <= |modulus|/2 - // 10.0 % 7.0: Q = 1.428... rounds to 1, remainder = 10.0 - 1*7.0 = 3.0 + let mut emu = emu64(); // IEEE remainder magnitude should be <= |modulus|/2 + // 10.0 % 7.0: Q = 1.428... rounds to 1, remainder = 10.0 - 1*7.0 = 3.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -188,7 +190,10 @@ fn test_fprem1_magnitude_less_than_half() { let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, 3.0, "10.0 % 7.0 (IEEE) should be 3.0"); - assert!(result.abs() <= 7.0 / 2.0, "Magnitude should be <= |modulus|/2"); + assert!( + result.abs() <= 7.0 / 2.0, + "Magnitude should be <= |modulus|/2" + ); } // ============================================================================ @@ -197,13 +202,13 @@ fn test_fprem1_magnitude_less_than_half() { #[test] fn test_fprem1_negative_dividend() { - let mut emu = emu64(); // -7.0 % 3.0 + let mut emu = emu64(); // -7.0 % 3.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -219,13 +224,13 @@ fn test_fprem1_negative_dividend() { #[test] fn test_fprem1_negative_divisor() { - let mut emu = emu64(); // 7.0 % -3.0 + let mut emu = emu64(); // 7.0 % -3.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -241,13 +246,13 @@ fn test_fprem1_negative_divisor() { #[test] fn test_fprem1_both_negative() { - let mut emu = emu64(); // -7.0 % -3.0 + let mut emu = emu64(); // -7.0 % -3.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -263,13 +268,13 @@ fn test_fprem1_both_negative() { #[test] fn test_fprem1_negative_half_case() { - let mut emu = emu64(); // -5.0 % 3.0: rounds to nearest even + let mut emu = emu64(); // -5.0 % 3.0: rounds to nearest even let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -289,13 +294,13 @@ fn test_fprem1_negative_half_case() { #[test] fn test_fprem1_zero_dividend() { - let mut emu = emu64(); // 0.0 % 5.0 = 0.0 + let mut emu = emu64(); // 0.0 % 5.0 = 0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -311,13 +316,13 @@ fn test_fprem1_zero_dividend() { #[test] fn test_fprem1_negative_zero_dividend() { - let mut emu = emu64(); // -0.0 % 5.0 = -0.0 + let mut emu = emu64(); // -0.0 % 5.0 = -0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -337,13 +342,13 @@ fn test_fprem1_negative_zero_dividend() { #[test] fn test_fprem1_divisor_one() { - let mut emu = emu64(); // 5.5 % 1.0 = 0.5 + let mut emu = emu64(); // 5.5 % 1.0 = 0.5 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -359,13 +364,13 @@ fn test_fprem1_divisor_one() { #[test] fn test_fprem1_small_divisor() { - let mut emu = emu64(); // 10.0 % 0.5 = 0.0 + let mut emu = emu64(); // 10.0 % 0.5 = 0.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -380,13 +385,13 @@ fn test_fprem1_small_divisor() { #[test] fn test_fprem1_large_divisor() { - let mut emu = emu64(); // 5.0 % 10.0 = 5.0 + let mut emu = emu64(); // 5.0 % 10.0 = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -401,13 +406,13 @@ fn test_fprem1_large_divisor() { #[test] fn test_fprem1_fractional_divisor() { - let mut emu = emu64(); // 7.0 % 1.5 + let mut emu = emu64(); // 7.0 % 1.5 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -427,13 +432,13 @@ fn test_fprem1_fractional_divisor() { #[test] fn test_fprem1_finite_mod_infinity() { - let mut emu = emu64(); // 5.0 % infinity = 5.0 + let mut emu = emu64(); // 5.0 % infinity = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -448,13 +453,13 @@ fn test_fprem1_finite_mod_infinity() { #[test] fn test_fprem1_finite_mod_neg_infinity() { - let mut emu = emu64(); // 5.0 % -infinity = 5.0 + let mut emu = emu64(); // 5.0 % -infinity = 5.0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -473,12 +478,13 @@ fn test_fprem1_finite_mod_neg_infinity() { #[test] fn test_fprem1_pi_over_4_reduction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -490,17 +496,21 @@ fn test_fprem1_pi_over_4_reduction() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() <= pi_over_4 / 2.0, "Reduced angle magnitude should be <= π/8"); + assert!( + result.abs() <= pi_over_4 / 2.0, + "Reduced angle magnitude should be <= π/8" + ); } #[test] fn test_fprem1_pi_modulo() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -512,7 +522,10 @@ fn test_fprem1_pi_modulo() { let result = emu.maps.read_f64(0x3000).unwrap(); // PI/1.0 = 3.14159... rounds to 3, so PI - 3*1.0 = 0.14159... let expected = std::f64::consts::PI - 3.0; - assert!((result - expected).abs() < 1e-10, "PI % 1.0 (IEEE) computation"); + assert!( + (result - expected).abs() < 1e-10, + "PI % 1.0 (IEEE) computation" + ); } // ============================================================================ @@ -521,16 +534,17 @@ fn test_fprem1_pi_modulo() { #[test] fn test_fprem1_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -555,12 +569,13 @@ fn test_fprem1_sequence() { #[test] fn test_fprem1_very_large_dividend() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -576,12 +591,13 @@ fn test_fprem1_very_large_dividend() { #[test] fn test_fprem1_very_small_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -591,18 +607,21 @@ fn test_fprem1_very_small_values() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.abs() <= 1.5e-11, "Magnitude should be <= |modulus|/2"); + assert!( + result.abs() <= 1.5e-11, + "Magnitude should be <= |modulus|/2" + ); } #[test] fn test_fprem1_same_values() { - let mut emu = emu64(); // x % x = 0 + let mut emu = emu64(); // x % x = 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -616,14 +635,14 @@ fn test_fprem1_same_values() { #[test] fn test_fprem1_preserves_divisor() { - let mut emu = emu64(); // FPREM1 only modifies ST(0), ST(1) (divisor) remains unchanged + let mut emu = emu64(); // FPREM1 only modifies ST(0), ST(1) (divisor) remains unchanged let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; remainder - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; divisor - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; divisor + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; dividend + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; remainder + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; divisor + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -644,12 +663,13 @@ fn test_fprem1_preserves_divisor() { #[test] fn test_fprem1_power_of_two_divisor() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -665,12 +685,13 @@ fn test_fprem1_power_of_two_divisor() { #[test] fn test_fprem1_irrational_dividend() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -688,12 +709,13 @@ fn test_fprem1_irrational_dividend() { #[test] fn test_fprem1_halfway_cases() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -709,12 +731,13 @@ fn test_fprem1_halfway_cases() { #[test] fn test_fprem1_completion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF5, // FPREM1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF5, // FPREM1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fptan.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fptan.rs index 4ffa9324..c1312636 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fptan.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fptan.rs @@ -27,7 +27,7 @@ //! Flags affected: //! - C1: Set to 0 if stack underflow occurred; set to 1 if stack overflow occurred //! - C2: Set to 1 if outside range (-2^63 < source < +2^63); - // otherwise 0 +// otherwise 0 //! - C0, C3: Undefined //! //! Reference: /Users/int/dev/rax/docs/fptan.txt @@ -37,12 +37,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -53,17 +55,17 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fptan_zero() { - let mut emu = emu64(); // FLD qword [0x2000] ; Load angle - // FPTAN ; Compute tangent, push 1.0 - // FSTP qword [0x3000] ; Store the 1.0 - // FSTP qword [0x3008] ; Store the tangent result - // HLT + let mut emu = emu64(); // FLD qword [0x2000] ; Load angle + // FPTAN ; Compute tangent, push 1.0 + // FSTP qword [0x3000] ; Store the 1.0 + // FSTP qword [0x3008] ; Store the tangent result + // HLT let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF2, // FPTAN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF2, // FPTAN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -80,12 +82,10 @@ fn test_fptan_zero() { #[test] fn test_fptan_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -102,12 +102,10 @@ fn test_fptan_pi_over_4() { #[test] fn test_fptan_pi_over_6() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -120,17 +118,18 @@ fn test_fptan_pi_over_6() { let expected = 1.0 / 3.0_f64.sqrt(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-14, "tan(π/6) should be 1/√3"); + assert!( + (tangent - expected).abs() < 1e-14, + "tan(π/6) should be 1/√3" + ); } #[test] fn test_fptan_pi_over_3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -148,12 +147,10 @@ fn test_fptan_pi_over_3() { #[test] fn test_fptan_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -174,12 +171,10 @@ fn test_fptan_pi() { #[test] fn test_fptan_negative_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -196,12 +191,10 @@ fn test_fptan_negative_pi_over_4() { #[test] fn test_fptan_negative_pi_over_6() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -214,17 +207,18 @@ fn test_fptan_negative_pi_over_6() { let expected = -1.0 / 3.0_f64.sqrt(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-14, "tan(-π/6) should be -1/√3"); + assert!( + (tangent - expected).abs() < 1e-14, + "tan(-π/6) should be -1/√3" + ); } #[test] fn test_fptan_negative_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -245,12 +239,10 @@ fn test_fptan_negative_pi() { #[test] fn test_fptan_small_positive_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -263,17 +255,18 @@ fn test_fptan_small_positive_angle() { let expected = 0.1_f64.tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-15, "tan(0.1) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-15, + "tan(0.1) should match Rust tan" + ); } #[test] fn test_fptan_small_negative_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -286,17 +279,18 @@ fn test_fptan_small_negative_angle() { let expected = (-0.1_f64).tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-15, "tan(-0.1) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-15, + "tan(-0.1) should match Rust tan" + ); } #[test] fn test_fptan_very_small_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -309,7 +303,10 @@ fn test_fptan_very_small_angle() { assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); let expected = (0.001_f64).tan(); - assert!((tangent - expected).abs() < 1e-15, "tan(0.001) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-15, + "tan(0.001) should match Rust tan" + ); } // ============================================================================ @@ -318,12 +315,10 @@ fn test_fptan_very_small_angle() { #[test] fn test_fptan_two_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -340,16 +335,15 @@ fn test_fptan_two_pi() { #[test] fn test_fptan_three_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_4); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_4); emu.run(None).unwrap(); @@ -362,16 +356,15 @@ fn test_fptan_three_pi_over_4() { #[test] fn test_fptan_five_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 5.0 * std::f64::consts::FRAC_PI_4); + emu.maps + .write_f64(0x2000, 5.0 * std::f64::consts::FRAC_PI_4); emu.run(None).unwrap(); @@ -388,12 +381,10 @@ fn test_fptan_five_pi_over_4() { #[test] fn test_fptan_ten_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -410,12 +401,10 @@ fn test_fptan_ten_pi() { #[test] fn test_fptan_hundred() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -428,18 +417,18 @@ fn test_fptan_hundred() { let expected = 100.0_f64.tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() / expected.abs() < 1e-10, - "tan(100) should approximately match Rust tan"); + assert!( + (tangent - expected).abs() / expected.abs() < 1e-10, + "tan(100) should approximately match Rust tan" + ); } #[test] fn test_fptan_thousand() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -459,12 +448,10 @@ fn test_fptan_thousand() { #[test] fn test_fptan_one_radian() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -477,17 +464,18 @@ fn test_fptan_one_radian() { let expected = 1.0_f64.tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-14, "tan(1) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-14, + "tan(1) should match Rust tan" + ); } #[test] fn test_fptan_two_radians() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -500,17 +488,18 @@ fn test_fptan_two_radians() { let expected = 2.0_f64.tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-14, "tan(2) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-14, + "tan(2) should match Rust tan" + ); } #[test] fn test_fptan_half_radian() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -523,17 +512,18 @@ fn test_fptan_half_radian() { let expected = 0.5_f64.tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-15, "tan(0.5) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-15, + "tan(0.5) should match Rust tan" + ); } #[test] fn test_fptan_pi_over_8() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -546,21 +536,23 @@ fn test_fptan_pi_over_8() { let expected = std::f64::consts::FRAC_PI_8.tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-15, "tan(π/8) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-15, + "tan(π/8) should match Rust tan" + ); } #[test] fn test_fptan_three_pi_over_8() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_8); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_8); emu.run(None).unwrap(); @@ -569,7 +561,10 @@ fn test_fptan_three_pi_over_8() { let expected = (3.0 * std::f64::consts::FRAC_PI_8).tan(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!((tangent - expected).abs() < 1e-13, "tan(3π/8) should match Rust tan"); + assert!( + (tangent - expected).abs() < 1e-13, + "tan(3π/8) should match Rust tan" + ); } // ============================================================================ @@ -578,14 +573,14 @@ fn test_fptan_three_pi_over_8() { #[test] fn test_fptan_fpatan_cotangent_calculation() { - let mut emu = emu64(); // FPTAN returns tan(x) in ST(1) and 1.0 in ST(0) - // FDIVR ST(1), ST(0) computes ST(1) = ST(0) / ST(1) = 1.0 / tan(x) = cot(x) + let mut emu = emu64(); // FPTAN returns tan(x) in ST(1) and 1.0 in ST(0) + // FDIVR ST(1), ST(0) computes ST(1) = ST(0) / ST(1) = 1.0 / tan(x) = cot(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF2, // FPTAN (ST(0)=1.0, ST(1)=tan) - 0xDE, 0xF9, // FDIVR (ST(1) = ST(0)/ST(1) = 1/tan = cot) - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] (store cotangent) - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF2, // FPTAN (ST(0)=1.0, ST(1)=tan) + 0xDE, 0xF9, // FDIVR (ST(1) = ST(0)/ST(1) = 1/tan = cot) + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] (store cotangent) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -595,18 +590,18 @@ fn test_fptan_fpatan_cotangent_calculation() { let cotangent = emu.maps.read_f64(0x3008).unwrap(); // cot(π/4) = 1/tan(π/4) = 1/1 = 1 - assert!((cotangent - 1.0).abs() < 1e-14, - "cot(π/4) calculated via FPTAN+FDIVR should be 1"); + assert!( + (cotangent - 1.0).abs() < 1e-14, + "cot(π/4) calculated via FPTAN+FDIVR should be 1" + ); } #[test] fn test_fptan_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -618,18 +613,18 @@ fn test_fptan_positive_zero() { let tangent = emu.maps.read_f64(0x3008).unwrap(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!(tangent == 0.0 && !tangent.is_sign_negative(), - "tan(+0) should be +0"); + assert!( + tangent == 0.0 && !tangent.is_sign_negative(), + "tan(+0) should be +0" + ); } #[test] fn test_fptan_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -641,20 +636,20 @@ fn test_fptan_negative_zero() { let tangent = emu.maps.read_f64(0x3008).unwrap(); assert!((one_value - 1.0).abs() < 1e-15, "FPTAN should push 1.0"); - assert!(tangent == 0.0 && tangent.is_sign_negative(), - "tan(-0) should be -0"); + assert!( + tangent == 0.0 && tangent.is_sign_negative(), + "tan(-0) should be -0" + ); } #[test] fn test_fptan_symmetry() { - let mut emu = emu64(); let angle = 0.7; + let mut emu = emu64(); + let angle = 0.7; let code_pos = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code_pos); @@ -663,11 +658,8 @@ fn test_fptan_symmetry() { let tan_pos = emu.maps.read_f64(0x3008).unwrap(); let code_neg = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF2, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF2, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code_neg); @@ -675,6 +667,8 @@ fn test_fptan_symmetry() { emu.run(None).unwrap(); let tan_neg = emu.maps.read_f64(0x3008).unwrap(); - assert!((tan_pos + tan_neg).abs() < 1e-15, - "tan(-x) should equal -tan(x)"); + assert!( + (tan_pos + tan_neg).abs() < 1e-15, + "tan(-x) should equal -tan(x)" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint.rs index 3314dee8..da110698 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint.rs @@ -20,19 +20,22 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // Helper function to write FPU control word fn write_fpu_control_word(mem: u64, addr: u64, cw: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &cw.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &cw.to_le_bytes()); } // ============================================================================ @@ -41,11 +44,12 @@ fn write_fpu_control_word(mem: u64, addr: u64, cw: u16) { #[test] fn test_frndint_positive_round_down() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -59,11 +63,12 @@ fn test_frndint_positive_round_down() { #[test] fn test_frndint_positive_round_up() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -77,11 +82,12 @@ fn test_frndint_positive_round_up() { #[test] fn test_frndint_positive_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -95,11 +101,12 @@ fn test_frndint_positive_half() { #[test] fn test_frndint_positive_half_odd() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -117,11 +124,12 @@ fn test_frndint_positive_half_odd() { #[test] fn test_frndint_negative_round_up() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -135,11 +143,12 @@ fn test_frndint_negative_round_up() { #[test] fn test_frndint_negative_round_down() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -153,11 +162,12 @@ fn test_frndint_negative_round_down() { #[test] fn test_frndint_negative_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -171,11 +181,12 @@ fn test_frndint_negative_half() { #[test] fn test_frndint_negative_half_odd() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -193,11 +204,12 @@ fn test_frndint_negative_half_odd() { #[test] fn test_frndint_already_integer_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -211,11 +223,12 @@ fn test_frndint_already_integer_positive() { #[test] fn test_frndint_already_integer_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -229,11 +242,12 @@ fn test_frndint_already_integer_negative() { #[test] fn test_frndint_already_integer_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -242,7 +256,10 @@ fn test_frndint_already_integer_large() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 123456789.0, "FRNDINT of large integer should remain unchanged"); + assert_eq!( + result, 123456789.0, + "FRNDINT of large integer should remain unchanged" + ); } // ============================================================================ @@ -251,11 +268,12 @@ fn test_frndint_already_integer_large() { #[test] fn test_frndint_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -270,11 +288,12 @@ fn test_frndint_positive_zero() { #[test] fn test_frndint_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -289,11 +308,12 @@ fn test_frndint_negative_zero() { #[test] fn test_frndint_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -302,17 +322,24 @@ fn test_frndint_positive_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite(), "FRNDINT of +infinity should remain +infinity"); - assert!(!result.is_sign_negative(), "Result should be positive infinity"); + assert!( + result.is_infinite(), + "FRNDINT of +infinity should remain +infinity" + ); + assert!( + !result.is_sign_negative(), + "Result should be positive infinity" + ); } #[test] fn test_frndint_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -321,17 +348,24 @@ fn test_frndint_negative_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite(), "FRNDINT of -infinity should remain -infinity"); - assert!(result.is_sign_negative(), "Result should be negative infinity"); + assert!( + result.is_infinite(), + "FRNDINT of -infinity should remain -infinity" + ); + assert!( + result.is_sign_negative(), + "Result should be negative infinity" + ); } #[test] fn test_frndint_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -349,11 +383,12 @@ fn test_frndint_nan() { #[test] fn test_frndint_small_positive_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -367,11 +402,12 @@ fn test_frndint_small_positive_fraction() { #[test] fn test_frndint_small_negative_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -385,11 +421,12 @@ fn test_frndint_small_negative_fraction() { #[test] fn test_frndint_near_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -403,11 +440,12 @@ fn test_frndint_near_one() { #[test] fn test_frndint_near_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -425,11 +463,12 @@ fn test_frndint_near_negative_one() { #[test] fn test_frndint_large_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -438,16 +477,20 @@ fn test_frndint_large_positive() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, 123456790.0, "FRNDINT of large value should round correctly"); + assert_eq!( + result, 123456790.0, + "FRNDINT of large value should round correctly" + ); } #[test] fn test_frndint_large_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -456,7 +499,10 @@ fn test_frndint_large_negative() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, -987654321.0, "FRNDINT of large negative should round correctly"); + assert_eq!( + result, -987654321.0, + "FRNDINT of large negative should round correctly" + ); } // ============================================================================ @@ -465,11 +511,12 @@ fn test_frndint_large_negative() { #[test] fn test_frndint_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -483,11 +530,12 @@ fn test_frndint_pi() { #[test] fn test_frndint_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -505,14 +553,15 @@ fn test_frndint_e() { #[test] fn test_frndint_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -529,13 +578,13 @@ fn test_frndint_sequence() { #[test] fn test_frndint_idempotent() { - let mut emu = emu64(); // FRNDINT on an integer should be idempotent + let mut emu = emu64(); // FRNDINT on an integer should be idempotent let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xD9, 0xFC, // FRNDINT (second time) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xD9, 0xFC, // FRNDINT (second time) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -553,11 +602,12 @@ fn test_frndint_idempotent() { #[test] fn test_frndint_very_large_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -571,11 +621,12 @@ fn test_frndint_very_large_value() { #[test] fn test_frndint_one_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -589,11 +640,12 @@ fn test_frndint_one_half() { #[test] fn test_frndint_one_and_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -607,11 +659,12 @@ fn test_frndint_one_and_half() { #[test] fn test_frndint_negative_one_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -625,11 +678,12 @@ fn test_frndint_negative_one_half() { #[test] fn test_frndint_negative_one_and_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -643,11 +697,12 @@ fn test_frndint_negative_one_and_half() { #[test] fn test_frndint_various_fractions() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![ @@ -665,9 +720,13 @@ fn test_frndint_various_fractions() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, expected, "FRNDINT of {} should be {}", input, expected); + assert_eq!( + result, expected, + "FRNDINT of {} should be {}", + input, expected + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint_extended.rs index 24587aa7..4f956ccf 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/frndint_extended.rs @@ -19,39 +19,41 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Rounding mode constants -const RC_NEAREST: u16 = 0x037F; // bits 10-11 = 00 -const RC_DOWN: u16 = 0x077F; // bits 10-11 = 01 -const RC_UP: u16 = 0x0B7F; // bits 10-11 = 10 -const RC_ZERO: u16 = 0x0F7F; // bits 10-11 = 11 +const RC_NEAREST: u16 = 0x037F; // bits 10-11 = 00 +const RC_DOWN: u16 = 0x077F; // bits 10-11 = 01 +const RC_UP: u16 = 0x0B7F; // bits 10-11 = 10 +const RC_ZERO: u16 = 0x0F7F; // bits 10-11 = 11 // Tests with round to nearest (default) #[test] fn test_frndint_nearest_half_to_even() { - let mut emu = emu64(); let test_cases = vec![(2.5, 2.0), (3.5, 4.0), (4.5, 4.0), (5.5, 6.0)]; + let mut emu = emu64(); + let test_cases = vec![(2.5, 2.0), (3.5, 4.0), (4.5, 4.0), (5.5, 6.0)]; for (input, expected) in test_cases { let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, + 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, expected, "FRNDINT({}) nearest", input); } @@ -60,22 +62,29 @@ fn test_frndint_nearest_half_to_even() { // Tests with round down #[test] fn test_frndint_round_down() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFC, // FRNDINT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFC, // FRNDINT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] 0xF4, ]; let test_cases = vec![ - (2.1, 2.0), (2.9, 2.0), (-2.1, -3.0), (-2.9, -3.0), - (0.1, 0.0), (0.9, 0.0), (-0.1, -1.0), (-0.9, -1.0), + (2.1, 2.0), + (2.9, 2.0), + (-2.1, -3.0), + (-2.9, -3.0), + (0.1, 0.0), + (0.9, 0.0), + (-0.1, -1.0), + (-0.9, -1.0), ]; for (input, expected) in test_cases { emu.load_code_bytes(&code); emu.maps.write_word(0x2000, RC_DOWN); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, expected, "FRNDINT({}) down", input); } @@ -84,22 +93,26 @@ fn test_frndint_round_down() { // Tests with round up #[test] fn test_frndint_round_up() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD9, + 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; let test_cases = vec![ - (2.1, 3.0), (2.9, 3.0), (-2.1, -2.0), (-2.9, -2.0), - (0.1, 1.0), (0.9, 1.0), (-0.1, 0.0), (-0.9, 0.0), + (2.1, 3.0), + (2.9, 3.0), + (-2.1, -2.0), + (-2.9, -2.0), + (0.1, 1.0), + (0.9, 1.0), + (-0.1, 0.0), + (-0.9, 0.0), ]; for (input, expected) in test_cases { emu.load_code_bytes(&code); emu.maps.write_word(0x2000, RC_UP); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, expected, "FRNDINT({}) up", input); } @@ -108,22 +121,26 @@ fn test_frndint_round_up() { // Tests with round toward zero (truncate) #[test] fn test_frndint_round_zero() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD9, + 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; let test_cases = vec![ - (2.1, 2.0), (2.9, 2.0), (-2.1, -2.0), (-2.9, -2.0), - (0.1, 0.0), (0.9, 0.0), (-0.1, 0.0), (-0.9, 0.0), + (2.1, 2.0), + (2.9, 2.0), + (-2.1, -2.0), + (-2.9, -2.0), + (0.1, 0.0), + (0.9, 0.0), + (-0.1, 0.0), + (-0.9, 0.0), ]; for (input, expected) in test_cases { emu.load_code_bytes(&code); emu.maps.write_word(0x2000, RC_ZERO); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, expected, "FRNDINT({}) zero", input); } @@ -134,15 +151,14 @@ macro_rules! frndint_special_test { ($name:ident, $val:expr, $expected:expr) => { #[test] fn $name() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, + 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, $val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected_val: f64 = $expected; if expected_val.is_nan() { @@ -165,11 +181,10 @@ frndint_special_test!(test_frndint_neg_one, -1.0, -1.0); // Edge case tests #[test] fn test_frndint_large_integer() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1e15); @@ -180,11 +195,10 @@ fn test_frndint_large_integer() { #[test] fn test_frndint_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, f64::MAX); @@ -196,18 +210,13 @@ fn test_frndint_max_value() { // Tests with different modes changing mid-execution #[test] fn test_frndint_mode_switching() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Round to nearest - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - // Round down - 0xD9, 0x2C, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD9, + 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // Round down + 0xD9, 0x2C, 0x25, 0x10, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, 0xD9, + 0xFC, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, RC_NEAREST); @@ -217,28 +226,31 @@ fn test_frndint_mode_switching() { emu.run(None).unwrap(); let r1 = emu.maps.read_f64(0x3000).unwrap(); let r2 = emu.maps.read_f64(0x3008).unwrap(); - assert_eq!(r1, 2.0); // 2.5 nearest -> 2.0 (even) - assert_eq!(r2, 2.0); // 2.9 down -> 2.0 + assert_eq!(r1, 2.0); // 2.5 nearest -> 2.0 (even) + assert_eq!(r2, 2.0); // 2.9 down -> 2.0 } // Comprehensive test with all rounding modes #[test] fn test_frndint_all_modes_positive() { - let mut emu = emu64(); let input = 7.6; - let expected = [(RC_NEAREST, 8.0), (RC_DOWN, 7.0), (RC_UP, 8.0), (RC_ZERO, 7.0)]; + let mut emu = emu64(); + let input = 7.6; + let expected = [ + (RC_NEAREST, 8.0), + (RC_DOWN, 7.0), + (RC_UP, 8.0), + (RC_ZERO, 7.0), + ]; for (mode, exp) in expected { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, + 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, mode); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, exp, "Mode {:04X}", mode); } @@ -246,21 +258,24 @@ fn test_frndint_all_modes_positive() { #[test] fn test_frndint_all_modes_negative() { - let mut emu = emu64(); let input = -7.6; - let expected = [(RC_NEAREST, -8.0), (RC_DOWN, -8.0), (RC_UP, -7.0), (RC_ZERO, -7.0)]; + let mut emu = emu64(); + let input = -7.6; + let expected = [ + (RC_NEAREST, -8.0), + (RC_DOWN, -8.0), + (RC_UP, -7.0), + (RC_ZERO, -7.0), + ]; for (mode, exp) in expected { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, + 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, mode); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, exp, "Mode {:04X}", mode); } @@ -269,17 +284,12 @@ fn test_frndint_all_modes_negative() { // Stress tests with multiple values #[test] fn test_frndint_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x08, 0x30, + 0x00, 0x00, 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x10, + 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1.4); @@ -296,18 +306,16 @@ macro_rules! batch_test { ($name:ident, $mode:expr, $cases:expr) => { #[test] fn $name() { - let mut emu = emu64(); for (input, expected) in $cases { + let mut emu = emu64(); + for (input, expected) in $cases { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, + 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, $mode); emu.maps.write_f64(0x2008, input); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, expected, "{}", input); } @@ -315,33 +323,72 @@ macro_rules! batch_test { }; } -batch_test!(test_nearest_fractional, RC_NEAREST, vec![ - (1.1, 1.0), (1.9, 2.0), (2.5, 2.0), (3.5, 4.0), - (-1.1, -1.0), (-1.9, -2.0), (-2.5, -2.0), (-3.5, -4.0) -]); +batch_test!( + test_nearest_fractional, + RC_NEAREST, + vec![ + (1.1, 1.0), + (1.9, 2.0), + (2.5, 2.0), + (3.5, 4.0), + (-1.1, -1.0), + (-1.9, -2.0), + (-2.5, -2.0), + (-3.5, -4.0) + ] +); -batch_test!(test_down_fractional, RC_DOWN, vec![ - (1.1, 1.0), (1.9, 1.0), (2.5, 2.0), (3.5, 3.0), - (-1.1, -2.0), (-1.9, -2.0), (-2.5, -3.0), (-3.5, -4.0) -]); +batch_test!( + test_down_fractional, + RC_DOWN, + vec![ + (1.1, 1.0), + (1.9, 1.0), + (2.5, 2.0), + (3.5, 3.0), + (-1.1, -2.0), + (-1.9, -2.0), + (-2.5, -3.0), + (-3.5, -4.0) + ] +); -batch_test!(test_up_fractional, RC_UP, vec![ - (1.1, 2.0), (1.9, 2.0), (2.5, 3.0), (3.5, 4.0), - (-1.1, -1.0), (-1.9, -1.0), (-2.5, -2.0), (-3.5, -3.0) -]); +batch_test!( + test_up_fractional, + RC_UP, + vec![ + (1.1, 2.0), + (1.9, 2.0), + (2.5, 3.0), + (3.5, 4.0), + (-1.1, -1.0), + (-1.9, -1.0), + (-2.5, -2.0), + (-3.5, -3.0) + ] +); -batch_test!(test_zero_fractional, RC_ZERO, vec![ - (1.1, 1.0), (1.9, 1.0), (2.5, 2.0), (3.5, 3.0), - (-1.1, -1.0), (-1.9, -1.0), (-2.5, -2.0), (-3.5, -3.0) -]); +batch_test!( + test_zero_fractional, + RC_ZERO, + vec![ + (1.1, 1.0), + (1.9, 1.0), + (2.5, 2.0), + (3.5, 3.0), + (-1.1, -1.0), + (-1.9, -1.0), + (-2.5, -2.0), + (-3.5, -3.0) + ] +); #[test] fn test_frndint_tiny_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 0.0001); @@ -352,16 +399,15 @@ fn test_frndint_tiny_values() { #[test] fn test_frndint_preserves_integers() { - let mut emu = emu64(); for val in &[1.0, 2.0, 100.0, -50.0, 999.0] { + let mut emu = emu64(); + for val in &[1.0, 2.0, 100.0, -50.0, 999.0] { let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, + 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, *val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); assert_eq!(result, *val); } @@ -369,11 +415,10 @@ fn test_frndint_preserves_integers() { #[test] fn test_frndint_denormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFC, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xFC, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, f64::MIN_POSITIVE / 2.0); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsave_frstor.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsave_frstor.rs index 5f22a6f1..f56c229d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsave_frstor.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsave_frstor.rs @@ -25,33 +25,37 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // FSAVE/FRSTOR area structure offsets (in protected 32-bit mode, 108 bytes) -const FSAVE_FCW: u64 = 0; // FPU Control Word (2 bytes) -const FSAVE_FSW: u64 = 2; // FPU Status Word (2 bytes) -const FSAVE_FTW: u64 = 4; // FPU Tag Word (2 bytes) -const FSAVE_SIZE: u64 = 108; // Total size in 32-bit protected mode +const FSAVE_FCW: u64 = 0; // FPU Control Word (2 bytes) +const FSAVE_FSW: u64 = 2; // FPU Status Word (2 bytes) +const FSAVE_FTW: u64 = 4; // FPU Tag Word (2 bytes) +const FSAVE_SIZE: u64 = 108; // Total size in 32-bit protected mode // Status word bit definitions const IE_BIT: u16 = 0x0001; @@ -63,9 +67,10 @@ const TOP_MASK: u16 = 0x3800; #[test] fn test_fnsave_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -78,11 +83,11 @@ fn test_fnsave_basic() { #[test] fn test_fnsave_saves_control_word() { - let mut emu = emu64(); // FNSAVE should save the control word + let mut emu = emu64(); // FNSAVE should save the control word let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -96,11 +101,11 @@ fn test_fnsave_saves_control_word() { #[test] fn test_fnsave_saves_status_word() { - let mut emu = emu64(); // FNSAVE should save the status word + let mut emu = emu64(); // FNSAVE should save the status word let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -114,12 +119,12 @@ fn test_fnsave_saves_status_word() { #[test] fn test_fnsave_saves_fpu_registers() { - let mut emu = emu64(); // FNSAVE should save FPU register contents + let mut emu = emu64(); // FNSAVE should save FPU register contents let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -136,13 +141,13 @@ fn test_fnsave_saves_fpu_registers() { #[test] fn test_fnsave_reinitializes_fpu() { - let mut emu = emu64(); // FNSAVE should reinitialize the FPU after saving + let mut emu = emu64(); // FNSAVE should reinitialize the FPU after saving let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDF, 0xE0, // FNSTSW AX (check status after save) - 0x66, 0x89, 0x04, 0x25, 0x00, 0x40, 0x00, 0x00, // MOV word [0x4000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDF, 0xE0, // FNSTSW AX (check status after save) + 0x66, 0x89, 0x04, 0x25, 0x00, 0x40, 0x00, 0x00, // MOV word [0x4000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -156,12 +161,13 @@ fn test_fnsave_reinitializes_fpu() { #[test] fn test_fnsave_multiple_times() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSAVE [0x3200] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSAVE [0x3200] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -172,7 +178,10 @@ fn test_fnsave_multiple_times() { let fcw1 = emu.maps.read_word(0x3000 + FSAVE_FCW).unwrap(); let fcw2 = emu.maps.read_word(0x3200 + FSAVE_FCW).unwrap(); - assert_eq!(fcw1, fcw2, "Multiple FNSAVE should save identical control words"); + assert_eq!( + fcw1, fcw2, + "Multiple FNSAVE should save identical control words" + ); } // ============================================================================ @@ -181,9 +190,10 @@ fn test_fnsave_multiple_times() { #[test] fn test_fsave_basic() { - let mut emu = emu64(); let code = [ - 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -196,11 +206,11 @@ fn test_fsave_basic() { #[test] fn test_fsave_saves_control_word() { - let mut emu = emu64(); // FSAVE should save the control word + let mut emu = emu64(); // FSAVE should save the control word let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -218,15 +228,15 @@ fn test_fsave_saves_control_word() { #[test] fn test_fsave_vs_fnsave() { - let mut emu = emu64(); // FSAVE and FNSAVE should produce same result in normal operation + let mut emu = emu64(); // FSAVE and FNSAVE should produce same result in normal operation let code1 = [ - 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] - 0xF4, // HLT + 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] + 0xF4, // HLT ]; let code2 = [ - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -246,10 +256,11 @@ fn test_fsave_vs_fnsave() { #[test] fn test_frstor_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] - 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -267,14 +278,14 @@ fn test_frstor_basic() { #[test] fn test_fnsave_frstor_roundtrip() { - let mut emu = emu64(); // FNSAVE followed by FRSTOR should preserve state + let mut emu = emu64(); // FNSAVE followed by FRSTOR should preserve state let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (after init) - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (after init) + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -284,21 +295,24 @@ fn test_fnsave_frstor_roundtrip() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x4010).unwrap(); - assert_eq!(result, 1.5, "Value should be preserved through FNSAVE/FRSTOR"); + assert_eq!( + result, 1.5, + "Value should be preserved through FNSAVE/FRSTOR" + ); } #[test] fn test_fnsave_frstor_multiple_values() { - let mut emu = emu64(); // FNSAVE/FRSTOR with multiple FPU values + let mut emu = emu64(); // FNSAVE/FRSTOR with multiple FPU values let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (new value) - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x18, 0x40, 0x00, 0x00, // FSTP qword [0x4018] - 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (new value) + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x18, 0x40, 0x00, 0x00, // FSTP qword [0x4018] + 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -320,11 +334,11 @@ fn test_fnsave_frstor_multiple_values() { #[test] fn test_fnsave_area_structure() { - let mut emu = emu64(); // FNSAVE uses up to 108 bytes in 32-bit protected mode + let mut emu = emu64(); // FNSAVE uses up to 108 bytes in 32-bit protected mode let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -347,23 +361,27 @@ fn test_fnsave_area_structure() { #[test] fn test_fnsave_different_control_words() { - let mut emu = emu64(); // FNSAVE should preserve different control word values + let mut emu = emu64(); // FNSAVE should preserve different control word values let test_cws = vec![0x037F, 0x027F, 0x0C7F]; for test_cw in test_cws { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let saved_cw = emu.maps.read_word(0x3000 + FSAVE_FCW).unwrap(); - assert_eq!(saved_cw, test_cw, "Control word 0x{:04X} should be saved", test_cw); + assert_eq!( + saved_cw, test_cw, + "Control word 0x{:04X} should be saved", + test_cw + ); } } @@ -373,11 +391,11 @@ fn test_fnsave_different_control_words() { #[test] fn test_frstor_from_prepared_area() { - let mut emu = emu64(); // FRSTOR from a pre-prepared FNSAVE area + let mut emu = emu64(); // FRSTOR from a pre-prepared FNSAVE area let code = [ - 0xDD, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FRSTOR [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0xDD, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FRSTOR [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -387,7 +405,10 @@ fn test_frstor_from_prepared_area() { emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(cw, 0x037F, "Control word should be restored from prepared area"); + assert_eq!( + cw, 0x037F, + "Control word should be restored from prepared area" + ); } // ============================================================================ @@ -396,12 +417,13 @@ fn test_frstor_from_prepared_area() { #[test] fn test_sequential_fnsave() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSAVE [0x3200] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSAVE [0x3200] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -412,7 +434,10 @@ fn test_sequential_fnsave() { let fcw1 = emu.maps.read_word(0x3000 + FSAVE_FCW).unwrap(); let fcw2 = emu.maps.read_word(0x3200 + FSAVE_FCW).unwrap(); - assert_eq!(fcw1, fcw2, "Multiple FNSAVE should produce identical results"); + assert_eq!( + fcw1, fcw2, + "Multiple FNSAVE should produce identical results" + ); } // ============================================================================ @@ -421,13 +446,13 @@ fn test_sequential_fnsave() { #[test] fn test_fnsave_after_arithmetic() { - let mut emu = emu64(); // FNSAVE after arithmetic operations + let mut emu = emu64(); // FNSAVE after arithmetic operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -442,13 +467,13 @@ fn test_fnsave_after_arithmetic() { #[test] fn test_frstor_then_arithmetic() { - let mut emu = emu64(); // FRSTOR followed by arithmetic + let mut emu = emu64(); // FRSTOR followed by arithmetic let code = [ - 0xDD, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FRSTOR [0x2000] - 0xDD, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FLD qword [0x3000] - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + 0xDD, 0x24, 0x25, 0x00, 0x20, 0x00, 0x00, // FRSTOR [0x2000] + 0xDD, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FLD qword [0x3000] + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -468,15 +493,15 @@ fn test_frstor_then_arithmetic() { #[test] fn test_fnsave_preserves_control_precision() { - let mut emu = emu64(); // FNSAVE should preserve control word precision bits + let mut emu = emu64(); // FNSAVE should preserve control word precision bits let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_word(0x2000, 0x037F); // Default (64-bit precision) + emu.maps.write_word(0x2000, 0x037F); // Default (64-bit precision) emu.run(None).unwrap(); @@ -491,21 +516,22 @@ fn test_fnsave_preserves_control_precision() { #[test] fn test_fnsave_frstor_complete_flow() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Load and use FPU - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] // Save state - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] // FPU is reinitialized by FNSAVE, do some other work - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] // Restore saved state - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] // Use restored state - 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] - 0xDD, 0x1C, 0x25, 0x28, 0x40, 0x00, 0x00, // FSTP qword [0x4028] - 0xF4, // HLT + 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] + 0xDD, 0x1C, 0x25, 0x28, 0x40, 0x00, 0x00, // FSTP qword [0x4028] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -523,18 +549,19 @@ fn test_fnsave_frstor_complete_flow() { #[test] fn test_fnsave_frstor_multiple_cycles() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Cycle 1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] // Cycle 2 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSAVE [0x3200] - 0xDD, 0x24, 0x25, 0x00, 0x32, 0x00, 0x00, // FRSTOR [0x3200] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x34, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSAVE [0x3200] + 0xDD, 0x24, 0x25, 0x00, 0x32, 0x00, 0x00, // FRSTOR [0x3200] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -551,12 +578,13 @@ fn test_fnsave_frstor_multiple_cycles() { #[test] fn test_fsave_vs_fnsave_roundtrip() { - let mut emu = emu64(); let code1 = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + let mut emu = emu64(); + let code1 = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x9B, 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FSAVE [0x3000] + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -568,11 +596,11 @@ fn test_fsave_vs_fnsave_roundtrip() { assert_eq!(result1, 1.5, "FSAVE roundtrip should preserve value"); let code2 = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] - 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSAVE [0x3000] + 0xDD, 0x24, 0x25, 0x00, 0x30, 0x00, 0x00, // FRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code2); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fscale.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fscale.rs index 67cb717e..409451fd 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fscale.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fscale.rs @@ -29,12 +29,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -45,23 +47,23 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fscale_multiply_by_2() { - let mut emu = emu64(); // FLD qword [0x2000] ; Load value to scale (ST(0)) - // FLD qword [0x2008] ; Load scale factor (ST(0), value becomes ST(1)) - // FSCALE ; ST(0) = ST(1) * 2^trunc(ST(0)) - // FSTP qword [0x3000] ; Store result - // HLT + let mut emu = emu64(); // FLD qword [0x2000] ; Load value to scale (ST(0)) + // FLD qword [0x2008] ; Load scale factor (ST(0), value becomes ST(1)) + // FSCALE ; ST(0) = ST(1) * 2^trunc(ST(0)) + // FSTP qword [0x3000] ; Store result + // HLT let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFD, // FSCALE - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) (clean stack) - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFD, // FSCALE + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) (clean stack) + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 5.0); // Value to scale - emu.maps.write_f64(0x2008, 1.0); // Scale factor + emu.maps.write_f64(0x2000, 5.0); // Value to scale + emu.maps.write_f64(0x2008, 1.0); // Scale factor emu.run(None).unwrap(); @@ -71,13 +73,10 @@ fn test_fscale_multiply_by_2() { #[test] fn test_fscale_multiply_by_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -92,13 +91,10 @@ fn test_fscale_multiply_by_4() { #[test] fn test_fscale_multiply_by_8() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -113,13 +109,10 @@ fn test_fscale_multiply_by_8() { #[test] fn test_fscale_multiply_by_1024() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -129,7 +122,10 @@ fn test_fscale_multiply_by_1024() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1024.0).abs() < 1e-13, "1.0 * 2^10 should be 1024.0"); + assert!( + (result - 1024.0).abs() < 1e-13, + "1.0 * 2^10 should be 1024.0" + ); } // ============================================================================ @@ -138,13 +134,10 @@ fn test_fscale_multiply_by_1024() { #[test] fn test_fscale_divide_by_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -159,13 +152,10 @@ fn test_fscale_divide_by_2() { #[test] fn test_fscale_divide_by_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -180,13 +170,10 @@ fn test_fscale_divide_by_4() { #[test] fn test_fscale_divide_by_8() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -201,13 +188,10 @@ fn test_fscale_divide_by_8() { #[test] fn test_fscale_divide_by_1024() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -226,13 +210,10 @@ fn test_fscale_divide_by_1024() { #[test] fn test_fscale_zero_scale_factor() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -247,13 +228,10 @@ fn test_fscale_zero_scale_factor() { #[test] fn test_fscale_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -263,18 +241,18 @@ fn test_fscale_positive_zero() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 99.5).abs() < 1e-14, "Value should remain unchanged"); + assert!( + (result - 99.5).abs() < 1e-14, + "Value should remain unchanged" + ); } #[test] fn test_fscale_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -284,7 +262,10 @@ fn test_fscale_negative_zero() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 77.7).abs() < 1e-14, "Value should remain unchanged"); + assert!( + (result - 77.7).abs() < 1e-14, + "Value should remain unchanged" + ); } // ============================================================================ @@ -293,13 +274,10 @@ fn test_fscale_negative_zero() { #[test] fn test_fscale_truncate_positive_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -310,19 +288,18 @@ fn test_fscale_truncate_positive_fraction() { let result = emu.maps.read_f64(0x3000).unwrap(); // 2.9 truncates to 2, so 1.0 * 2^2 = 4.0 - assert!((result - 4.0).abs() < 1e-15, - "Scale factor 2.9 should truncate to 2"); + assert!( + (result - 4.0).abs() < 1e-15, + "Scale factor 2.9 should truncate to 2" + ); } #[test] fn test_fscale_truncate_negative_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -333,19 +310,18 @@ fn test_fscale_truncate_negative_fraction() { let result = emu.maps.read_f64(0x3000).unwrap(); // -2.9 truncates to -2, so 16.0 * 2^-2 = 4.0 - assert!((result - 4.0).abs() < 1e-15, - "Scale factor -2.9 should truncate to -2"); + assert!( + (result - 4.0).abs() < 1e-15, + "Scale factor -2.9 should truncate to -2" + ); } #[test] fn test_fscale_truncate_small_positive_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -356,19 +332,18 @@ fn test_fscale_truncate_small_positive_fraction() { let result = emu.maps.read_f64(0x3000).unwrap(); // 0.9 truncates to 0, so 5.0 * 2^0 = 5.0 - assert!((result - 5.0).abs() < 1e-15, - "Scale factor 0.9 should truncate to 0"); + assert!( + (result - 5.0).abs() < 1e-15, + "Scale factor 0.9 should truncate to 0" + ); } #[test] fn test_fscale_truncate_small_negative_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -379,8 +354,10 @@ fn test_fscale_truncate_small_negative_fraction() { let result = emu.maps.read_f64(0x3000).unwrap(); // -0.9 truncates to 0, so 7.0 * 2^0 = 7.0 - assert!((result - 7.0).abs() < 1e-15, - "Scale factor -0.9 should truncate to 0"); + assert!( + (result - 7.0).abs() < 1e-15, + "Scale factor -0.9 should truncate to 0" + ); } // ============================================================================ @@ -389,13 +366,10 @@ fn test_fscale_truncate_small_negative_fraction() { #[test] fn test_fscale_negative_value_positive_scale() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -405,18 +379,18 @@ fn test_fscale_negative_value_positive_scale() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - (-12.0)).abs() < 1e-15, "-3.0 * 2^2 should be -12.0"); + assert!( + (result - (-12.0)).abs() < 1e-15, + "-3.0 * 2^2 should be -12.0" + ); } #[test] fn test_fscale_negative_value_negative_scale() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -426,7 +400,10 @@ fn test_fscale_negative_value_negative_scale() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - (-2.0)).abs() < 1e-15, "-8.0 * 2^-2 should be -2.0"); + assert!( + (result - (-2.0)).abs() < 1e-15, + "-8.0 * 2^-2 should be -2.0" + ); } // ============================================================================ @@ -435,13 +412,10 @@ fn test_fscale_negative_value_negative_scale() { #[test] fn test_fscale_zero_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -451,19 +425,18 @@ fn test_fscale_zero_value() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result == 0.0 && !result.is_sign_negative(), - "0.0 * 2^5 should be +0.0"); + assert!( + result == 0.0 && !result.is_sign_negative(), + "0.0 * 2^5 should be +0.0" + ); } #[test] fn test_fscale_negative_zero_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -473,8 +446,10 @@ fn test_fscale_negative_zero_value() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result == 0.0 && result.is_sign_negative(), - "-0.0 * 2^5 should be -0.0"); + assert!( + result == 0.0 && result.is_sign_negative(), + "-0.0 * 2^5 should be -0.0" + ); } // ============================================================================ @@ -483,13 +458,14 @@ fn test_fscale_negative_zero_value() { #[test] fn test_fscale_fxtract_reversal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF4, // FXTRACT (ST(0)=sig, ST(1)=exp) - 0xD9, 0xFD, // FSCALE (ST(0) = sig * 2^exp) - 0xDD, 0xD9, // FSTP ST(1) (pop exponent) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF4, // FXTRACT (ST(0)=sig, ST(1)=exp) + 0xD9, 0xFD, // FSCALE (ST(0) = sig * 2^exp) + 0xDD, 0xD9, // FSTP ST(1) (pop exponent) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -499,19 +475,18 @@ fn test_fscale_fxtract_reversal() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - original).abs() < 1e-14, - "FXTRACT followed by FSCALE should restore original value"); + assert!( + (result - original).abs() < 1e-14, + "FXTRACT followed by FSCALE should restore original value" + ); } #[test] fn test_fscale_fxtract_reversal_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xD9, 0xFD, - 0xDD, 0xD9, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xD9, 0xFD, 0xDD, 0xD9, 0xDD, 0x1C, + 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -521,19 +496,18 @@ fn test_fscale_fxtract_reversal_negative() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - original).abs() < 1e-13, - "FXTRACT followed by FSCALE should restore negative value"); + assert!( + (result - original).abs() < 1e-13, + "FXTRACT followed by FSCALE should restore negative value" + ); } #[test] fn test_fscale_fxtract_reversal_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xD9, 0xFD, - 0xDD, 0xD9, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xD9, 0xFD, 0xDD, 0xD9, 0xDD, 0x1C, + 0x25, 0x00, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -543,8 +517,10 @@ fn test_fscale_fxtract_reversal_small() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - original).abs() < 1e-17, - "FXTRACT followed by FSCALE should restore small value"); + assert!( + (result - original).abs() < 1e-17, + "FXTRACT followed by FSCALE should restore small value" + ); } // ============================================================================ @@ -553,13 +529,10 @@ fn test_fscale_fxtract_reversal_small() { #[test] fn test_fscale_large_positive_scale() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -570,19 +543,18 @@ fn test_fscale_large_positive_scale() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0_f64.powf(100.0); - assert!((result - expected).abs() / expected < 1e-15, - "1.0 * 2^100 should match"); + assert!( + (result - expected).abs() / expected < 1e-15, + "1.0 * 2^100 should match" + ); } #[test] fn test_fscale_large_negative_scale() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -593,8 +565,10 @@ fn test_fscale_large_negative_scale() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0_f64.powf(-100.0); - assert!((result - expected).abs() / expected < 1e-15, - "1.0 * 2^-100 should match"); + assert!( + (result - expected).abs() / expected < 1e-15, + "1.0 * 2^-100 should match" + ); } // ============================================================================ @@ -603,13 +577,10 @@ fn test_fscale_large_negative_scale() { #[test] fn test_fscale_pi_scale_by_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -620,19 +591,18 @@ fn test_fscale_pi_scale_by_4() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::PI * 16.0; - assert!((result - expected).abs() < 1e-13, - "π * 2^4 should be π * 16"); + assert!( + (result - expected).abs() < 1e-13, + "π * 2^4 should be π * 16" + ); } #[test] fn test_fscale_e_scale_by_minus_3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, + 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -643,13 +613,16 @@ fn test_fscale_e_scale_by_minus_3() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::E / 8.0; - assert!((result - expected).abs() < 1e-15, - "e * 2^-3 should be e / 8"); + assert!( + (result - expected).abs() < 1e-15, + "e * 2^-3 should be e / 8" + ); } #[test] fn test_fscale_series() { - let mut emu = emu64(); let test_cases = [ + let mut emu = emu64(); + let test_cases = [ (1.0, 0.0, 1.0), (1.0, 1.0, 2.0), (1.0, 2.0, 4.0), @@ -662,22 +635,24 @@ fn test_fscale_series() { for &(value, scale, expected) in &test_cases { let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xFD, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, + 0xD9, 0xFD, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, value); emu.maps.write_f64(0x2008, scale); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - expected).abs() < 1e-14, - "{} * 2^{} should be {}, got {}", value, scale, expected, result); + assert!( + (result - expected).abs() < 1e-14, + "{} * 2^{} should be {}, got {}", + value, + scale, + expected, + result + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsin_fcos.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsin_fcos.rs index 0f1b1830..94099e35 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsin_fcos.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsin_fcos.rs @@ -18,7 +18,7 @@ //! Flags affected: //! - C1: Set to 0 if stack underflow occurred; Set if result was rounded up //! - C2: Set to 1 if outside range (-2^63 < source < +2^63); - // otherwise 0 +// otherwise 0 //! - C0, C3: Undefined //! //! Reference: /Users/int/dev/rax/docs/fsin.txt, /Users/int/dev/rax/docs/fcos.txt @@ -28,12 +28,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -44,15 +46,15 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fsin_zero() { - let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 - // FSIN ; D9 FE - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 + // FSIN ; D9 FE + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -66,11 +68,12 @@ fn test_fsin_zero() { #[test] fn test_fsin_pi_over_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -84,11 +87,12 @@ fn test_fsin_pi_over_2() { #[test] fn test_fsin_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -102,15 +106,17 @@ fn test_fsin_pi() { #[test] fn test_fsin_3pi_over_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); emu.run(None).unwrap(); @@ -120,11 +126,12 @@ fn test_fsin_3pi_over_2() { #[test] fn test_fsin_2pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -138,11 +145,12 @@ fn test_fsin_2pi() { #[test] fn test_fsin_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -157,11 +165,12 @@ fn test_fsin_pi_over_4() { #[test] fn test_fsin_pi_over_6() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -179,11 +188,12 @@ fn test_fsin_pi_over_6() { #[test] fn test_fsin_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -197,11 +207,12 @@ fn test_fsin_negative_zero() { #[test] fn test_fsin_negative_pi_over_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -215,11 +226,12 @@ fn test_fsin_negative_pi_over_2() { #[test] fn test_fsin_negative_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -237,15 +249,15 @@ fn test_fsin_negative_pi() { #[test] fn test_fcos_zero() { - let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 - // FCOS ; D9 FF - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 + // FCOS ; D9 FF + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -259,11 +271,12 @@ fn test_fcos_zero() { #[test] fn test_fcos_pi_over_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -277,11 +290,12 @@ fn test_fcos_pi_over_2() { #[test] fn test_fcos_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -295,15 +309,17 @@ fn test_fcos_pi() { #[test] fn test_fcos_3pi_over_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); emu.run(None).unwrap(); @@ -313,11 +329,12 @@ fn test_fcos_3pi_over_2() { #[test] fn test_fcos_2pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -331,11 +348,12 @@ fn test_fcos_2pi() { #[test] fn test_fcos_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -350,11 +368,12 @@ fn test_fcos_pi_over_4() { #[test] fn test_fcos_pi_over_6() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -373,11 +392,12 @@ fn test_fcos_pi_over_6() { #[test] fn test_fcos_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -391,11 +411,12 @@ fn test_fcos_negative_zero() { #[test] fn test_fcos_negative_pi_over_2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -409,11 +430,12 @@ fn test_fcos_negative_pi_over_2() { #[test] fn test_fcos_negative_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -431,11 +453,12 @@ fn test_fcos_negative_pi() { #[test] fn test_fsin_large_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -449,11 +472,12 @@ fn test_fsin_large_positive() { #[test] fn test_fcos_large_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -467,12 +491,12 @@ fn test_fcos_large_positive() { #[test] fn test_fsin_multiple_periods() { - let mut emu = emu64(); // sin(x + 2πn) = sin(x) + let mut emu = emu64(); // sin(x + 2πn) = sin(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -488,12 +512,12 @@ fn test_fsin_multiple_periods() { #[test] fn test_fcos_multiple_periods() { - let mut emu = emu64(); // cos(x + 2πn) = cos(x) + let mut emu = emu64(); // cos(x + 2πn) = cos(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -513,18 +537,18 @@ fn test_fcos_multiple_periods() { #[test] fn test_sin_cos_pythagorean_identity() { - let mut emu = emu64(); // sin²(x) + cos²(x) = 1 + let mut emu = emu64(); // sin²(x) + cos²(x) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xC0, // FLD ST(0) (duplicate) - 0xD9, 0xFE, // FSIN - 0xD8, 0xC8, // FMUL ST(0), ST(0) (sin²) - 0xD9, 0xC9, // FXCH ST(1) - 0xD9, 0xFF, // FCOS - 0xD8, 0xC8, // FMUL ST(0), ST(0) (cos²) - 0xDE, 0xC1, // FADDP (add sin² + cos²) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xC0, // FLD ST(0) (duplicate) + 0xD9, 0xFE, // FSIN + 0xD8, 0xC8, // FMUL ST(0), ST(0) (sin²) + 0xD9, 0xC9, // FXCH ST(1) + 0xD9, 0xFF, // FCOS + 0xD8, 0xC8, // FMUL ST(0), ST(0) (cos²) + 0xDE, 0xC1, // FADDP (add sin² + cos²) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -533,17 +557,20 @@ fn test_sin_cos_pythagorean_identity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-14, "sin²(x) + cos²(x) should equal 1"); + assert!( + (result - 1.0).abs() < 1e-14, + "sin²(x) + cos²(x) should equal 1" + ); } #[test] fn test_sin_odd_function() { - let mut emu = emu64(); // sin(-x) = -sin(x) + let mut emu = emu64(); // sin(-x) = -sin(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let angle = 0.5; @@ -558,17 +585,20 @@ fn test_sin_odd_function() { emu.run(None).unwrap(); let sin_negative = emu.maps.read_f64(0x3000).unwrap(); - assert!((sin_positive + sin_negative).abs() < 1e-15, "sin(-x) should equal -sin(x)"); + assert!( + (sin_positive + sin_negative).abs() < 1e-15, + "sin(-x) should equal -sin(x)" + ); } #[test] fn test_cos_even_function() { - let mut emu = emu64(); // cos(-x) = cos(x) + let mut emu = emu64(); // cos(-x) = cos(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let angle = 0.5; @@ -583,7 +613,10 @@ fn test_cos_even_function() { emu.run(None).unwrap(); let cos_negative = emu.maps.read_f64(0x3000).unwrap(); - assert!((cos_positive - cos_negative).abs() < 1e-15, "cos(-x) should equal cos(x)"); + assert!( + (cos_positive - cos_negative).abs() < 1e-15, + "cos(-x) should equal cos(x)" + ); } // ============================================================================ @@ -592,11 +625,12 @@ fn test_cos_even_function() { #[test] fn test_fsin_small_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -611,11 +645,12 @@ fn test_fsin_small_angle() { #[test] fn test_fcos_small_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -634,11 +669,12 @@ fn test_fcos_small_angle() { #[test] fn test_fsin_various_angles() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_angles = vec![0.1, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]; @@ -647,21 +683,26 @@ fn test_fsin_various_angles() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, angle); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = angle.sin(); - assert!((result - expected).abs() < 1e-14, "sin({}) error too large", angle); + assert!( + (result - expected).abs() < 1e-14, + "sin({}) error too large", + angle + ); } } #[test] fn test_fcos_various_angles() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_angles = vec![0.1, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]; @@ -670,11 +711,15 @@ fn test_fcos_various_angles() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, angle); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = angle.cos(); - assert!((result - expected).abs() < 1e-14, "cos({}) error too large", angle); + assert!( + (result - expected).abs() < 1e-14, + "cos({}) error too large", + angle + ); } } @@ -684,12 +729,12 @@ fn test_fcos_various_angles() { #[test] fn test_fsin_infinity() { - let mut emu = emu64(); // FSIN of infinity should produce NaN (invalid operation) and set C2 + let mut emu = emu64(); // FSIN of infinity should produce NaN (invalid operation) and set C2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -703,12 +748,12 @@ fn test_fsin_infinity() { #[test] fn test_fcos_infinity() { - let mut emu = emu64(); // FCOS of infinity should produce NaN (invalid operation) and set C2 + let mut emu = emu64(); // FCOS of infinity should produce NaN (invalid operation) and set C2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -722,11 +767,12 @@ fn test_fcos_infinity() { #[test] fn test_fsin_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -740,11 +786,12 @@ fn test_fsin_nan() { #[test] fn test_fcos_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -758,11 +805,12 @@ fn test_fcos_nan() { #[test] fn test_fsin_pi_over_3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -777,11 +825,12 @@ fn test_fsin_pi_over_3() { #[test] fn test_fcos_pi_over_3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -796,11 +845,12 @@ fn test_fcos_pi_over_3() { #[test] fn test_fsin_negative_pi_over_4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -810,17 +860,20 @@ fn test_fsin_negative_pi_over_4() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (-std::f64::consts::FRAC_PI_4).sin(); - assert!((result - expected).abs() < 1e-15, "sin(-π/4) should be -√2/2"); + assert!( + (result - expected).abs() < 1e-15, + "sin(-π/4) should be -√2/2" + ); } #[test] fn test_fcos_2pi_plus_pi_over_6() { - let mut emu = emu64(); // cos(2π + π/6) = cos(π/6) + let mut emu = emu64(); // cos(2π + π/6) = cos(π/6) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFF, // FCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFF, // FCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -831,17 +884,20 @@ fn test_fcos_2pi_plus_pi_over_6() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (std::f64::consts::FRAC_PI_6).cos(); - assert!((result - expected).abs() < 1e-14, "cos(2π + π/6) should equal cos(π/6)"); + assert!( + (result - expected).abs() < 1e-14, + "cos(2π + π/6) should equal cos(π/6)" + ); } #[test] fn test_fsin_bounds_check() { - let mut emu = emu64(); // sin should always be in [-1, 1] + let mut emu = emu64(); // sin should always be in [-1, 1] let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFE, // FSIN - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFE, // FSIN + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_angles = vec![0.1, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0]; @@ -850,9 +906,14 @@ fn test_fsin_bounds_check() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, angle); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result >= -1.0 && result <= 1.0, "sin({}) must be in [-1, 1], got {}", angle, result); + assert!( + result >= -1.0 && result <= 1.0, + "sin({}) must be in [-1, 1], got {}", + angle, + result + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsincos.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsincos.rs index c1ce9017..47c1c561 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsincos.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsincos.rs @@ -12,7 +12,7 @@ //! Flags affected: //! - C1: Set to 0 if stack underflow; set to 1 if stack overflow; set if result rounded up //! - C2: Set to 1 if outside range (-2^63 < source < +2^63); - // otherwise 0 +// otherwise 0 //! - C0, C3: Undefined //! //! Reference: /Users/int/dev/rax/docs/fsincos.txt @@ -22,12 +22,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -38,13 +40,13 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fsincos_zero() { - let mut emu = emu64(); // sin(0) = 0, cos(0) = 1 + let mut emu = emu64(); // sin(0) = 0, cos(0) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -60,13 +62,13 @@ fn test_fsincos_zero() { #[test] fn test_fsincos_pi_over_2() { - let mut emu = emu64(); // sin(π/2) = 1, cos(π/2) = 0 + let mut emu = emu64(); // sin(π/2) = 1, cos(π/2) = 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -82,13 +84,13 @@ fn test_fsincos_pi_over_2() { #[test] fn test_fsincos_pi() { - let mut emu = emu64(); // sin(π) = 0, cos(π) = -1 + let mut emu = emu64(); // sin(π) = 0, cos(π) = -1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -104,17 +106,18 @@ fn test_fsincos_pi() { #[test] fn test_fsincos_3pi_over_2() { - let mut emu = emu64(); // sin(3π/2) = -1, cos(3π/2) = 0 + let mut emu = emu64(); // sin(3π/2) = -1, cos(3π/2) = 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); + emu.maps + .write_f64(0x2000, 3.0 * std::f64::consts::FRAC_PI_2); emu.run(None).unwrap(); @@ -126,13 +129,13 @@ fn test_fsincos_3pi_over_2() { #[test] fn test_fsincos_2pi() { - let mut emu = emu64(); // sin(2π) = 0, cos(2π) = 1 + let mut emu = emu64(); // sin(2π) = 0, cos(2π) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -148,13 +151,13 @@ fn test_fsincos_2pi() { #[test] fn test_fsincos_pi_over_4() { - let mut emu = emu64(); // sin(π/4) = cos(π/4) = √2/2 + let mut emu = emu64(); // sin(π/4) = cos(π/4) = √2/2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -172,13 +175,13 @@ fn test_fsincos_pi_over_4() { #[test] fn test_fsincos_pi_over_6() { - let mut emu = emu64(); // sin(π/6) = 0.5, cos(π/6) = √3/2 + let mut emu = emu64(); // sin(π/6) = 0.5, cos(π/6) = √3/2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -190,18 +193,21 @@ fn test_fsincos_pi_over_6() { let sine = emu.maps.read_f64(0x3008).unwrap(); assert!((sine - 0.5).abs() < 1e-15, "sin(π/6) should be 0.5"); let expected_cos = (std::f64::consts::FRAC_PI_6).cos(); - assert!((cosine - expected_cos).abs() < 1e-15, "cos(π/6) should be √3/2"); + assert!( + (cosine - expected_cos).abs() < 1e-15, + "cos(π/6) should be √3/2" + ); } #[test] fn test_fsincos_pi_over_3() { - let mut emu = emu64(); // sin(π/3) = √3/2, cos(π/3) = 0.5 + let mut emu = emu64(); // sin(π/3) = √3/2, cos(π/3) = 0.5 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -212,7 +218,10 @@ fn test_fsincos_pi_over_3() { let cosine = emu.maps.read_f64(0x3000).unwrap(); let sine = emu.maps.read_f64(0x3008).unwrap(); let expected_sin = (std::f64::consts::PI / 3.0).sin(); - assert!((sine - expected_sin).abs() < 1e-15, "sin(π/3) should be √3/2"); + assert!( + (sine - expected_sin).abs() < 1e-15, + "sin(π/3) should be √3/2" + ); assert!((cosine - 0.5).abs() < 1e-15, "cos(π/3) should be 0.5"); } @@ -222,13 +231,13 @@ fn test_fsincos_pi_over_3() { #[test] fn test_fsincos_negative_zero() { - let mut emu = emu64(); // sin(-0) = -0, cos(-0) = 1 + let mut emu = emu64(); // sin(-0) = -0, cos(-0) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -244,13 +253,13 @@ fn test_fsincos_negative_zero() { #[test] fn test_fsincos_negative_pi_over_2() { - let mut emu = emu64(); // sin(-π/2) = -1, cos(-π/2) = 0 + let mut emu = emu64(); // sin(-π/2) = -1, cos(-π/2) = 0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -266,13 +275,13 @@ fn test_fsincos_negative_pi_over_2() { #[test] fn test_fsincos_negative_pi() { - let mut emu = emu64(); // sin(-π) = 0, cos(-π) = -1 + let mut emu = emu64(); // sin(-π) = 0, cos(-π) = -1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -288,13 +297,13 @@ fn test_fsincos_negative_pi() { #[test] fn test_fsincos_negative_pi_over_4() { - let mut emu = emu64(); // sin(-π/4) = -√2/2, cos(-π/4) = √2/2 + let mut emu = emu64(); // sin(-π/4) = -√2/2, cos(-π/4) = √2/2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -306,7 +315,10 @@ fn test_fsincos_negative_pi_over_4() { let sine = emu.maps.read_f64(0x3008).unwrap(); let expected = (-std::f64::consts::FRAC_PI_4).sin(); assert!((sine - expected).abs() < 1e-15, "sin(-π/4) should be -√2/2"); - assert!((cosine + sine).abs() < 1e-15, "cos(-π/4) should equal -sin(-π/4)"); + assert!( + (cosine + sine).abs() < 1e-15, + "cos(-π/4) should equal -sin(-π/4)" + ); } // ============================================================================ @@ -315,18 +327,18 @@ fn test_fsincos_negative_pi_over_4() { #[test] fn test_fsincos_pythagorean_identity() { - let mut emu = emu64(); // sin²(x) + cos²(x) = 1 + let mut emu = emu64(); // sin²(x) + cos²(x) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xD9, 0xC0, // FLD ST(0) (duplicate cosine) - 0xD8, 0xC8, // FMUL ST(0), ST(0) (cos²) - 0xD9, 0xCA, // FXCH ST(2) - 0xD8, 0xC8, // FMUL ST(0), ST(0) (sin²) - 0xDE, 0xC2, // FADDP (add sin² + cos²) - 0xDD, 0xD8, // FSTP ST(0) (pop extra) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xD9, 0xC0, // FLD ST(0) (duplicate cosine) + 0xD8, 0xC8, // FMUL ST(0), ST(0) (cos²) + 0xD9, 0xCA, // FXCH ST(2) + 0xD8, 0xC8, // FMUL ST(0), ST(0) (sin²) + 0xDE, 0xC2, // FADDP (add sin² + cos²) + 0xDD, 0xD8, // FSTP ST(0) (pop extra) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -335,18 +347,21 @@ fn test_fsincos_pythagorean_identity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 1.0).abs() < 1e-14, "sin²(x) + cos²(x) should equal 1"); + assert!( + (result - 1.0).abs() < 1e-14, + "sin²(x) + cos²(x) should equal 1" + ); } #[test] fn test_fsincos_odd_even_symmetry() { - let mut emu = emu64(); // sin(-x) = -sin(x), cos(-x) = cos(x) + let mut emu = emu64(); // sin(-x) = -sin(x), cos(-x) = cos(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; let angle = 0.5; @@ -363,19 +378,25 @@ fn test_fsincos_odd_even_symmetry() { let cos_negative = emu.maps.read_f64(0x3000).unwrap(); let sin_negative = emu.maps.read_f64(0x3008).unwrap(); - assert!((sin_positive + sin_negative).abs() < 1e-15, "sin(-x) should equal -sin(x)"); - assert!((cos_positive - cos_negative).abs() < 1e-15, "cos(-x) should equal cos(x)"); + assert!( + (sin_positive + sin_negative).abs() < 1e-15, + "sin(-x) should equal -sin(x)" + ); + assert!( + (cos_positive - cos_negative).abs() < 1e-15, + "cos(-x) should equal cos(x)" + ); } #[test] fn test_fsincos_periodicity() { - let mut emu = emu64(); // sin(x + 2π) = sin(x), cos(x + 2π) = cos(x) + let mut emu = emu64(); // sin(x + 2π) = sin(x), cos(x + 2π) = cos(x) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; let angle = std::f64::consts::FRAC_PI_6; @@ -387,13 +408,20 @@ fn test_fsincos_periodicity() { let sin1 = emu.maps.read_f64(0x3008).unwrap(); emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, angle + 2.0 * std::f64::consts::PI); + emu.maps + .write_f64(0x2000, angle + 2.0 * std::f64::consts::PI); emu.run(None).unwrap(); let cos2 = emu.maps.read_f64(0x3000).unwrap(); let sin2 = emu.maps.read_f64(0x3008).unwrap(); - assert!((sin1 - sin2).abs() < 1e-14, "sin(x + 2π) should equal sin(x)"); - assert!((cos1 - cos2).abs() < 1e-14, "cos(x + 2π) should equal cos(x)"); + assert!( + (sin1 - sin2).abs() < 1e-14, + "sin(x + 2π) should equal sin(x)" + ); + assert!( + (cos1 - cos2).abs() < 1e-14, + "cos(x + 2π) should equal cos(x)" + ); } // ============================================================================ @@ -402,12 +430,13 @@ fn test_fsincos_periodicity() { #[test] fn test_fsincos_large_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -423,12 +452,13 @@ fn test_fsincos_large_positive() { #[test] fn test_fsincos_large_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -438,8 +468,14 @@ fn test_fsincos_large_negative() { let cosine = emu.maps.read_f64(0x3000).unwrap(); let sine = emu.maps.read_f64(0x3008).unwrap(); - assert!(sine.abs() <= 1.0, "sin(large negative) should be in [-1, 1]"); - assert!(cosine.abs() <= 1.0, "cos(large negative) should be in [-1, 1]"); + assert!( + sine.abs() <= 1.0, + "sin(large negative) should be in [-1, 1]" + ); + assert!( + cosine.abs() <= 1.0, + "cos(large negative) should be in [-1, 1]" + ); } // ============================================================================ @@ -448,12 +484,13 @@ fn test_fsincos_large_negative() { #[test] fn test_fsincos_small_angle() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -474,12 +511,13 @@ fn test_fsincos_small_angle() { #[test] fn test_fsincos_various_angles() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; let test_angles = vec![0.1, 0.2, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0]; @@ -488,14 +526,22 @@ fn test_fsincos_various_angles() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, angle); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let cosine = emu.maps.read_f64(0x3000).unwrap(); let sine = emu.maps.read_f64(0x3008).unwrap(); let expected_sin = angle.sin(); let expected_cos = angle.cos(); - assert!((sine - expected_sin).abs() < 1e-14, "sin({}) error too large", angle); - assert!((cosine - expected_cos).abs() < 1e-14, "cos({}) error too large", angle); + assert!( + (sine - expected_sin).abs() < 1e-14, + "sin({}) error too large", + angle + ); + assert!( + (cosine - expected_cos).abs() < 1e-14, + "cos({}) error too large", + angle + ); } } @@ -505,13 +551,13 @@ fn test_fsincos_various_angles() { #[test] fn test_fsincos_infinity() { - let mut emu = emu64(); // FSINCOS of infinity should produce NaN + let mut emu = emu64(); // FSINCOS of infinity should produce NaN let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -527,13 +573,13 @@ fn test_fsincos_infinity() { #[test] fn test_fsincos_neg_infinity() { - let mut emu = emu64(); // FSINCOS of -infinity should produce NaN + let mut emu = emu64(); // FSINCOS of -infinity should produce NaN let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -549,12 +595,13 @@ fn test_fsincos_neg_infinity() { #[test] fn test_fsincos_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -574,16 +621,17 @@ fn test_fsincos_nan() { #[test] fn test_fsincos_multiple_angles() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cos1 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sin1 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] ; cos2 - 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] ; sin2 - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cos1 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sin1 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] ; cos2 + 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] ; sin2 + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -614,12 +662,13 @@ fn test_fsincos_multiple_angles() { #[test] fn test_fsincos_all_quadrants() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -627,7 +676,10 @@ fn test_fsincos_all_quadrants() { emu.run(None).unwrap(); let cos_q1 = emu.maps.read_f64(0x3000).unwrap(); let sin_q1 = emu.maps.read_f64(0x3008).unwrap(); - assert!(sin_q1 > 0.0 && cos_q1 > 0.0, "Quadrant I: both should be positive"); + assert!( + sin_q1 > 0.0 && cos_q1 > 0.0, + "Quadrant I: both should be positive" + ); emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 2.0 * std::f64::consts::PI / 3.0); @@ -641,7 +693,10 @@ fn test_fsincos_all_quadrants() { emu.run(None).unwrap(); let cos_q3 = emu.maps.read_f64(0x3000).unwrap(); let sin_q3 = emu.maps.read_f64(0x3008).unwrap(); - assert!(sin_q3 < 0.0 && cos_q3 < 0.0, "Quadrant III: both should be negative"); + assert!( + sin_q3 < 0.0 && cos_q3 < 0.0, + "Quadrant III: both should be negative" + ); emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 5.0 * std::f64::consts::PI / 3.0); @@ -653,12 +708,13 @@ fn test_fsincos_all_quadrants() { #[test] fn test_fsincos_bound_check() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFB, // FSINCOS - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFB, // FSINCOS + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; cosine + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; sine + 0xF4, // HLT ]; let test_angles = vec![0.1, 0.5, 1.0, 2.0, 3.0, 5.0, 10.0, 50.0]; @@ -667,11 +723,21 @@ fn test_fsincos_bound_check() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, angle); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let cosine = emu.maps.read_f64(0x3000).unwrap(); let sine = emu.maps.read_f64(0x3008).unwrap(); - assert!(sine >= -1.0 && sine <= 1.0, "sin({}) must be in [-1, 1], got {}", angle, sine); - assert!(cosine >= -1.0 && cosine <= 1.0, "cos({}) must be in [-1, 1], got {}", angle, cosine); + assert!( + sine >= -1.0 && sine <= 1.0, + "sin({}) must be in [-1, 1], got {}", + angle, + sine + ); + assert!( + cosine >= -1.0 && cosine <= 1.0, + "cos({}) must be in [-1, 1], got {}", + angle, + cosine + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsqrt.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsqrt.rs index 68aa7f72..e0f024a9 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsqrt.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsqrt.rs @@ -24,12 +24,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -40,15 +42,15 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fsqrt_perfect_square_4() { - let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 - // FSQRT ; D9 FA - // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 - // HLT ; F4 + let mut emu = emu64(); // FLD qword [0x2000] ; DD 04 25 00 20 00 00 + // FSQRT ; D9 FA + // FSTP qword [0x3000] ; DD 1C 25 00 30 00 00 + // HLT ; F4 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -62,11 +64,12 @@ fn test_fsqrt_perfect_square_4() { #[test] fn test_fsqrt_perfect_square_9() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -80,11 +83,12 @@ fn test_fsqrt_perfect_square_9() { #[test] fn test_fsqrt_perfect_square_16() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -98,11 +102,12 @@ fn test_fsqrt_perfect_square_16() { #[test] fn test_fsqrt_perfect_square_25() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -116,11 +121,12 @@ fn test_fsqrt_perfect_square_25() { #[test] fn test_fsqrt_perfect_square_100() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -134,11 +140,12 @@ fn test_fsqrt_perfect_square_100() { #[test] fn test_fsqrt_perfect_square_144() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -156,11 +163,12 @@ fn test_fsqrt_perfect_square_144() { #[test] fn test_fsqrt_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -170,16 +178,21 @@ fn test_fsqrt_two() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 2.0_f64.sqrt(); - assert!((result - expected).abs() < 1e-15, "FSQRT of 2.0 should be approximately {}", expected); + assert!( + (result - expected).abs() < 1e-15, + "FSQRT of 2.0 should be approximately {}", + expected + ); } #[test] fn test_fsqrt_three() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -189,16 +202,21 @@ fn test_fsqrt_three() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 3.0_f64.sqrt(); - assert!((result - expected).abs() < 1e-15, "FSQRT of 3.0 should be approximately {}", expected); + assert!( + (result - expected).abs() < 1e-15, + "FSQRT of 3.0 should be approximately {}", + expected + ); } #[test] fn test_fsqrt_five() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -208,16 +226,21 @@ fn test_fsqrt_five() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 5.0_f64.sqrt(); - assert!((result - expected).abs() < 1e-15, "FSQRT of 5.0 should be approximately {}", expected); + assert!( + (result - expected).abs() < 1e-15, + "FSQRT of 5.0 should be approximately {}", + expected + ); } #[test] fn test_fsqrt_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -227,16 +250,21 @@ fn test_fsqrt_pi() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::PI.sqrt(); - assert!((result - expected).abs() < 1e-15, "FSQRT of PI should be approximately {}", expected); + assert!( + (result - expected).abs() < 1e-15, + "FSQRT of PI should be approximately {}", + expected + ); } #[test] fn test_fsqrt_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -246,7 +274,11 @@ fn test_fsqrt_e() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::E.sqrt(); - assert!((result - expected).abs() < 1e-15, "FSQRT of E should be approximately {}", expected); + assert!( + (result - expected).abs() < 1e-15, + "FSQRT of E should be approximately {}", + expected + ); } // ============================================================================ @@ -255,11 +287,12 @@ fn test_fsqrt_e() { #[test] fn test_fsqrt_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -274,11 +307,12 @@ fn test_fsqrt_positive_zero() { #[test] fn test_fsqrt_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -297,11 +331,12 @@ fn test_fsqrt_negative_zero() { #[test] fn test_fsqrt_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -310,17 +345,21 @@ fn test_fsqrt_positive_infinity() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert_eq!(result, f64::INFINITY, "FSQRT of +infinity should be +infinity"); + assert_eq!( + result, + f64::INFINITY, + "FSQRT of +infinity should be +infinity" + ); } #[test] fn test_fsqrt_negative_infinity() { - let mut emu = emu64(); // FSQRT of negative infinity should produce NaN (invalid operation) + let mut emu = emu64(); // FSQRT of negative infinity should produce NaN (invalid operation) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -338,11 +377,12 @@ fn test_fsqrt_negative_infinity() { #[test] fn test_fsqrt_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -360,12 +400,12 @@ fn test_fsqrt_nan() { #[test] fn test_fsqrt_negative_one() { - let mut emu = emu64(); // FSQRT of negative number (except -0) should produce NaN + let mut emu = emu64(); // FSQRT of negative number (except -0) should produce NaN let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -374,16 +414,20 @@ fn test_fsqrt_negative_one() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_nan(), "FSQRT of -1.0 should produce NaN (invalid operation)"); + assert!( + result.is_nan(), + "FSQRT of -1.0 should produce NaN (invalid operation)" + ); } #[test] fn test_fsqrt_negative_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -397,11 +441,12 @@ fn test_fsqrt_negative_small() { #[test] fn test_fsqrt_negative_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -419,11 +464,12 @@ fn test_fsqrt_negative_large() { #[test] fn test_fsqrt_one_quarter() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -437,11 +483,12 @@ fn test_fsqrt_one_quarter() { #[test] fn test_fsqrt_one_sixteenth() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -455,11 +502,12 @@ fn test_fsqrt_one_sixteenth() { #[test] fn test_fsqrt_decimal_fraction() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -477,11 +525,12 @@ fn test_fsqrt_decimal_fraction() { #[test] fn test_fsqrt_large_perfect_square() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -495,11 +544,12 @@ fn test_fsqrt_large_perfect_square() { #[test] fn test_fsqrt_very_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -518,11 +568,12 @@ fn test_fsqrt_very_large() { #[test] fn test_fsqrt_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -532,16 +583,20 @@ fn test_fsqrt_very_small() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1e-50; - assert!((result - expected).abs() < 1e-60, "FSQRT of 1e-100 should be approximately 1e-50"); + assert!( + (result - expected).abs() < 1e-60, + "FSQRT of 1e-100 should be approximately 1e-50" + ); } #[test] fn test_fsqrt_min_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -560,11 +615,12 @@ fn test_fsqrt_min_positive() { #[test] fn test_fsqrt_precision_1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -578,11 +634,12 @@ fn test_fsqrt_precision_1() { #[test] fn test_fsqrt_precision_check() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_values = vec![2.0, 3.0, 5.0, 7.0, 10.0, 50.0, 123.456]; @@ -591,12 +648,17 @@ fn test_fsqrt_precision_check() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = val.sqrt(); let rel_error = ((result - expected) / expected).abs(); - assert!(rel_error < 1e-15, "FSQRT of {} has relative error {} (expected < 1e-15)", val, rel_error); + assert!( + rel_error < 1e-15, + "FSQRT of {} has relative error {} (expected < 1e-15)", + val, + rel_error + ); } } @@ -606,13 +668,13 @@ fn test_fsqrt_precision_check() { #[test] fn test_fsqrt_twice() { - let mut emu = emu64(); // FSQRT(FSQRT(16)) should be 2 + let mut emu = emu64(); // FSQRT(FSQRT(16)) should be 2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xD9, 0xFA, // FSQRT (second time) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xD9, 0xFA, // FSQRT (second time) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -626,14 +688,15 @@ fn test_fsqrt_twice() { #[test] fn test_fsqrt_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -650,13 +713,14 @@ fn test_fsqrt_sequence() { #[test] fn test_fsqrt_with_multiplication() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC9, // FMULP (multiply and pop) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC9, // FMULP (multiply and pop) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -675,11 +739,12 @@ fn test_fsqrt_with_multiplication() { #[test] fn test_fsqrt_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -694,12 +759,13 @@ fn test_fsqrt_max_value() { #[test] fn test_fsqrt_inverse_property() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xD8, 0xC8, // FMUL ST(0), ST(0) (square the result) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xD8, 0xC8, // FMUL ST(0), ST(0) (square the result) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -709,17 +775,20 @@ fn test_fsqrt_inverse_property() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - test_val).abs() < 1e-14, "FSQRT(x)^2 should equal x"); + assert!( + (result - test_val).abs() < 1e-14, + "FSQRT(x)^2 should equal x" + ); } #[test] fn test_fsqrt_power_of_two() { - let mut emu = emu64(); // FSQRT(256) = 16 + let mut emu = emu64(); // FSQRT(256) = 16 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -733,14 +802,14 @@ fn test_fsqrt_power_of_two() { #[test] fn test_fsqrt_nested() { - let mut emu = emu64(); // FSQRT(FSQRT(256)) should be 4 - let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xD9, 0xFA, // FSQRT (second) - 0xD9, 0xFA, // FSQRT (third) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); // FSQRT(FSQRT(256)) should be 4 + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xD9, 0xFA, // FSQRT (second) + 0xD9, 0xFA, // FSQRT (third) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fst_fstp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fst_fstp.rs index 6538e5cc..4f616497 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fst_fstp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fst_fstp.rs @@ -18,19 +18,22 @@ const DATA_ADDR: u64 = 0x2000; // Helper to write f64 to memory fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } // Helper to read f32 from memory fn read_f32(mem: u64, addr: u64) -> f32 { - let emu = emu64(); let mut buf = [0u8; 4]; + let emu = emu64(); + let mut buf = [0u8; 4]; emu.maps.read_bytes_buff(&mut buf, addr); f32::from_le_bytes(buf) } // Helper to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -41,9 +44,9 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fst_m32fp_positive_one() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 - // FST dword ptr [0x3000] ; Store as f32 - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 + // FST dword ptr [0x3000] ; Store as f32 + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] @@ -59,7 +62,8 @@ fn test_fst_m32fp_positive_one() { #[test] fn test_fst_m32fp_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -74,7 +78,8 @@ fn test_fst_m32fp_zero() { #[test] fn test_fst_m32fp_negative_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -89,7 +94,8 @@ fn test_fst_m32fp_negative_zero() { #[test] fn test_fst_m32fp_negative_one() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -104,7 +110,8 @@ fn test_fst_m32fp_negative_one() { #[test] fn test_fst_m32fp_infinity_positive() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -119,7 +126,8 @@ fn test_fst_m32fp_infinity_positive() { #[test] fn test_fst_m32fp_infinity_negative() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -134,7 +142,8 @@ fn test_fst_m32fp_infinity_negative() { #[test] fn test_fst_m32fp_nan() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -149,10 +158,10 @@ fn test_fst_m32fp_nan() { #[test] fn test_fst_m32fp_no_pop() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 - // FST dword ptr [0x3000] ; Store (no pop) - // FST dword ptr [0x3004] ; Store again (should still be 1.0) - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 + // FST dword ptr [0x3000] ; Store (no pop) + // FST dword ptr [0x3004] ; Store again (should still be 1.0) + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] @@ -173,9 +182,9 @@ fn test_fst_m32fp_no_pop() { #[test] fn test_fst_m64fp_positive_one() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 - // FST qword ptr [0x3000] ; Store as f64 - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 + // FST qword ptr [0x3000] ; Store as f64 + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST qword ptr [0x3000] @@ -191,7 +200,8 @@ fn test_fst_m64fp_positive_one() { #[test] fn test_fst_m64fp_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST qword ptr [0x3000] 0xf4, @@ -206,7 +216,8 @@ fn test_fst_m64fp_zero() { #[test] fn test_fst_m64fp_negative_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST qword ptr [0x3000] 0xf4, @@ -221,7 +232,8 @@ fn test_fst_m64fp_negative_zero() { #[test] fn test_fst_m64fp_pi() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST qword ptr [0x3000] 0xf4, @@ -236,7 +248,8 @@ fn test_fst_m64fp_pi() { #[test] fn test_fst_m64fp_no_pop() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST qword ptr [0x3000] 0xDD, 0x14, 0x25, 0x08, 0x30, 0x00, 0x00, // FST qword ptr [0x3008] @@ -256,7 +269,8 @@ fn test_fst_m64fp_no_pop() { #[test] fn test_fstp_m32fp_positive_one() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP dword ptr [0x3000] 0xf4, @@ -271,7 +285,8 @@ fn test_fstp_m32fp_positive_one() { #[test] fn test_fstp_m32fp_large_value() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP dword ptr [0x3000] 0xf4, @@ -286,11 +301,11 @@ fn test_fstp_m32fp_large_value() { #[test] fn test_fstp_m32fp_with_pop() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 - // FLD qword ptr [0x2008] ; Load 2.0 (now ST(0)) - // FSTP dword ptr [0x3000] ; Store 2.0 and pop - // FSTP dword ptr [0x3004] ; Store 1.0 and pop - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 + // FLD qword ptr [0x2008] ; Load 2.0 (now ST(0)) + // FSTP dword ptr [0x3000] ; Store 2.0 and pop + // FSTP dword ptr [0x3004] ; Store 1.0 and pop + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] @@ -313,7 +328,8 @@ fn test_fstp_m32fp_with_pop() { #[test] fn test_fstp_m64fp_positive_one() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -328,7 +344,8 @@ fn test_fstp_m64fp_positive_one() { #[test] fn test_fstp_m64fp_zero() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -343,7 +360,8 @@ fn test_fstp_m64fp_zero() { #[test] fn test_fstp_m64fp_negative_value() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, @@ -358,7 +376,8 @@ fn test_fstp_m64fp_negative_value() { #[test] fn test_fstp_m64fp_with_pop() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword ptr [0x2010] @@ -384,12 +403,12 @@ fn test_fstp_m64fp_with_pop() { #[test] fn test_fst_st1() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) - // FLD qword ptr [0x2008] ; Load 2.0 into ST(0), 1.0 -> ST(1) - // FST ST(1) ; Copy ST(0) to ST(1) (both should be 2.0) - // FSTP qword ptr [0x3000] ; Pop ST(0) (2.0) - // FSTP qword ptr [0x3008] ; Pop ST(0) (was ST(1), now 2.0) - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) + // FLD qword ptr [0x2008] ; Load 2.0 into ST(0), 1.0 -> ST(1) + // FST ST(1) ; Copy ST(0) to ST(1) (both should be 2.0) + // FSTP qword ptr [0x3000] ; Pop ST(0) (2.0) + // FSTP qword ptr [0x3008] ; Pop ST(0) (was ST(1), now 2.0) + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] @@ -409,7 +428,8 @@ fn test_fst_st1() { #[test] fn test_fst_st2() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] ; 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] ; 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword ptr [0x2010] ; 3.0 @@ -436,11 +456,11 @@ fn test_fst_st2() { #[test] fn test_fstp_st1() { - let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) - // FLD qword ptr [0x2008] ; Load 2.0 into ST(0), 1.0 -> ST(1) - // FSTP ST(1) ; Copy ST(0) to ST(1) and pop - // FSTP qword ptr [0x3000] ; Pop remaining value - // HLT + let mut emu = emu64(); // FLD qword ptr [0x2000] ; Load 1.0 into ST(0) + // FLD qword ptr [0x2008] ; Load 2.0 into ST(0), 1.0 -> ST(1) + // FSTP ST(1) ; Copy ST(0) to ST(1) and pop + // FSTP qword ptr [0x3000] ; Pop remaining value + // HLT let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] @@ -458,7 +478,8 @@ fn test_fstp_st1() { #[test] fn test_fstp_st2() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] ; 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] ; 2.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword ptr [0x2010] ; 3.0 @@ -483,7 +504,8 @@ fn test_fstp_st2() { #[test] fn test_fst_m32fp_precision_loss() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xf4, @@ -499,7 +521,8 @@ fn test_fst_m32fp_precision_loss() { #[test] fn test_fstp_m32fp_very_small() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP dword ptr [0x3000] 0xf4, @@ -514,7 +537,8 @@ fn test_fstp_m32fp_very_small() { #[test] fn test_fstp_m32fp_very_large() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP dword ptr [0x3000] 0xf4, @@ -533,10 +557,12 @@ fn test_fstp_m32fp_very_large() { #[test] fn test_mixed_fst_fstp() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] ; 1.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] ; 2.0 - 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] ; Store 2.0, no pop + 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, + 0x00, // FST dword ptr [0x3000] ; Store 2.0, no pop 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3008] ; Store 2.0, pop 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3010] ; Store 1.0, pop 0xf4, @@ -553,7 +579,8 @@ fn test_mixed_fst_fstp() { #[test] fn test_fst_multiple_formats() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xD9, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST dword ptr [0x3000] 0xDD, 0x14, 0x25, 0x08, 0x30, 0x00, 0x00, // FST qword ptr [0x3008] @@ -575,7 +602,8 @@ fn test_fst_multiple_formats() { #[test] fn test_fstp_special_values_sequence() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword ptr [0x2008] 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword ptr [0x2010] @@ -600,7 +628,8 @@ fn test_fstp_special_values_sequence() { #[test] fn test_fst_preserves_nan() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x14, 0x25, 0x00, 0x30, 0x00, 0x00, // FST qword ptr [0x3000] 0xDD, 0x14, 0x25, 0x08, 0x30, 0x00, 0x00, // FST qword ptr [0x3008] @@ -616,7 +645,8 @@ fn test_fst_preserves_nan() { #[test] fn test_fstp_extreme_values() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword ptr [0x2000] 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword ptr [0x3000] 0xf4, diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstenv_fnstenv.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstenv_fnstenv.rs index c37a2856..5268576f 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstenv_fnstenv.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstenv_fnstenv.rs @@ -23,21 +23,25 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -48,9 +52,10 @@ const ENV_FTW: u64 = 4; #[test] fn test_fnstenv_basic() { - let mut emu = emu64(); let code = [ - 0xD9, 0x34, 0x25, 0x00, 0x20, 0x00, 0x00, // FNSTENV [0x2000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x34, 0x25, 0x00, 0x20, 0x00, 0x00, // FNSTENV [0x2000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -62,11 +67,12 @@ fn test_fnstenv_basic() { #[test] fn test_fnstenv_with_fpu_data() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -82,10 +88,11 @@ fn test_fnstenv_with_fpu_data() { #[test] fn test_fnstenv_saves_control_word() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -99,11 +106,12 @@ fn test_fnstenv_saves_control_word() { #[test] fn test_fnstenv_saves_status_word() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -117,12 +125,13 @@ fn test_fnstenv_saves_status_word() { #[test] fn test_fnstenv_multiple_times() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xD9, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTENV [0x3100] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xD9, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTENV [0x3100] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -137,13 +146,14 @@ fn test_fnstenv_multiple_times() { #[test] fn test_fnstenv_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -158,17 +168,18 @@ fn test_fnstenv_after_arithmetic() { #[test] fn test_fnstenv_with_different_control_words() { - let mut emu = emu64(); for cw in &[0x037F, 0x027F, 0x0C7F] { + let mut emu = emu64(); + for cw in &[0x037F, 0x027F, 0x0C7F] { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, *cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let saved_cw = emu.maps.read_word(0x3000 + ENV_FCW).unwrap(); assert_eq!(saved_cw, *cw); @@ -177,15 +188,16 @@ fn test_fnstenv_with_different_control_words() { #[test] fn test_fnstenv_with_stack_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -197,11 +209,12 @@ fn test_fnstenv_with_stack_operations() { #[test] fn test_fnstenv_with_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -213,14 +226,15 @@ fn test_fnstenv_with_constants() { #[test] fn test_fnstenv_after_comparison() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -235,11 +249,12 @@ fn test_fnstenv_after_comparison() { #[test] fn test_fnstenv_with_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -253,11 +268,12 @@ fn test_fnstenv_with_infinity() { #[test] fn test_fnstenv_with_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -271,10 +287,11 @@ fn test_fnstenv_with_nan() { #[test] fn test_fnstenv_empty_stack() { - let mut emu = emu64(); let code = [ - 0xDB, 0xE3, // FNINIT - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDB, 0xE3, // FNINIT + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -286,25 +303,20 @@ fn test_fnstenv_empty_stack() { #[test] fn test_fnstenv_full_stack() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0xD8, // FSTP ST(0) x8 - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0xD8, // FSTP ST(0) x8 + 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -316,13 +328,14 @@ fn test_fnstenv_full_stack() { #[test] fn test_fnstenv_after_division() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDE, 0xF9, // FDIVP - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDE, 0xF9, // FDIVP + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -336,13 +349,14 @@ fn test_fnstenv_after_division() { #[test] fn test_fnstenv_after_multiplication() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC9, // FMULP - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC9, // FMULP + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -357,13 +371,14 @@ fn test_fnstenv_after_multiplication() { #[test] fn test_fnstenv_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDE, 0xC1, // FADDP (fails - only 1 value) - 0xD9, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTENV [0x3100] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDE, 0xC1, // FADDP (fails - only 1 value) + 0xD9, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTENV [0x3100] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -379,11 +394,12 @@ fn test_fnstenv_sequence() { #[test] fn test_fnstenv_with_zero() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -395,11 +411,12 @@ fn test_fnstenv_with_zero() { #[test] fn test_fnstenv_negative_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -413,12 +430,13 @@ fn test_fnstenv_negative_value() { #[test] fn test_fnstenv_after_sqrt() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFA, // FSQRT - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFA, // FSQRT + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -432,12 +450,13 @@ fn test_fnstenv_after_sqrt() { #[test] fn test_fnstenv_after_abs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE1, // FABS - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE1, // FABS + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -451,12 +470,13 @@ fn test_fnstenv_after_abs() { #[test] fn test_fnstenv_after_change_sign() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE0, // FCHS - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE0, // FCHS + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -470,10 +490,11 @@ fn test_fnstenv_after_change_sign() { #[test] fn test_fnstenv_preserves_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -488,10 +509,11 @@ fn test_fnstenv_preserves_precision() { #[test] fn test_fnstenv_preserves_rounding() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -506,11 +528,12 @@ fn test_fnstenv_preserves_rounding() { #[test] fn test_fnstenv_denormal_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -524,11 +547,12 @@ fn test_fnstenv_denormal_value() { #[test] fn test_fnstenv_very_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -542,14 +566,15 @@ fn test_fnstenv_very_large() { #[test] fn test_fnstenv_after_exchange() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -564,13 +589,14 @@ fn test_fnstenv_after_exchange() { #[test] fn test_fnstenv_mixed_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDE, 0xC1, // FADDP - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDE, 0xC1, // FADDP + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -584,11 +610,12 @@ fn test_fnstenv_mixed_operations() { #[test] fn test_fnstenv_tag_word() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -602,12 +629,13 @@ fn test_fnstenv_tag_word() { #[test] fn test_fnstenv_consistency() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xD9, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTENV [0x3100] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xD9, 0x34, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTENV [0x3100] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -623,12 +651,13 @@ fn test_fnstenv_consistency() { #[test] fn test_fnstenv_after_rounding() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xFC, // FRNDINT - 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xFC, // FRNDINT + 0xD9, 0x34, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTENV [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstsw_fnstsw.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstsw_fnstsw.rs index 852ff5d7..4864dc3d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstsw_fnstsw.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fstsw_fnstsw.rs @@ -37,41 +37,45 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; // Status word bit definitions -const IE_BIT: u16 = 0x0001; // Invalid Operation -const DE_BIT: u16 = 0x0002; // Denormalized Operand -const ZE_BIT: u16 = 0x0004; // Zero Divide -const OE_BIT: u16 = 0x0008; // Overflow -const UE_BIT: u16 = 0x0010; // Underflow -const PE_BIT: u16 = 0x0020; // Precision -const SF_BIT: u16 = 0x0040; // Stack Fault -const ES_BIT: u16 = 0x0080; // Exception Summary Status -const TOP_MASK: u16 = 0x3800; // TOP bits 11-13 -const C2_BIT: u16 = 0x0400; // Condition Code 2 -const C1_BIT: u16 = 0x0200; // Condition Code 1 -const C3_BIT: u16 = 0x4000; // Condition Code 3 -const C0_BIT: u16 = 0x0100; // Condition Code 0 -const B_BIT: u16 = 0x8000; // Busy +const IE_BIT: u16 = 0x0001; // Invalid Operation +const DE_BIT: u16 = 0x0002; // Denormalized Operand +const ZE_BIT: u16 = 0x0004; // Zero Divide +const OE_BIT: u16 = 0x0008; // Overflow +const UE_BIT: u16 = 0x0010; // Underflow +const PE_BIT: u16 = 0x0020; // Precision +const SF_BIT: u16 = 0x0040; // Stack Fault +const ES_BIT: u16 = 0x0080; // Exception Summary Status +const TOP_MASK: u16 = 0x3800; // TOP bits 11-13 +const C2_BIT: u16 = 0x0400; // Condition Code 2 +const C1_BIT: u16 = 0x0200; // Condition Code 1 +const C3_BIT: u16 = 0x4000; // Condition Code 3 +const C0_BIT: u16 = 0x0100; // Condition Code 0 +const B_BIT: u16 = 0x8000; // Busy // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -82,10 +86,11 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fnstsw_ax_basic() { - let mut emu = emu64(); let code = [ - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -98,12 +103,13 @@ fn test_fnstsw_ax_basic() { #[test] fn test_fnstsw_ax_multiple_calls() { - let mut emu = emu64(); let code = [ - 0xDF, 0xE0, // FNSTSW AX (1st time) - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDF, 0xE0, // FNSTSW AX (2nd time) - 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDF, 0xE0, // FNSTSW AX (1st time) + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDF, 0xE0, // FNSTSW AX (2nd time) + 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -121,9 +127,10 @@ fn test_fnstsw_ax_multiple_calls() { #[test] fn test_fnstsw_m16_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -136,11 +143,12 @@ fn test_fnstsw_m16_basic() { #[test] fn test_fnstsw_m16_multiple_locations() { - let mut emu = emu64(); let code = [ - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] - 0xDD, 0x3C, 0x25, 0x04, 0x30, 0x00, 0x00, // FNSTSW [0x3004] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] + 0xDD, 0x3C, 0x25, 0x04, 0x30, 0x00, 0x00, // FNSTSW [0x3004] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -160,10 +168,11 @@ fn test_fnstsw_m16_multiple_locations() { #[test] fn test_fstsw_ax_basic() { - let mut emu = emu64(); let code = [ - 0x9B, 0xDF, 0xE0, // FSTSW AX (with FWAIT) - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x9B, 0xDF, 0xE0, // FSTSW AX (with FWAIT) + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -176,9 +185,10 @@ fn test_fstsw_ax_basic() { #[test] fn test_fstsw_m16_basic() { - let mut emu = emu64(); let code = [ - 0x9B, 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTSW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x9B, 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTSW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -195,16 +205,17 @@ fn test_fstsw_m16_basic() { #[test] fn test_fstsw_vs_fnstsw_ax() { - let mut emu = emu64(); let code1 = [ - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code1 = [ + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; let code2 = [ - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -220,14 +231,15 @@ fn test_fstsw_vs_fnstsw_ax() { #[test] fn test_fstsw_vs_fnstsw_m16() { - let mut emu = emu64(); let code1 = [ - 0x9B, 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTSW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code1 = [ + 0x9B, 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTSW [0x3000] + 0xF4, // HLT ]; let code2 = [ - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xF4, // HLT + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code1); @@ -247,14 +259,15 @@ fn test_fstsw_vs_fnstsw_m16() { #[test] fn test_status_word_top_pointer() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -271,10 +284,11 @@ fn test_status_word_top_pointer() { #[test] fn test_status_word_empty_stack() { - let mut emu = emu64(); let code = [ - 0xDF, 0xE0, // FNSTSW AX (empty stack) - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDF, 0xE0, // FNSTSW AX (empty stack) + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -288,12 +302,13 @@ fn test_status_word_empty_stack() { #[test] fn test_status_word_after_fld_fst() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x10, 0x30, 0x00, 0x00, // MOV word [0x3010], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x10, 0x30, 0x00, 0x00, // MOV word [0x3010], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -313,15 +328,16 @@ fn test_status_word_after_fld_fst() { #[test] fn test_condition_codes_c0_c1_c2_c3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -340,10 +356,11 @@ fn test_condition_codes_c0_c1_c2_c3() { #[test] fn test_status_word_exception_flags() { - let mut emu = emu64(); let code = [ - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -358,7 +375,10 @@ fn test_status_word_exception_flags() { let ue = (status & UE_BIT) != 0; let pe = (status & PE_BIT) != 0; - assert!(!ie || !de || !ze || !oe || !ue || !pe, "At least some exceptions should be clear"); + assert!( + !ie || !de || !ze || !oe || !ue || !pe, + "At least some exceptions should be clear" + ); } // ============================================================================ @@ -367,14 +387,15 @@ fn test_status_word_exception_flags() { #[test] fn test_status_word_persists_across_operations() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -395,11 +416,11 @@ fn test_status_word_persists_across_operations() { #[test] fn test_fnstsw_ax_full_register() { - let mut emu = emu64(); // FNSTSW AX should use 16-bit AX, verify full value is stored + let mut emu = emu64(); // FNSTSW AX should use 16-bit AX, verify full value is stored let code = [ - 0xDF, 0xE0, // FNSTSW AX - 0x48, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV qword [0x3000], RAX - 0xF4, // HLT + 0xDF, 0xE0, // FNSTSW AX + 0x48, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV qword [0x3000], RAX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -407,7 +428,10 @@ fn test_fnstsw_ax_full_register() { emu.run(None).unwrap(); let full_value = emu.maps.read_word(0x3000).unwrap(); - assert!(full_value < 0xFFFF, "AX register should contain valid status word"); + assert!( + full_value < 0xFFFF, + "AX register should contain valid status word" + ); } // ============================================================================ @@ -416,13 +440,14 @@ fn test_fnstsw_ax_full_register() { #[test] fn test_fnstsw_m16_various_addresses() { - let mut emu = emu64(); let addresses = vec![0x3000, 0x3100, 0x3200]; + let mut emu = emu64(); + let addresses = vec![0x3000, 0x3100, 0x3200]; let code = [ - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xDD, 0x3C, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTSW [0x3100] - 0xDD, 0x3C, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTSW [0x3200] - 0xF4, // HLT + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xDD, 0x3C, 0x25, 0x00, 0x31, 0x00, 0x00, // FNSTSW [0x3100] + 0xDD, 0x3C, 0x25, 0x00, 0x32, 0x00, 0x00, // FNSTSW [0x3200] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -443,15 +468,16 @@ fn test_fnstsw_m16_various_addresses() { #[test] fn test_fnstsw_ax_after_comparison() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD8, 0xD1, // FCOM ST(1) - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD8, 0xD1, // FCOM ST(1) + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -461,18 +487,22 @@ fn test_fnstsw_ax_after_comparison() { emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); - assert!(status < 0xFFFF, "Status word should be valid after comparison"); + assert!( + status < 0xFFFF, + "Status word should be valid after comparison" + ); } #[test] fn test_fnstsw_m16_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTSW [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -489,14 +519,15 @@ fn test_fnstsw_m16_after_arithmetic() { #[test] fn test_fnstsw_ax_sequential() { - let mut emu = emu64(); let code = [ - 0xDF, 0xE0, // FNSTSW AX (1st) - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDF, 0xE0, // FNSTSW AX (2nd) - 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDF, 0xE0, // FNSTSW AX (1st) + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDF, 0xE0, // FNSTSW AX (2nd) + 0x66, 0x89, 0x04, 0x25, 0x02, 0x30, 0x00, 0x00, // MOV word [0x3002], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -512,11 +543,12 @@ fn test_fnstsw_ax_sequential() { #[test] fn test_fnstsw_m16_vs_ax_same_value() { - let mut emu = emu64(); let code = [ - 0xDF, 0xE0, // FNSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDF, 0xE0, // FNSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x3C, 0x25, 0x02, 0x30, 0x00, 0x00, // FNSTSW [0x3002] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -525,22 +557,25 @@ fn test_fnstsw_m16_vs_ax_same_value() { let status_ax = emu.maps.read_word(0x3000).unwrap(); let status_m16 = emu.maps.read_word(0x3002).unwrap(); - assert_eq!(status_ax, status_m16, "FNSTSW AX and FNSTSW m16 should give same result"); + assert_eq!( + status_ax, status_m16, + "FNSTSW AX and FNSTSW m16 should give same result" + ); } #[test] fn test_fstsw_multiple_operations() { - let mut emu = emu64(); // FSTSW with multiple FPU operations + let mut emu = emu64(); // FSTSW with multiple FPU operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDE, 0xC1, // FADDP - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDE, 0xC1, // FADDP + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x89, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // MOV word [0x3000], AX + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsub.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsub.rs index b4e70045..e1d786af 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsub.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fsub.rs @@ -15,23 +15,28 @@ use crate::*; const DATA_ADDR: u64 = 0x2000; fn write_f32(mem: u64, addr: u64, value: f32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_f64(mem: u64, addr: u64, value: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i16(mem: u64, addr: u64, value: i16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn write_i32(mem: u64, addr: u64, value: i32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &value.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -42,11 +47,10 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fsub_m32fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -58,11 +62,10 @@ fn test_fsub_m32fp_basic() { #[test] fn test_fsub_m32fp_negative_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -74,11 +77,10 @@ fn test_fsub_m32fp_negative_result() { #[test] fn test_fsub_m32fp_zero_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.5); @@ -96,11 +98,10 @@ fn test_fsub_m32fp_zero_result() { #[test] fn test_fsub_m64fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.5); @@ -112,11 +113,10 @@ fn test_fsub_m64fp_basic() { #[test] fn test_fsub_m64fp_large_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0e15); @@ -132,12 +132,11 @@ fn test_fsub_m64fp_large_values() { #[test] fn test_fsub_st0_st1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xE1, // FSUB ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xE1, // FSUB ST(0), ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -153,13 +152,11 @@ fn test_fsub_st0_st1() { #[test] fn test_fsub_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0xE9, // FSUB ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0xE9, // FSUB ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -176,12 +173,11 @@ fn test_fsub_st1_st0() { #[test] fn test_fsubp_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xE9, // FSUBP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xE9, // FSUBP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -197,11 +193,10 @@ fn test_fsubp_st1_st0() { #[test] fn test_fisub_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.5); @@ -213,11 +208,10 @@ fn test_fisub_m16int_positive() { #[test] fn test_fisub_m16int_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 50.0); @@ -233,11 +227,10 @@ fn test_fisub_m16int_negative() { #[test] fn test_fisub_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1000.5); @@ -253,11 +246,10 @@ fn test_fisub_m32int_positive() { #[test] fn test_fsubr_m32fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -269,11 +261,10 @@ fn test_fsubr_m32fp_basic() { #[test] fn test_fsubr_m32fp_negative_result() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD8, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD8, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -289,11 +280,10 @@ fn test_fsubr_m32fp_negative_result() { #[test] fn test_fsubr_m64fp_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 25.5); @@ -309,12 +299,11 @@ fn test_fsubr_m64fp_basic() { #[test] fn test_fsubr_st0_st1() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xD8, 0xE9, // FSUBR ST(0), ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xD8, + 0xE9, // FSUBR ST(0), ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -330,13 +319,11 @@ fn test_fsubr_st0_st1() { #[test] fn test_fsubr_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0xE1, // FSUBR ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, + 0xE1, // FSUBR ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -353,12 +340,11 @@ fn test_fsubr_st1_st0() { #[test] fn test_fsubrp_st1_st0() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDE, 0xE1, // FSUBRP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDE, + 0xE1, // FSUBRP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 3.0); @@ -374,11 +360,10 @@ fn test_fsubrp_st1_st0() { #[test] fn test_fisubr_m16int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDE, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 25.5); @@ -394,11 +379,10 @@ fn test_fisubr_m16int_positive() { #[test] fn test_fisubr_m32int_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 250.5); @@ -414,11 +398,10 @@ fn test_fisubr_m32int_positive() { #[test] fn test_fsub_infinity_handling() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::INFINITY); @@ -431,11 +414,10 @@ fn test_fsub_infinity_handling() { #[test] fn test_fsub_from_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -448,11 +430,10 @@ fn test_fsub_from_infinity() { #[test] fn test_fsub_nan_propagation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, f64::NAN); @@ -464,11 +445,10 @@ fn test_fsub_nan_propagation() { #[test] fn test_fsub_zero_handling() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -480,11 +460,10 @@ fn test_fsub_zero_handling() { #[test] fn test_fsub_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -0.0); @@ -497,17 +476,16 @@ fn test_fsub_negative_zero() { #[test] fn test_fsubr_vs_fsub() { - let mut emu = emu64(); let code1 = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, // FSUB - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code1 = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, + 0x00, // FSUB + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; let code2 = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDC, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FSUBR - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDC, 0x2C, 0x25, 0x00, 0x20, 0x00, + 0x00, // FSUBR + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code1); @@ -527,13 +505,13 @@ fn test_fsubr_vs_fsub() { #[test] fn test_fsub_chain() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 100.0 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, // FSUB 10.0 0xDC, 0x24, 0x25, 0x10, 0x20, 0x00, 0x00, // FSUB 20.0 0xDC, 0x24, 0x25, 0x18, 0x20, 0x00, 0x00, // FSUB 30.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.0); @@ -547,11 +525,10 @@ fn test_fsub_chain() { #[test] fn test_fisub_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 100.75); @@ -563,11 +540,10 @@ fn test_fisub_precision() { #[test] fn test_fisubr_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDA, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 25.25); @@ -579,11 +555,10 @@ fn test_fisubr_precision() { #[test] fn test_fsub_small_from_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 1.0e100); @@ -595,14 +570,14 @@ fn test_fsub_small_from_large() { #[test] fn test_fsubp_stack_behavior() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 10.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 20.0 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD 30.0 0xDE, 0xE9, // FSUBP ST(1), ST(0) ; ST(1) = 20.0 - 30.0, pop 0xDE, 0xE9, // FSUBP ST(1), ST(0) ; ST(1) = 10.0 - (-10.0), pop - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 10.0); @@ -615,12 +590,12 @@ fn test_fsubp_stack_behavior() { #[test] fn test_fsubrp_stack_behavior() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD 5.0 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD 15.0 0xDE, 0xE1, // FSUBRP ST(1), ST(0) ; ST(1) = 15.0 - 5.0, pop - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 5.0); @@ -632,11 +607,10 @@ fn test_fsubrp_stack_behavior() { #[test] fn test_fsub_alternating_signs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x24, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDD, + 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, -10.5); @@ -648,12 +622,11 @@ fn test_fsub_alternating_signs() { #[test] fn test_fsubr_symmetry() { - let mut emu = emu64(); // FSUBR should give negative of FSUB when swapping operands + let mut emu = emu64(); // FSUBR should give negative of FSUB when swapping operands let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDC, 0x2C, 0x25, 0x08, 0x20, 0x00, 0x00, // FSUBR - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xf4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDC, 0x2C, 0x25, 0x08, 0x20, 0x00, + 0x00, // FSUBR + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, 0xf4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(DATA_ADDR, 7.5); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ftst.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ftst.rs index 79626f6b..169012f1 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ftst.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/ftst.rs @@ -25,12 +25,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } @@ -41,12 +43,13 @@ fn read_u16(mem: u64, addr: u64) -> u16 { #[test] fn test_ftst_positive_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -68,12 +71,13 @@ fn test_ftst_positive_small() { #[test] fn test_ftst_positive_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -93,12 +97,13 @@ fn test_ftst_positive_one() { #[test] fn test_ftst_positive_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -118,12 +123,13 @@ fn test_ftst_positive_large() { #[test] fn test_ftst_positive_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -143,12 +149,13 @@ fn test_ftst_positive_very_small() { #[test] fn test_ftst_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -172,12 +179,13 @@ fn test_ftst_positive_infinity() { #[test] fn test_ftst_negative_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -199,12 +207,13 @@ fn test_ftst_negative_small() { #[test] fn test_ftst_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -224,12 +233,13 @@ fn test_ftst_negative_one() { #[test] fn test_ftst_negative_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -249,12 +259,13 @@ fn test_ftst_negative_large() { #[test] fn test_ftst_negative_very_small() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -274,12 +285,13 @@ fn test_ftst_negative_very_small() { #[test] fn test_ftst_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -303,12 +315,13 @@ fn test_ftst_negative_infinity() { #[test] fn test_ftst_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -330,13 +343,13 @@ fn test_ftst_positive_zero() { #[test] fn test_ftst_negative_zero() { - let mut emu = emu64(); // -0.0 should be equal to +0.0 + let mut emu = emu64(); // -0.0 should be equal to +0.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -360,12 +373,13 @@ fn test_ftst_negative_zero() { #[test] fn test_ftst_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -385,12 +399,13 @@ fn test_ftst_nan() { #[test] fn test_ftst_negative_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -414,12 +429,13 @@ fn test_ftst_negative_nan() { #[test] fn test_ftst_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -439,12 +455,13 @@ fn test_ftst_pi() { #[test] fn test_ftst_negative_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -468,17 +485,18 @@ fn test_ftst_negative_e() { #[test] fn test_ftst_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x08, 0x30, 0x00, 0x00, // MOV [0x3008], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x08, 0x30, 0x00, 0x00, // MOV [0x3008], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -503,12 +521,13 @@ fn test_ftst_sequence() { #[test] fn test_ftst_positive_denormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -529,12 +548,13 @@ fn test_ftst_positive_denormal() { #[test] fn test_ftst_negative_denormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -559,12 +579,13 @@ fn test_ftst_negative_denormal() { #[test] fn test_ftst_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -580,12 +601,13 @@ fn test_ftst_max_value() { #[test] fn test_ftst_min_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -601,12 +623,13 @@ fn test_ftst_min_value() { #[test] fn test_ftst_various_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; let test_values = vec![0.1, 0.5, 1.0, 10.0, 100.0, 1e10, 1e100]; @@ -615,7 +638,7 @@ fn test_ftst_various_positive() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); let c3 = (status >> 14) & 1; @@ -630,12 +653,13 @@ fn test_ftst_various_positive() { #[test] fn test_ftst_various_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE4, // FTST - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE4, // FTST + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; let test_values = vec![-0.1, -0.5, -1.0, -10.0, -100.0, -1e10, -1e100]; @@ -644,7 +668,7 @@ fn test_ftst_various_negative() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); let c3 = (status >> 14) & 1; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucom_fucomp_fucompp.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucom_fucomp_fucompp.rs index 6ca7960a..474b0721 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucom_fucomp_fucompp.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucom_fucomp_fucompp.rs @@ -31,12 +31,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -47,13 +49,14 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fucom_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -70,13 +73,14 @@ fn test_fucom_equal() { #[test] fn test_fucom_greater_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -93,13 +97,14 @@ fn test_fucom_greater_than() { #[test] fn test_fucom_less_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -116,14 +121,14 @@ fn test_fucom_less_than() { #[test] fn test_fucom_st0_implicit() { - let mut emu = emu64(); // FUCOM without operand compares ST(0) with ST(1) + let mut emu = emu64(); // FUCOM without operand compares ST(0) with ST(1) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -140,16 +145,16 @@ fn test_fucom_st0_implicit() { #[test] fn test_fucom_st2() { - let mut emu = emu64(); // FUCOM with ST(2) + let mut emu = emu64(); // FUCOM with ST(2) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDD, 0xE2, // FUCOM ST(2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDD, 0xE2, // FUCOM ST(2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -173,13 +178,14 @@ fn test_fucom_st2() { #[test] fn test_fucom_nan_vs_number() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -196,13 +202,14 @@ fn test_fucom_nan_vs_number() { #[test] fn test_fucom_number_vs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -219,13 +226,14 @@ fn test_fucom_number_vs_nan() { #[test] fn test_fucom_nan_vs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -242,14 +250,14 @@ fn test_fucom_nan_vs_nan() { #[test] fn test_fucom_positive_negative_zero() { - let mut emu = emu64(); // +0.0 should equal -0.0 + let mut emu = emu64(); // +0.0 should equal -0.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-0.0) - 0xD9, 0xEE, // FLDZ (+0.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-0.0) + 0xD9, 0xEE, // FLDZ (+0.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -265,14 +273,14 @@ fn test_fucom_positive_negative_zero() { #[test] fn test_fucom_infinity_greater() { - let mut emu = emu64(); // +infinity > finite + let mut emu = emu64(); // +infinity > finite let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -289,14 +297,14 @@ fn test_fucom_infinity_greater() { #[test] fn test_fucom_negative_infinity_less() { - let mut emu = emu64(); // -infinity < finite + let mut emu = emu64(); // -infinity < finite let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (0.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-inf) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (0.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-inf) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -313,14 +321,14 @@ fn test_fucom_negative_infinity_less() { #[test] fn test_fucom_infinities_equal() { - let mut emu = emu64(); // +inf == +inf + let mut emu = emu64(); // +inf == +inf let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -341,12 +349,13 @@ fn test_fucom_infinities_equal() { #[test] fn test_fucomp_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -361,12 +370,13 @@ fn test_fucomp_equal() { #[test] fn test_fucomp_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -381,12 +391,13 @@ fn test_fucomp_greater() { #[test] fn test_fucomp_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -401,13 +412,13 @@ fn test_fucomp_less() { #[test] fn test_fucomp_with_nan() { - let mut emu = emu64(); // FUCOMP with NaN should not generate exception + let mut emu = emu64(); // FUCOMP with NaN should not generate exception let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -422,12 +433,13 @@ fn test_fucomp_with_nan() { #[test] fn test_fucomp_with_constant() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -440,15 +452,15 @@ fn test_fucomp_with_constant() { #[test] fn test_fucomp_st2() { - let mut emu = emu64(); // FUCOMP with ST(2) + let mut emu = emu64(); // FUCOMP with ST(2) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDD, 0xEA, // FUCOMP ST(2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDD, 0xEA, // FUCOMP ST(2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -470,13 +482,14 @@ fn test_fucomp_st2() { #[test] fn test_fucompp_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xE8, // FLD1 (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xE8, // FLD1 (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -491,13 +504,14 @@ fn test_fucompp_equal() { #[test] fn test_fucompp_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (2.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (6.0) - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xE8, // FLD1 (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (2.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (6.0) + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xE8, // FLD1 (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -512,13 +526,14 @@ fn test_fucompp_greater() { #[test] fn test_fucompp_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (8.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xEE, // FLDZ (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (8.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xEE, // FLDZ (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -533,14 +548,14 @@ fn test_fucompp_less() { #[test] fn test_fucompp_with_nan() { - let mut emu = emu64(); // FUCOMPP with NaN should not generate exception + let mut emu = emu64(); // FUCOMPP with NaN should not generate exception let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xE8, // FLD1 (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xE8, // FLD1 (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -555,13 +570,14 @@ fn test_fucompp_with_nan() { #[test] fn test_fucompp_with_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xE8, // FLD1 - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xEB, // FLDPI (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0xE8, // FLD1 + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xEB, // FLDPI (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -578,13 +594,14 @@ fn test_fucompp_with_constants() { #[test] fn test_fucom_very_close_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -596,13 +613,14 @@ fn test_fucom_very_close_numbers() { #[test] fn test_fucom_negative_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -619,13 +637,14 @@ fn test_fucom_negative_numbers() { #[test] fn test_fucom_mixed_signs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-3.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-3.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -642,13 +661,14 @@ fn test_fucom_mixed_signs() { #[test] fn test_fucom_tiny_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -665,13 +685,14 @@ fn test_fucom_tiny_numbers() { #[test] fn test_fucom_huge_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -688,13 +709,14 @@ fn test_fucom_huge_numbers() { #[test] fn test_fucom_denormal_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -712,16 +734,17 @@ fn test_fucom_denormal_numbers() { #[test] fn test_fucom_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -741,16 +764,17 @@ fn test_fucom_sequence() { #[test] fn test_mixed_fucom_operations() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 (1.0) - 0xD9, 0xE8, // FLD1 (1.0) - 0xDD, 0xE1, // FUCOM ST(1) - 0xD9, 0xE8, // FLD1 (1.0) - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xEE, // FLDZ (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 (1.0) + 0xD9, 0xE8, // FLD1 (1.0) + 0xDD, 0xE1, // FUCOM ST(1) + 0xD9, 0xE8, // FLD1 (1.0) + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xEE, // FLDZ (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -763,17 +787,18 @@ fn test_mixed_fucom_operations() { #[test] fn test_fucom_with_arithmetic() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + 1 = 2) - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (1 + 1 = 2) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + 1 = 2) + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (1 + 1 = 2) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -788,13 +813,14 @@ fn test_fucom_with_arithmetic() { #[test] fn test_fucompp_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xEB, // FLDPI (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xEB, // FLDPI (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -809,13 +835,14 @@ fn test_fucompp_negative_infinity() { #[test] fn test_fucom_epsilon() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -827,14 +854,15 @@ fn test_fucom_epsilon() { #[test] fn test_fucomp_sequential() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDD, 0xE9, // FUCOMP ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDD, 0xE9, // FUCOMP ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -847,13 +875,14 @@ fn test_fucomp_sequential() { #[test] fn test_fucom_max_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -870,17 +899,18 @@ fn test_fucom_max_values() { #[test] fn test_fucompp_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC1, // FADDP (2) - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xDE, 0xC9, // FMULP (1) - 0xDA, 0xE9, // FUCOMPP - 0xD9, 0xEE, // FLDZ (marker) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC1, // FADDP (2) + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xDE, 0xC9, // FMULP (1) + 0xDA, 0xE9, // FUCOMPP + 0xD9, 0xEE, // FLDZ (marker) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -893,13 +923,14 @@ fn test_fucompp_after_arithmetic() { #[test] fn test_fucom_inf_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -916,13 +947,14 @@ fn test_fucom_inf_nan() { #[test] fn test_fucom_constants_comparison() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0xD9, 0xEA, // FLDL2E - 0xDD, 0xE1, // FUCOM ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0xD9, 0xEA, // FLDL2E + 0xDD, 0xE1, // FUCOM ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucomi_fucomip.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucomi_fucomip.rs index 27471710..6ae4386d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucomi_fucomip.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fucomi_fucomip.rs @@ -29,26 +29,30 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // Helper function to read u64 from memory fn read_u64(mem: u64, addr: u64) -> u64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); u64::from_le_bytes(buf) } // Helper function to write u64 to memory fn write_u64(mem: u64, addr: u64, val: u64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // EFLAGS bit positions @@ -62,15 +66,16 @@ const ZF_BIT: u64 = 1 << 6; #[test] fn test_fucomi_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -91,15 +96,16 @@ fn test_fucomi_equal() { #[test] fn test_fucomi_greater_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -120,15 +126,16 @@ fn test_fucomi_greater_than() { #[test] fn test_fucomi_less_than() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (7.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (3.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -149,18 +156,18 @@ fn test_fucomi_less_than() { #[test] fn test_fucomi_st2() { - let mut emu = emu64(); // FUCOMI with ST(2) + let mut emu = emu64(); // FUCOMI with ST(2) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDB, 0xEA, // FUCOMI ST(2) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDB, 0xEA, // FUCOMI ST(2) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -180,15 +187,16 @@ fn test_fucomi_st2() { #[test] fn test_fucomi_nan_vs_number() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -209,15 +217,16 @@ fn test_fucomi_nan_vs_number() { #[test] fn test_fucomi_number_vs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -238,15 +247,16 @@ fn test_fucomi_number_vs_nan() { #[test] fn test_fucomi_nan_vs_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (NaN) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -263,16 +273,16 @@ fn test_fucomi_nan_vs_nan() { #[test] fn test_fucomi_infinity_greater() { - let mut emu = emu64(); // +infinity > finite -> ZF=0, PF=0, CF=0 + let mut emu = emu64(); // +infinity > finite -> ZF=0, PF=0, CF=0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (100.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -289,16 +299,16 @@ fn test_fucomi_infinity_greater() { #[test] fn test_fucomi_infinities_equal() { - let mut emu = emu64(); // +inf == +inf -> ZF=1, PF=0, CF=0 + let mut emu = emu64(); // +inf == +inf -> ZF=1, PF=0, CF=0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (+inf) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -319,14 +329,15 @@ fn test_fucomi_infinities_equal() { #[test] fn test_fucomip_equal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDF, 0xE9, // FUCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDF, 0xE9, // FUCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -344,14 +355,15 @@ fn test_fucomip_equal() { #[test] fn test_fucomip_greater() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) - 0xDF, 0xE9, // FUCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (3.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (8.0) + 0xDF, 0xE9, // FUCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -369,14 +381,15 @@ fn test_fucomip_greater() { #[test] fn test_fucomip_less() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDF, 0xE9, // FUCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (9.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDF, 0xE9, // FUCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -394,15 +407,15 @@ fn test_fucomip_less() { #[test] fn test_fucomip_with_nan() { - let mut emu = emu64(); // FUCOMIP with NaN should not generate exception + let mut emu = emu64(); // FUCOMIP with NaN should not generate exception let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDF, 0xE9, // FUCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDF, 0xE9, // FUCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -421,16 +434,17 @@ fn test_fucomip_with_nan() { #[test] fn test_fucomip_st2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDF, 0xEA, // FUCOMIP ST(2) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDF, 0xEA, // FUCOMIP ST(2) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -454,16 +468,17 @@ fn test_fucomip_st2() { #[test] fn test_fucomi_conditional_je() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xE9, // FUCOMI ST(1) - 0x74, 0x07, // JE +7 (skip if equal) - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xE9, // FUCOMI ST(1) + 0x74, 0x07, // JE +7 (skip if equal) + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -471,21 +486,21 @@ fn test_fucomi_conditional_je() { emu.maps.write_f64(0x2008, 5.0); emu.run(None).unwrap(); - } #[test] fn test_fucomi_conditional_jb() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (10.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (5.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x72, 0x07, // JB +7 (jump if below) - 0xD9, 0xE8, // FLD1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (10.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (5.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x72, 0x07, // JB +7 (jump if below) + 0xD9, 0xE8, // FLD1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -500,16 +515,17 @@ fn test_fucomi_conditional_jb() { #[test] fn test_fucomi_conditional_ja() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x77, 0x07, // JA +7 (jump if above) - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (10.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x77, 0x07, // JA +7 (jump if above) + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -524,15 +540,16 @@ fn test_fucomi_conditional_ja() { #[test] fn test_fucomip_conditional_jp() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) - 0xDF, 0xE9, // FUCOMIP ST(1) - 0x7A, 0x07, // JP +7 (jump if unordered) - 0xD9, 0xEE, // FLDZ - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (5.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (NaN) + 0xDF, 0xE9, // FUCOMIP ST(1) + 0x7A, 0x07, // JP +7 (jump if unordered) + 0xD9, 0xEE, // FLDZ + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -540,7 +557,6 @@ fn test_fucomip_conditional_jp() { emu.maps.write_f64(0x2008, f64::NAN); emu.run(None).unwrap(); - } // ============================================================================ @@ -549,20 +565,21 @@ fn test_fucomip_conditional_jp() { #[test] fn test_fucomi_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] (first flags) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] (second flags) - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] (first flags) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (3.0) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] (second flags) + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -580,18 +597,19 @@ fn test_fucomi_sequence() { #[test] fn test_fucomip_chain() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (2.0) - 0xDF, 0xE9, // FUCOMIP ST(1) - compare and pop - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDF, 0xE9, // FUCOMIP ST(1) - compare and pop - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (2.0) + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] (2.0) + 0xDF, 0xE9, // FUCOMIP ST(1) - compare and pop + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDF, 0xE9, // FUCOMIP ST(1) - compare and pop + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x08, 0x30, 0x00, 0x00, // POP qword [0x3008] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -603,21 +621,26 @@ fn test_fucomip_chain() { let flags1 = emu.maps.read_qword(0x3000).unwrap(); let flags2 = emu.maps.read_qword(0x3008).unwrap(); - assert_ne!(flags1 & ZF_BIT, 0, "First comparison: 2.0 == 2.0 should set ZF"); + assert_ne!( + flags1 & ZF_BIT, + 0, + "First comparison: 2.0 == 2.0 should set ZF" + ); assert_eq!(flags2 & CF_BIT, 0, "Second comparison: 2.0 > 1.0"); } #[test] fn test_fucomi_zero_comparison() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xEE, // FLDZ - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0xEE, // FLDZ + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -630,15 +653,16 @@ fn test_fucomi_zero_comparison() { #[test] fn test_fucomi_inf_vs_finite() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1000.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (1000.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (+inf) + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -654,14 +678,15 @@ fn test_fucomi_inf_vs_finite() { #[test] fn test_fucomip_negative_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) - 0xDF, 0xE9, // FUCOMIP ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] (-10.0) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] (-5.0) + 0xDF, 0xE9, // FUCOMIP ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -676,15 +701,16 @@ fn test_fucomip_negative_numbers() { #[test] fn test_fucomi_denormals() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDB, 0xE9, // FUCOMI ST(1) - 0x9C, // PUSHFQ - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] - 0xDD, 0xD8, // FSTP ST(0) - 0xDD, 0xD8, // FSTP ST(0) - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDB, 0xE9, // FUCOMI ST(1) + 0x9C, // PUSHFQ + 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // POP qword [0x3000] + 0xDD, 0xD8, // FSTP ST(0) + 0xDD, 0xD8, // FSTP ST(0) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -697,20 +723,19 @@ fn test_fucomi_denormals() { let flags = emu.maps.read_qword(0x3000).unwrap(); assert_eq!(flags & ZF_BIT, 0, "ZF should be clear"); - assert_eq!(flags & CF_BIT, 0, "CF should be clear (denormal1 > denormal2)"); + assert_eq!( + flags & CF_BIT, + 0, + "CF should be clear (denormal1 > denormal2)" + ); } #[test] fn test_fucomi_small_diff() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDB, 0xE9, - 0x9C, - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDB, + 0xE9, 0x9C, 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1.0); @@ -723,14 +748,10 @@ fn test_fucomi_small_diff() { #[test] fn test_fucomip_large_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDF, 0xE9, - 0x9C, - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDF, + 0xE9, 0x9C, 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, 1e100); @@ -742,15 +763,10 @@ fn test_fucomip_large_values() { #[test] fn test_fucomi_mixed_sign_large() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, - 0xDB, 0xE9, - 0x9C, - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, 0xDB, + 0xE9, 0x9C, 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, -1e100); @@ -763,14 +779,10 @@ fn test_fucomi_mixed_sign_large() { #[test] fn test_fucomip_zero_neg_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xEE, - 0xDF, 0xE9, - 0x9C, - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xEE, 0xDF, 0xE9, 0x9C, 0x8F, 0x04, 0x25, + 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, -0.0); @@ -781,12 +793,10 @@ fn test_fucomip_zero_neg_zero() { #[test] fn test_fucomi_st4() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, - 0xDB, 0xEC, - 0x9C, - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xD9, 0xE8, 0xDB, 0xEC, 0x9C, 0x8F, 0x04, + 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xDD, 0xD8, 0xF4, ]; emu.load_code_bytes(&code); @@ -797,14 +807,10 @@ fn test_fucomi_st4() { #[test] fn test_fucomip_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, - 0xD9, 0xE8, - 0xDF, 0xE9, - 0x9C, - 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0xD8, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, 0xD9, 0xE8, 0xDF, 0xE9, 0x9C, 0x8F, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, 0xDD, + 0xD8, 0xF4, ]; emu.load_code_bytes(&code); emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxam.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxam.rs index 90c6ea9a..00dca396 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxam.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxam.rs @@ -28,19 +28,22 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } @@ -51,13 +54,13 @@ fn read_u16(mem: u64, addr: u64) -> u16 { #[test] fn test_fxam_positive_normal() { - let mut emu = emu64(); // FXAM on positive normal number + let mut emu = emu64(); // FXAM on positive normal number let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -79,13 +82,13 @@ fn test_fxam_positive_normal() { #[test] fn test_fxam_negative_normal() { - let mut emu = emu64(); // FXAM on negative normal number + let mut emu = emu64(); // FXAM on negative normal number let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -107,12 +110,13 @@ fn test_fxam_negative_normal() { #[test] fn test_fxam_large_normal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -132,12 +136,13 @@ fn test_fxam_large_normal() { #[test] fn test_fxam_small_normal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -161,12 +166,13 @@ fn test_fxam_small_normal() { #[test] fn test_fxam_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -188,12 +194,13 @@ fn test_fxam_positive_zero() { #[test] fn test_fxam_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -219,12 +226,13 @@ fn test_fxam_negative_zero() { #[test] fn test_fxam_positive_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -246,12 +254,13 @@ fn test_fxam_positive_infinity() { #[test] fn test_fxam_negative_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -277,12 +286,13 @@ fn test_fxam_negative_infinity() { #[test] fn test_fxam_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -302,12 +312,13 @@ fn test_fxam_nan() { #[test] fn test_fxam_negative_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -333,12 +344,13 @@ fn test_fxam_negative_nan() { #[test] fn test_fxam_positive_denormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -361,12 +373,13 @@ fn test_fxam_positive_denormal() { #[test] fn test_fxam_negative_denormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -393,12 +406,13 @@ fn test_fxam_negative_denormal() { #[test] fn test_fxam_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -418,12 +432,13 @@ fn test_fxam_pi() { #[test] fn test_fxam_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -447,12 +462,13 @@ fn test_fxam_e() { #[test] fn test_fxam_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -472,12 +488,13 @@ fn test_fxam_one() { #[test] fn test_fxam_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -499,12 +516,13 @@ fn test_fxam_negative_one() { #[test] fn test_fxam_max_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -524,12 +542,13 @@ fn test_fxam_max_value() { #[test] fn test_fxam_min_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -553,12 +572,13 @@ fn test_fxam_min_positive() { #[test] fn test_fxam_sign_positive_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; let test_values = vec![1.0, 100.0, 0.5, f64::MAX, f64::INFINITY]; @@ -567,7 +587,7 @@ fn test_fxam_sign_positive_values() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); let c1 = (status >> 9) & 1; @@ -578,12 +598,13 @@ fn test_fxam_sign_positive_values() { #[test] fn test_fxam_sign_negative_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; let test_values = vec![-1.0, -100.0, -0.5, -f64::MAX, f64::NEG_INFINITY]; @@ -592,7 +613,7 @@ fn test_fxam_sign_negative_values() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); let c1 = (status >> 9) & 1; @@ -607,17 +628,18 @@ fn test_fxam_sign_negative_values() { #[test] fn test_fxam_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xDD, 0xD8, // FSTP ST(0) ; pop - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x08, 0x30, 0x00, 0x00, // MOV [0x3008], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xDD, 0xD8, // FSTP ST(0) ; pop + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x08, 0x30, 0x00, 0x00, // MOV [0x3008], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -646,12 +668,12 @@ fn test_fxam_sequence() { #[test] fn test_fxam_does_not_modify_value() { - let mut emu = emu64(); // FXAM should not modify ST(0) + let mut emu = emu64(); // FXAM should not modify ST(0) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -669,12 +691,13 @@ fn test_fxam_does_not_modify_value() { #[test] fn test_fxam_very_small_denormal() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -695,12 +718,13 @@ fn test_fxam_very_small_denormal() { #[test] fn test_fxam_fractional_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; let test_values = vec![0.5, 0.25, 0.125, 0.1, 0.01]; @@ -709,7 +733,7 @@ fn test_fxam_fractional_values() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); let c3 = (status >> 14) & 1; @@ -724,12 +748,13 @@ fn test_fxam_fractional_values() { #[test] fn test_fxam_power_of_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xE5, // FXAM - 0x9B, 0xDF, 0xE0, // FSTSW AX - 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xE5, // FXAM + 0x9B, 0xDF, 0xE0, // FSTSW AX + 0x66, 0x67, 0xA3, 0x00, 0x30, 0x00, 0x00, // MOV [0x3000], AX + 0xF4, // HLT ]; let test_values = vec![2.0, 4.0, 8.0, 16.0, 1024.0]; @@ -738,7 +763,7 @@ fn test_fxam_power_of_two() { emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, val); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let status = emu.maps.read_word(0x3000).unwrap(); let c3 = (status >> 14) & 1; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxch.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxch.rs index 5229df4b..717d2baf 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxch.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxch.rs @@ -19,12 +19,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,13 +37,15 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fxch_st1_basic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 3.14 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; ST(0) = 2.71, ST(1) = 3.14 - 0xD9, 0xC9, // FXCH ST(1) ; ST(0) = 3.14, ST(1) = 2.71 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; store ST(0) = 3.14 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; store ST(0) = 2.71 - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 3.14 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, + 0x00, // FLD qword [0x2008] ; ST(0) = 2.71, ST(1) = 3.14 + 0xD9, 0xC9, // FXCH ST(1) ; ST(0) = 3.14, ST(1) = 2.71 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; store ST(0) = 3.14 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; store ST(0) = 2.71 + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -58,14 +62,15 @@ fn test_fxch_st1_basic() { #[test] fn test_fxch_default() { - let mut emu = emu64(); // FXCH without operand exchanges ST(0) and ST(1) + let mut emu = emu64(); // FXCH without operand exchanges ST(0) and ST(1) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; ST(0) = 2.0, ST(1) = 1.0 - 0xD9, 0xC9, // FXCH ; ST(0) = 1.0, ST(1) = 2.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, + 0x00, // FLD qword [0x2008] ; ST(0) = 2.0, ST(1) = 1.0 + 0xD9, 0xC9, // FXCH ; ST(0) = 1.0, ST(1) = 2.0 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -86,15 +91,18 @@ fn test_fxch_default() { #[test] fn test_fxch_st2() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; ST(0) = 2.0, ST(1) = 1.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; ST(0) = 3.0, ST(1) = 2.0, ST(2) = 1.0 - 0xD9, 0xCA, // FXCH ST(2) ; ST(0) = 1.0, ST(1) = 2.0, ST(2) = 3.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; store 1.0 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; store 2.0 - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] ; store 3.0 - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, + 0x00, // FLD qword [0x2008] ; ST(0) = 2.0, ST(1) = 1.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, + 0x00, // FLD qword [0x2010] ; ST(0) = 3.0, ST(1) = 2.0, ST(2) = 1.0 + 0xD9, 0xCA, // FXCH ST(2) ; ST(0) = 1.0, ST(1) = 2.0, ST(2) = 3.0 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; store 1.0 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] ; store 2.0 + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] ; store 3.0 + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -109,19 +117,23 @@ fn test_fxch_st2() { let result3 = emu.maps.read_f64(0x3010).unwrap(); assert_eq!(result1, 1.0, "After FXCH ST(2), ST(0) should be 1.0"); assert_eq!(result2, 2.0, "ST(1) should remain 2.0"); - assert_eq!(result3, 3.0, "After FXCH ST(2), old ST(0) should be at ST(2)"); + assert_eq!( + result3, 3.0, + "After FXCH ST(2), old ST(0) should be at ST(2)" + ); } #[test] fn test_fxch_st3() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 10.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; ST(0) = 20.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; ST(0) = 30.0 - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; ST(0) = 40.0 - 0xD9, 0xCB, // FXCH ST(3) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; ST(0) = 10.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; ST(0) = 20.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; ST(0) = 30.0 + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; ST(0) = 40.0 + 0xD9, 0xCB, // FXCH ST(3) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -138,15 +150,16 @@ fn test_fxch_st3() { #[test] fn test_fxch_st4() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 - 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 - 0xD9, 0xCC, // FXCH ST(4) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 + 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 + 0xD9, 0xCC, // FXCH ST(4) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -164,16 +177,17 @@ fn test_fxch_st4() { #[test] fn test_fxch_st5() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 - 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 - 0xDD, 0x04, 0x25, 0x28, 0x20, 0x00, 0x00, // FLD qword [0x2028] ; 6.0 - 0xD9, 0xCD, // FXCH ST(5) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 + 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 + 0xDD, 0x04, 0x25, 0x28, 0x20, 0x00, 0x00, // FLD qword [0x2028] ; 6.0 + 0xD9, 0xCD, // FXCH ST(5) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -192,17 +206,18 @@ fn test_fxch_st5() { #[test] fn test_fxch_st6() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 - 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 - 0xDD, 0x04, 0x25, 0x28, 0x20, 0x00, 0x00, // FLD qword [0x2028] ; 6.0 - 0xDD, 0x04, 0x25, 0x30, 0x20, 0x00, 0x00, // FLD qword [0x2030] ; 7.0 - 0xD9, 0xCE, // FXCH ST(6) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 + 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 + 0xDD, 0x04, 0x25, 0x28, 0x20, 0x00, 0x00, // FLD qword [0x2028] ; 6.0 + 0xDD, 0x04, 0x25, 0x30, 0x20, 0x00, 0x00, // FLD qword [0x2030] ; 7.0 + 0xD9, 0xCE, // FXCH ST(6) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -222,18 +237,19 @@ fn test_fxch_st6() { #[test] fn test_fxch_st7() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 - 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 - 0xDD, 0x04, 0x25, 0x28, 0x20, 0x00, 0x00, // FLD qword [0x2028] ; 6.0 - 0xDD, 0x04, 0x25, 0x30, 0x20, 0x00, 0x00, // FLD qword [0x2030] ; 7.0 - 0xDD, 0x04, 0x25, 0x38, 0x20, 0x00, 0x00, // FLD qword [0x2038] ; 8.0 - 0xD9, 0xCF, // FXCH ST(7) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 + 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 + 0xDD, 0x04, 0x25, 0x28, 0x20, 0x00, 0x00, // FLD qword [0x2028] ; 6.0 + 0xDD, 0x04, 0x25, 0x30, 0x20, 0x00, 0x00, // FLD qword [0x2030] ; 7.0 + 0xDD, 0x04, 0x25, 0x38, 0x20, 0x00, 0x00, // FLD qword [0x2038] ; 8.0 + 0xD9, 0xCF, // FXCH ST(7) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -258,14 +274,15 @@ fn test_fxch_st7() { #[test] fn test_fxch_twice_cancels() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xD9, 0xC9, // FXCH ST(1) again - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xD9, 0xC9, // FXCH ST(1) again + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -282,14 +299,15 @@ fn test_fxch_twice_cancels() { #[test] fn test_fxch_chain() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xD9, 0xC9, // FXCH ST(1) ; swap ST(0) and ST(1) - 0xD9, 0xCA, // FXCH ST(2) ; swap ST(0) and ST(2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xD9, 0xC9, // FXCH ST(1) ; swap ST(0) and ST(1) + 0xD9, 0xCA, // FXCH ST(2) ; swap ST(0) and ST(2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -309,13 +327,14 @@ fn test_fxch_chain() { #[test] fn test_fxch_with_fadd() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 5.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 3.0 - 0xD9, 0xC9, // FXCH ST(1) - 0xDE, 0xC1, // FADDP ST(1), ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 5.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 3.0 + 0xD9, 0xC9, // FXCH ST(1) + 0xDE, 0xC1, // FADDP ST(1), ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -330,19 +349,20 @@ fn test_fxch_with_fadd() { #[test] fn test_fxch_sqrt_pattern() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 16.0 (to sqrt) - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; value to keep - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; value to keep - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; value to keep - 0xD9, 0xCB, // FXCH ST(3) ; bring 16.0 to top - 0xD9, 0xFA, // FSQRT - 0xD9, 0xCB, // FXCH ST(3) ; put result back - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; discard top - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] ; sqrt result - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 16.0 (to sqrt) + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; value to keep + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; value to keep + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; value to keep + 0xD9, 0xCB, // FXCH ST(3) ; bring 16.0 to top + 0xD9, 0xFA, // FSQRT + 0xD9, 0xCB, // FXCH ST(3) ; put result back + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; discard top + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xDD, 0x1C, 0x25, 0x18, 0x30, 0x00, 0x00, // FSTP qword [0x3018] ; sqrt result + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -363,13 +383,14 @@ fn test_fxch_sqrt_pattern() { #[test] fn test_fxch_with_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 0.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 5.0 - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 0.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 5.0 + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -386,12 +407,13 @@ fn test_fxch_with_zero() { #[test] fn test_fxch_with_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -406,12 +428,13 @@ fn test_fxch_with_infinity() { #[test] fn test_fxch_with_nan() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -426,13 +449,14 @@ fn test_fxch_with_nan() { #[test] fn test_fxch_negative_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -453,12 +477,12 @@ fn test_fxch_negative_values() { #[test] fn test_fxch_st0_is_nop() { - let mut emu = emu64(); // FXCH ST(0) should be a no-op (exchange ST(0) with itself) + let mut emu = emu64(); // FXCH ST(0) should be a no-op (exchange ST(0) with itself) let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xC8, // FXCH ST(0) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xC8, // FXCH ST(0) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -472,12 +496,13 @@ fn test_fxch_st0_is_nop() { #[test] fn test_fxch_preserves_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -493,12 +518,13 @@ fn test_fxch_preserves_precision() { #[test] fn test_fxch_with_very_small_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -513,12 +539,13 @@ fn test_fxch_with_very_small_values() { #[test] fn test_fxch_with_denormals() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -534,15 +561,16 @@ fn test_fxch_with_denormals() { #[test] fn test_fxch_alternating_exchanges() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xD9, 0xC9, // FXCH ST(1) - 0xD9, 0xCA, // FXCH ST(2) - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xD9, 0xC9, // FXCH ST(1) + 0xD9, 0xCA, // FXCH ST(2) + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -558,15 +586,16 @@ fn test_fxch_alternating_exchanges() { #[test] fn test_fxch_multiple_values_deep_stack() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 - 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 - 0xD9, 0xCC, // FXCH ST(4) ; bring 1.0 to top - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 1.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 2.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; 4.0 + 0xDD, 0x04, 0x25, 0x20, 0x20, 0x00, 0x00, // FLD qword [0x2020] ; 5.0 + 0xD9, 0xCC, // FXCH ST(4) ; bring 1.0 to top + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -584,13 +613,14 @@ fn test_fxch_multiple_values_deep_stack() { #[test] fn test_fxch_pi_and_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; PI - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; E - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; PI + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; E + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -607,12 +637,13 @@ fn test_fxch_pi_and_e() { #[test] fn test_fxch_max_and_min() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -627,13 +658,14 @@ fn test_fxch_max_and_min() { #[test] fn test_fxch_mixed_signs() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xD9, 0xCA, // FXCH ST(2) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xD9, 0xCA, // FXCH ST(2) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -649,12 +681,13 @@ fn test_fxch_mixed_signs() { #[test] fn test_fxch_fractional_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -669,12 +702,13 @@ fn test_fxch_fractional_values() { #[test] fn test_fxch_power_of_two_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -689,15 +723,15 @@ fn test_fxch_power_of_two_values() { #[test] fn test_fxch_after_arithmetic() { - let mut emu = emu64(); // FXCH after arithmetic operation + let mut emu = emu64(); // FXCH after arithmetic operation let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 10.0 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 5.0 - 0xDE, 0xC1, // FADDP ; ST(0) = 15.0 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 - 0xD9, 0xC9, // FXCH ST(1) ; swap 3.0 and 15.0 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; store 15.0 - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; 10.0 + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; 5.0 + 0xDE, 0xC1, // FADDP ; ST(0) = 15.0 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; 3.0 + 0xD9, 0xC9, // FXCH ST(1) ; swap 3.0 and 15.0 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] ; store 15.0 + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -713,12 +747,13 @@ fn test_fxch_after_arithmetic() { #[test] fn test_fxch_before_comparison() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -733,13 +768,14 @@ fn test_fxch_before_comparison() { #[test] fn test_fxch_zero_and_nonzero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xD9, 0xC9, // FXCH ST(1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xD9, 0xC9, // FXCH ST(1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave64_fxrstor64.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave64_fxrstor64.rs index e3ff064d..0dffee28 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave64_fxrstor64.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave64_fxrstor64.rs @@ -26,21 +26,25 @@ use crate::*; const DATA_ADDR: u64 = 0x7000; fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -51,9 +55,10 @@ const FXSAVE_FTW: u64 = 4; #[test] fn test_fxsave64_basic() { - let mut emu = emu64(); let code = [ - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FXSAVE64 [0x2000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FXSAVE64 [0x2000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -65,13 +70,14 @@ fn test_fxsave64_basic() { #[test] fn test_fxsave64_with_fpu_data() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x20, 0x00, 0x00, // FSTP qword [0x2010] - 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x20, 0x00, 0x00, // FSTP qword [0x2010] + 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -88,10 +94,11 @@ fn test_fxsave64_with_fpu_data() { #[test] fn test_fxsave64_saves_control_word() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -105,10 +112,11 @@ fn test_fxsave64_saves_control_word() { #[test] fn test_fxrstor64_basic() { - let mut emu = emu64(); let code = [ - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -122,13 +130,14 @@ fn test_fxrstor64_basic() { #[test] fn test_fxsave64_fxrstor64_roundtrip() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -137,20 +146,24 @@ fn test_fxsave64_fxrstor64_roundtrip() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x4008).unwrap(); - assert_eq!(result, 1.5, "Value should be preserved through FXSAVE64/FXRSTOR64"); + assert_eq!( + result, 1.5, + "Value should be preserved through FXSAVE64/FXRSTOR64" + ); } #[test] fn test_fxsave64_fxrstor64_multiple_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xDD, 0x1C, 0x25, 0x18, 0x40, 0x00, 0x00, // FSTP qword [0x4018] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xDD, 0x1C, 0x25, 0x18, 0x40, 0x00, 0x00, // FSTP qword [0x4018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -167,12 +180,13 @@ fn test_fxsave64_fxrstor64_multiple_values() { #[test] fn test_fxsave64_multiple_areas() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x31, 0x00, 0x00, // FXSAVE64 [0x3100] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x31, 0x00, 0x00, // FXSAVE64 [0x3100] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -187,10 +201,11 @@ fn test_fxsave64_multiple_areas() { #[test] fn test_fxrstor64_from_prepared_area() { - let mut emu = emu64(); let code = [ - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR64 [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR64 [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -200,18 +215,22 @@ fn test_fxrstor64_from_prepared_area() { emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(cw, 0x037F, "Control word should be restored from prepared area"); + assert_eq!( + cw, 0x037F, + "Control word should be restored from prepared area" + ); } #[test] fn test_fxsave64_after_arithmetic() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -226,12 +245,13 @@ fn test_fxsave64_after_arithmetic() { #[test] fn test_fxrstor64_then_arithmetic() { - let mut emu = emu64(); let code = [ - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR64 [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR64 [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -247,12 +267,13 @@ fn test_fxrstor64_then_arithmetic() { #[test] fn test_sequential_fxsave64() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE64 [0x3200] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE64 [0x3200] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -262,22 +283,26 @@ fn test_sequential_fxsave64() { let fcw1 = emu.maps.read_word(0x3000 + FXSAVE_FCW).unwrap(); let fcw2 = emu.maps.read_word(0x3200 + FXSAVE_FCW).unwrap(); - assert_eq!(fcw1, fcw2, "Multiple FXSAVE64 should produce identical results"); + assert_eq!( + fcw1, fcw2, + "Multiple FXSAVE64 should produce identical results" + ); } #[test] fn test_fxsave64_fxrstor64_complete_flow() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] - 0xDD, 0x1C, 0x25, 0x28, 0x40, 0x00, 0x00, // FSTP qword [0x4028] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] + 0xDD, 0x1C, 0x25, 0x28, 0x40, 0x00, 0x00, // FSTP qword [0x4028] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -295,18 +320,19 @@ fn test_fxsave64_fxrstor64_complete_flow() { #[test] fn test_fxsave64_fxrstor64_multiple_cycles() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE64 [0x3200] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x32, 0x00, 0x00, // FXRSTOR64 [0x3200] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE64 [0x3200] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x32, 0x00, 0x00, // FXRSTOR64 [0x3200] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -323,10 +349,11 @@ fn test_fxsave64_fxrstor64_multiple_cycles() { #[test] fn test_fxsave64_preserves_control_precision() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -341,10 +368,11 @@ fn test_fxsave64_preserves_control_precision() { #[test] fn test_fxsave64_preserves_control_rounding() { - let mut emu = emu64(); let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -359,32 +387,38 @@ fn test_fxsave64_preserves_control_rounding() { #[test] fn test_fxsave64_different_control_words() { - let mut emu = emu64(); let test_cws = vec![0x037F, 0x027F, 0x0C7F]; + let mut emu = emu64(); + let test_cws = vec![0x037F, 0x027F, 0x0C7F]; for test_cw in test_cws { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let saved_cw = emu.maps.read_word(0x3000 + FXSAVE_FCW).unwrap(); - assert_eq!(saved_cw, test_cw, "Control word 0x{:04X} should be saved", test_cw); + assert_eq!( + saved_cw, test_cw, + "Control word 0x{:04X} should be saved", + test_cw + ); } } #[test] fn test_fxsave64_with_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -398,13 +432,14 @@ fn test_fxsave64_with_infinity() { #[test] fn test_fxrstor64_with_saved_infinity() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -418,13 +453,14 @@ fn test_fxrstor64_with_saved_infinity() { #[test] fn test_fxsave64_with_constants() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEB, // FLDPI - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEB, // FLDPI + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -437,17 +473,18 @@ fn test_fxsave64_with_constants() { #[test] fn test_fxsave64_stack_depth() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0xD9, 0xE8, // FLD1 - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0xD9, 0xE8, // FLD1 + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -464,15 +501,16 @@ fn test_fxsave64_stack_depth() { #[test] fn test_fxsave64_zero_values() { - let mut emu = emu64(); let code = [ - 0xD9, 0xEE, // FLDZ - 0xD9, 0xEE, // FLDZ - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xEE, // FLDZ + 0xD9, 0xEE, // FLDZ + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -487,17 +525,18 @@ fn test_fxsave64_zero_values() { #[test] fn test_fxsave64_mixed_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xEB, // FLDPI - 0xD9, 0xE8, // FLD1 - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xEB, // FLDPI + 0xD9, 0xE8, // FLD1 + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -515,13 +554,14 @@ fn test_fxsave64_mixed_values() { #[test] fn test_fxsave64_after_division() { - let mut emu = emu64(); let code = [ - 0xD9, 0xE8, // FLD1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDE, 0xF9, // FDIVP - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xD9, 0xE8, // FLD1 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDE, 0xF9, // FDIVP + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -535,15 +575,16 @@ fn test_fxsave64_after_division() { #[test] fn test_fxrstor64_after_multiplication() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC9, // FMULP - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC9, // FMULP + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -558,15 +599,16 @@ fn test_fxrstor64_after_multiplication() { #[test] fn test_fxsave64_negative_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -583,13 +625,14 @@ fn test_fxsave64_negative_values() { #[test] fn test_fxsave64_very_small_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -603,13 +646,14 @@ fn test_fxsave64_very_small_numbers() { #[test] fn test_fxsave64_very_large_numbers() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] - 0xDB, 0xE3, // FNINIT - 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] - 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x48, 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE64 [0x3000] + 0xDB, 0xE3, // FNINIT + 0x48, 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR64 [0x3000] + 0xDD, 0x1C, 0x25, 0x00, 0x40, 0x00, 0x00, // FSTP qword [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave_fxrstor.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave_fxrstor.rs index 7597cf28..0eedb24e 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave_fxrstor.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxsave_fxrstor.rs @@ -31,58 +31,66 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write u16 to memory fn write_u16(mem: u64, addr: u64, val: u16) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u16 from memory fn read_u16(mem: u64, addr: u64) -> u16 { - let emu = emu64(); let mut buf = [0u8; 2]; + let emu = emu64(); + let mut buf = [0u8; 2]; emu.maps.read_bytes_buff(&mut buf, addr); u16::from_le_bytes(buf) } // Helper function to write u32 to memory fn write_u32(mem: u64, addr: u64, val: u32) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read u32 from memory fn read_u32(mem: u64, addr: u64) -> u32 { - let emu = emu64(); let mut buf = [0u8; 4]; + let emu = emu64(); + let mut buf = [0u8; 4]; emu.maps.read_bytes_buff(&mut buf, addr); u32::from_le_bytes(buf) } // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } // Helper function to write bytes to memory fn write_bytes(mem: u64, addr: u64, data: &[u8]) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, data); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, data); } // Helper function to read bytes from memory fn read_bytes(mem: u64, addr: u64, len: usize) -> Vec { - let emu = emu64(); let mut buf = vec![0u8; len]; + let emu = emu64(); + let mut buf = vec![0u8; len]; emu.maps.read_bytes_buff(&mut buf, addr); buf } // FXSAVE/FXRSTOR area offsets -const FXSAVE_FCW: u64 = 0; // FPU Control Word -const FXSAVE_FSW: u64 = 2; // FPU Status Word -const FXSAVE_FTW: u64 = 4; // FPU Tag Word -const FXSAVE_FOP: u64 = 6; // Last Opcode -const FXSAVE_ST0: u64 = 32; // First FPU register (16 bytes each) +const FXSAVE_FCW: u64 = 0; // FPU Control Word +const FXSAVE_FSW: u64 = 2; // FPU Status Word +const FXSAVE_FTW: u64 = 4; // FPU Tag Word +const FXSAVE_FOP: u64 = 6; // Last Opcode +const FXSAVE_ST0: u64 = 32; // First FPU register (16 bytes each) const FXSAVE_ST1: u64 = 48; const FXSAVE_ST2: u64 = 64; const FXSAVE_ST3: u64 = 80; @@ -90,7 +98,7 @@ const FXSAVE_ST4: u64 = 96; const FXSAVE_ST5: u64 = 112; const FXSAVE_ST6: u64 = 128; const FXSAVE_ST7: u64 = 144; -const FXSAVE_SIZE: u64 = 512; // Total size of FXSAVE area +const FXSAVE_SIZE: u64 = 512; // Total size of FXSAVE area // ============================================================================ // FXSAVE - Save FPU/SSE State @@ -98,9 +106,10 @@ const FXSAVE_SIZE: u64 = 512; // Total size of FXSAVE area #[test] fn test_fxsave_basic() { - let mut emu = emu64(); let code = [ - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FXSAVE [0x2000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FXSAVE [0x2000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -113,14 +122,14 @@ fn test_fxsave_basic() { #[test] fn test_fxsave_with_fpu_data() { - let mut emu = emu64(); // FXSAVE should save FPU register data + let mut emu = emu64(); // FXSAVE should save FPU register data let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x20, 0x00, 0x00, // FSTP qword [0x2010] - 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x20, 0x00, 0x00, // FSTP qword [0x2010] + 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -138,11 +147,11 @@ fn test_fxsave_with_fpu_data() { #[test] fn test_fxsave_saves_control_word() { - let mut emu = emu64(); // FXSAVE should save the control word + let mut emu = emu64(); // FXSAVE should save the control word let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -156,12 +165,12 @@ fn test_fxsave_saves_control_word() { #[test] fn test_fxsave_saves_status_word() { - let mut emu = emu64(); // FXSAVE should save the status word + let mut emu = emu64(); // FXSAVE should save the status word let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -175,13 +184,13 @@ fn test_fxsave_saves_status_word() { #[test] fn test_fxsave_multiple_areas() { - let mut emu = emu64(); // FXSAVE to different memory areas + let mut emu = emu64(); // FXSAVE to different memory areas let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x31, 0x00, 0x00, // FXSAVE [0x3100] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x31, 0x00, 0x00, // FXSAVE [0x3100] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -200,10 +209,11 @@ fn test_fxsave_multiple_areas() { #[test] fn test_fxrstor_basic() { - let mut emu = emu64(); let code = [ - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] - 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] + 0xD9, 0x3C, 0x25, 0x00, 0x40, 0x00, 0x00, // FNSTCW [0x4000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -221,14 +231,14 @@ fn test_fxrstor_basic() { #[test] fn test_fxsave_fxrstor_roundtrip() { - let mut emu = emu64(); // FXSAVE followed by FXRSTOR should preserve state + let mut emu = emu64(); // FXSAVE followed by FXRSTOR should preserve state let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDB, 0xE3, // FNINIT (clear FPU) - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDB, 0xE3, // FNINIT (clear FPU) + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -237,21 +247,24 @@ fn test_fxsave_fxrstor_roundtrip() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x4008).unwrap(); - assert_eq!(result, 1.5, "Value should be preserved through FXSAVE/FXRSTOR"); + assert_eq!( + result, 1.5, + "Value should be preserved through FXSAVE/FXRSTOR" + ); } #[test] fn test_fxsave_fxrstor_multiple_values() { - let mut emu = emu64(); // FXSAVE/FXRSTOR with multiple FPU values + let mut emu = emu64(); // FXSAVE/FXRSTOR with multiple FPU values let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDB, 0xE3, // FNINIT - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xDD, 0x1C, 0x25, 0x18, 0x40, 0x00, 0x00, // FSTP qword [0x4018] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDB, 0xE3, // FNINIT + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xDD, 0x1C, 0x25, 0x18, 0x40, 0x00, 0x00, // FSTP qword [0x4018] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -272,12 +285,12 @@ fn test_fxsave_fxrstor_multiple_values() { #[test] fn test_fxsave_area_512_bytes() { - let mut emu = emu64(); // FXSAVE uses a 512-byte area + let mut emu = emu64(); // FXSAVE uses a 512-byte area let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -300,23 +313,27 @@ fn test_fxsave_area_512_bytes() { #[test] fn test_fxsave_different_control_words() { - let mut emu = emu64(); // FXSAVE should preserve different control word values + let mut emu = emu64(); // FXSAVE should preserve different control word values let test_cws = vec![0x037F, 0x027F, 0x0C7F]; for test_cw in test_cws { let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); emu.maps.write_word(0x2000, test_cw); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let saved_cw = emu.maps.read_word(0x3000 + FXSAVE_FCW).unwrap(); - assert_eq!(saved_cw, test_cw, "Control word 0x{:04X} should be saved", test_cw); + assert_eq!( + saved_cw, test_cw, + "Control word 0x{:04X} should be saved", + test_cw + ); } } @@ -326,11 +343,11 @@ fn test_fxsave_different_control_words() { #[test] fn test_fxrstor_from_prepared_area() { - let mut emu = emu64(); // FXRSTOR from a pre-prepared FXSAVE area + let mut emu = emu64(); // FXRSTOR from a pre-prepared FXSAVE area let code = [ - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR [0x2000] - 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] - 0xF4, // HLT + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR [0x2000] + 0xD9, 0x3C, 0x25, 0x00, 0x30, 0x00, 0x00, // FNSTCW [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -340,7 +357,10 @@ fn test_fxrstor_from_prepared_area() { emu.run(None).unwrap(); let cw = emu.maps.read_word(0x3000).unwrap(); - assert_eq!(cw, 0x037F, "Control word should be restored from prepared area"); + assert_eq!( + cw, 0x037F, + "Control word should be restored from prepared area" + ); } // ============================================================================ @@ -349,12 +369,13 @@ fn test_fxrstor_from_prepared_area() { #[test] fn test_sequential_fxsave() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE [0x3200] - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE [0x3200] + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -364,7 +385,10 @@ fn test_sequential_fxsave() { let fcw1 = emu.maps.read_word(0x3000 + FXSAVE_FCW).unwrap(); let fcw2 = emu.maps.read_word(0x3200 + FXSAVE_FCW).unwrap(); - assert_eq!(fcw1, fcw2, "Multiple FXSAVE should produce identical results"); + assert_eq!( + fcw1, fcw2, + "Multiple FXSAVE should produce identical results" + ); } // ============================================================================ @@ -373,14 +397,14 @@ fn test_sequential_fxsave() { #[test] fn test_fxsave_after_arithmetic() { - let mut emu = emu64(); // FXSAVE after arithmetic operations + let mut emu = emu64(); // FXSAVE after arithmetic operations let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDD, 0x1C, 0x25, 0x10, 0x30, 0x00, 0x00, // FSTP qword [0x3010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -395,13 +419,13 @@ fn test_fxsave_after_arithmetic() { #[test] fn test_fxrstor_then_arithmetic() { - let mut emu = emu64(); // FXRSTOR followed by arithmetic + let mut emu = emu64(); // FXRSTOR followed by arithmetic let code = [ - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0xDE, 0xC1, // FADDP - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x20, 0x00, 0x00, // FXRSTOR [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDE, 0xC1, // FADDP + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -421,15 +445,15 @@ fn test_fxrstor_then_arithmetic() { #[test] fn test_fxsave_preserves_control_precision() { - let mut emu = emu64(); // FXSAVE should preserve control word precision bits + let mut emu = emu64(); // FXSAVE should preserve control word precision bits let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_word(0x2000, 0x037F); // Default (64-bit precision) + emu.maps.write_word(0x2000, 0x037F); // Default (64-bit precision) emu.run(None).unwrap(); @@ -440,15 +464,15 @@ fn test_fxsave_preserves_control_precision() { #[test] fn test_fxsave_preserves_control_rounding() { - let mut emu = emu64(); // FXSAVE should preserve control word rounding bits + let mut emu = emu64(); // FXSAVE should preserve control word rounding bits let code = [ - 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xF4, // HLT + 0xD9, 0x2C, 0x25, 0x00, 0x20, 0x00, 0x00, // FLDCW [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_word(0x2000, 0x037F); // Round to nearest + emu.maps.write_word(0x2000, 0x037F); // Round to nearest emu.run(None).unwrap(); @@ -463,23 +487,24 @@ fn test_fxsave_preserves_control_rounding() { #[test] fn test_fxsave_fxrstor_complete_flow() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Load and use FPU - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] // Save state - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] // Initialize FPU - 0xDB, 0xE3, // FNINIT + 0xDB, 0xE3, // FNINIT // Do some other work - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] - 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] + 0xDD, 0x1C, 0x25, 0x18, 0x20, 0x00, 0x00, // FSTP qword [0x2018] // Restore saved state - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] // Use restored state - 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] - 0xDD, 0x1C, 0x25, 0x28, 0x40, 0x00, 0x00, // FSTP qword [0x4028] - 0xF4, // HLT + 0xDD, 0x1C, 0x25, 0x20, 0x40, 0x00, 0x00, // FSTP qword [0x4020] + 0xDD, 0x1C, 0x25, 0x28, 0x40, 0x00, 0x00, // FSTP qword [0x4028] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -497,20 +522,21 @@ fn test_fxsave_fxrstor_complete_flow() { #[test] fn test_fxsave_fxrstor_multiple_cycles() { - let mut emu = emu64(); let code = [ + let mut emu = emu64(); + let code = [ // Cycle 1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] - 0xDB, 0xE3, // FNINIT - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] - 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x30, 0x00, 0x00, // FXSAVE [0x3000] + 0xDB, 0xE3, // FNINIT + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x30, 0x00, 0x00, // FXRSTOR [0x3000] + 0xDD, 0x1C, 0x25, 0x08, 0x40, 0x00, 0x00, // FSTP qword [0x4008] // Cycle 2 - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] - 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE [0x3200] - 0xDB, 0xE3, // FNINIT - 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x32, 0x00, 0x00, // FXRSTOR [0x3200] - 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] + 0x0F, 0xAE, 0x04, 0x25, 0x00, 0x32, 0x00, 0x00, // FXSAVE [0x3200] + 0xDB, 0xE3, // FNINIT + 0x0F, 0xAE, 0x0C, 0x25, 0x00, 0x32, 0x00, 0x00, // FXRSTOR [0x3200] + 0xDD, 0x1C, 0x25, 0x10, 0x40, 0x00, 0x00, // FSTP qword [0x4010] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxtract.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxtract.rs index 9676f494..a154b53f 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxtract.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fxtract.rs @@ -30,12 +30,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -46,13 +48,13 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fxtract_one() { - let mut emu = emu64(); // 1.0 has exponent 0 and significand 1.0 + let mut emu = emu64(); // 1.0 has exponent 0 and significand 1.0 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF4, // FXTRACT - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] (significand) - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] (exponent) - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF4, // FXTRACT + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] (significand) + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] (exponent) + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -63,18 +65,22 @@ fn test_fxtract_one() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 1.0 should be 1.0"); - assert!((exponent - 0.0).abs() < 1e-15, "Exponent of 1.0 should be 0.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 1.0 should be 1.0" + ); + assert!( + (exponent - 0.0).abs() < 1e-15, + "Exponent of 1.0 should be 0.0" + ); } #[test] fn test_fxtract_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -85,18 +91,22 @@ fn test_fxtract_two() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 2.0 should be 1.0"); - assert!((exponent - 1.0).abs() < 1e-15, "Exponent of 2.0 should be 1.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 2.0 should be 1.0" + ); + assert!( + (exponent - 1.0).abs() < 1e-15, + "Exponent of 2.0 should be 1.0" + ); } #[test] fn test_fxtract_four() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -107,18 +117,22 @@ fn test_fxtract_four() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 4.0 should be 1.0"); - assert!((exponent - 2.0).abs() < 1e-15, "Exponent of 4.0 should be 2.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 4.0 should be 1.0" + ); + assert!( + (exponent - 2.0).abs() < 1e-15, + "Exponent of 4.0 should be 2.0" + ); } #[test] fn test_fxtract_eight() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -129,18 +143,22 @@ fn test_fxtract_eight() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 8.0 should be 1.0"); - assert!((exponent - 3.0).abs() < 1e-15, "Exponent of 8.0 should be 3.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 8.0 should be 1.0" + ); + assert!( + (exponent - 3.0).abs() < 1e-15, + "Exponent of 8.0 should be 3.0" + ); } #[test] fn test_fxtract_large_power_of_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -151,8 +169,14 @@ fn test_fxtract_large_power_of_two() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 1024.0 should be 1.0"); - assert!((exponent - 10.0).abs() < 1e-15, "Exponent of 1024.0 should be 10.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 1024.0 should be 1.0" + ); + assert!( + (exponent - 10.0).abs() < 1e-15, + "Exponent of 1024.0 should be 10.0" + ); } // ============================================================================ @@ -161,12 +185,10 @@ fn test_fxtract_large_power_of_two() { #[test] fn test_fxtract_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -177,18 +199,22 @@ fn test_fxtract_half() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 0.5 should be 1.0"); - assert!((exponent - (-1.0)).abs() < 1e-15, "Exponent of 0.5 should be -1.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 0.5 should be 1.0" + ); + assert!( + (exponent - (-1.0)).abs() < 1e-15, + "Exponent of 0.5 should be -1.0" + ); } #[test] fn test_fxtract_quarter() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -199,18 +225,22 @@ fn test_fxtract_quarter() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 0.25 should be 1.0"); - assert!((exponent - (-2.0)).abs() < 1e-15, "Exponent of 0.25 should be -2.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 0.25 should be 1.0" + ); + assert!( + (exponent - (-2.0)).abs() < 1e-15, + "Exponent of 0.25 should be -2.0" + ); } #[test] fn test_fxtract_small_power_of_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -221,8 +251,14 @@ fn test_fxtract_small_power_of_two() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.0).abs() < 1e-15, "Significand of 2^-10 should be 1.0"); - assert!((exponent - (-10.0)).abs() < 1e-15, "Exponent of 2^-10 should be -10.0"); + assert!( + (significand - 1.0).abs() < 1e-15, + "Significand of 2^-10 should be 1.0" + ); + assert!( + (exponent - (-10.0)).abs() < 1e-15, + "Exponent of 2^-10 should be -10.0" + ); } // ============================================================================ @@ -231,13 +267,10 @@ fn test_fxtract_small_power_of_two() { #[test] fn test_fxtract_three() { - let mut emu = emu64(); // 3.0 = 1.5 * 2^1 + let mut emu = emu64(); // 3.0 = 1.5 * 2^1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -248,19 +281,22 @@ fn test_fxtract_three() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.5).abs() < 1e-15, "Significand of 3.0 should be 1.5"); - assert!((exponent - 1.0).abs() < 1e-15, "Exponent of 3.0 should be 1.0"); + assert!( + (significand - 1.5).abs() < 1e-15, + "Significand of 3.0 should be 1.5" + ); + assert!( + (exponent - 1.0).abs() < 1e-15, + "Exponent of 3.0 should be 1.0" + ); } #[test] fn test_fxtract_five() { - let mut emu = emu64(); // 5.0 = 1.25 * 2^2 + let mut emu = emu64(); // 5.0 = 1.25 * 2^2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -271,19 +307,22 @@ fn test_fxtract_five() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.25).abs() < 1e-15, "Significand of 5.0 should be 1.25"); - assert!((exponent - 2.0).abs() < 1e-15, "Exponent of 5.0 should be 2.0"); + assert!( + (significand - 1.25).abs() < 1e-15, + "Significand of 5.0 should be 1.25" + ); + assert!( + (exponent - 2.0).abs() < 1e-15, + "Exponent of 5.0 should be 2.0" + ); } #[test] fn test_fxtract_six() { - let mut emu = emu64(); // 6.0 = 1.5 * 2^2 + let mut emu = emu64(); // 6.0 = 1.5 * 2^2 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -294,19 +333,22 @@ fn test_fxtract_six() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.5).abs() < 1e-15, "Significand of 6.0 should be 1.5"); - assert!((exponent - 2.0).abs() < 1e-15, "Exponent of 6.0 should be 2.0"); + assert!( + (significand - 1.5).abs() < 1e-15, + "Significand of 6.0 should be 1.5" + ); + assert!( + (exponent - 2.0).abs() < 1e-15, + "Exponent of 6.0 should be 2.0" + ); } #[test] fn test_fxtract_ten() { - let mut emu = emu64(); // 10.0 = 1.25 * 2^3 + let mut emu = emu64(); // 10.0 = 1.25 * 2^3 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -317,19 +359,22 @@ fn test_fxtract_ten() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - 1.25).abs() < 1e-15, "Significand of 10.0 should be 1.25"); - assert!((exponent - 3.0).abs() < 1e-15, "Exponent of 10.0 should be 3.0"); + assert!( + (significand - 1.25).abs() < 1e-15, + "Significand of 10.0 should be 1.25" + ); + assert!( + (exponent - 3.0).abs() < 1e-15, + "Exponent of 10.0 should be 3.0" + ); } #[test] fn test_fxtract_pi() { - let mut emu = emu64(); // π ≈ 3.14159... = 1.5708... * 2^1 + let mut emu = emu64(); // π ≈ 3.14159... = 1.5708... * 2^1 let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -341,9 +386,14 @@ fn test_fxtract_pi() { let exponent = emu.maps.read_f64(0x3008).unwrap(); // π / 2 ≈ 1.5707963... - assert!((significand - std::f64::consts::PI / 2.0).abs() < 1e-15, - "Significand of π should be π/2"); - assert!((exponent - 1.0).abs() < 1e-15, "Exponent of π should be 1.0"); + assert!( + (significand - std::f64::consts::PI / 2.0).abs() < 1e-15, + "Significand of π should be π/2" + ); + assert!( + (exponent - 1.0).abs() < 1e-15, + "Exponent of π should be 1.0" + ); } // ============================================================================ @@ -352,12 +402,10 @@ fn test_fxtract_pi() { #[test] fn test_fxtract_negative_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -368,18 +416,22 @@ fn test_fxtract_negative_one() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - (-1.0)).abs() < 1e-15, "Significand of -1.0 should be -1.0"); - assert!((exponent - 0.0).abs() < 1e-15, "Exponent of -1.0 should be 0.0"); + assert!( + (significand - (-1.0)).abs() < 1e-15, + "Significand of -1.0 should be -1.0" + ); + assert!( + (exponent - 0.0).abs() < 1e-15, + "Exponent of -1.0 should be 0.0" + ); } #[test] fn test_fxtract_negative_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -390,18 +442,22 @@ fn test_fxtract_negative_two() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - (-1.0)).abs() < 1e-15, "Significand of -2.0 should be -1.0"); - assert!((exponent - 1.0).abs() < 1e-15, "Exponent of -2.0 should be 1.0"); + assert!( + (significand - (-1.0)).abs() < 1e-15, + "Significand of -2.0 should be -1.0" + ); + assert!( + (exponent - 1.0).abs() < 1e-15, + "Exponent of -2.0 should be 1.0" + ); } #[test] fn test_fxtract_negative_half() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -412,18 +468,22 @@ fn test_fxtract_negative_half() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - (-1.0)).abs() < 1e-15, "Significand of -0.5 should be -1.0"); - assert!((exponent - (-1.0)).abs() < 1e-15, "Exponent of -0.5 should be -1.0"); + assert!( + (significand - (-1.0)).abs() < 1e-15, + "Significand of -0.5 should be -1.0" + ); + assert!( + (exponent - (-1.0)).abs() < 1e-15, + "Exponent of -0.5 should be -1.0" + ); } #[test] fn test_fxtract_negative_pi() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -434,9 +494,14 @@ fn test_fxtract_negative_pi() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!((significand - (-std::f64::consts::PI / 2.0)).abs() < 1e-15, - "Significand of -π should be -π/2"); - assert!((exponent - 1.0).abs() < 1e-15, "Exponent of -π should be 1.0"); + assert!( + (significand - (-std::f64::consts::PI / 2.0)).abs() < 1e-15, + "Significand of -π should be -π/2" + ); + assert!( + (exponent - 1.0).abs() < 1e-15, + "Exponent of -π should be 1.0" + ); } // ============================================================================ @@ -445,12 +510,10 @@ fn test_fxtract_negative_pi() { #[test] fn test_fxtract_positive_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -461,20 +524,22 @@ fn test_fxtract_positive_zero() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!(significand == 0.0 && !significand.is_sign_negative(), - "Significand of +0 should be +0"); - assert!(exponent.is_infinite() && exponent.is_sign_negative(), - "Exponent of +0 should be -∞"); + assert!( + significand == 0.0 && !significand.is_sign_negative(), + "Significand of +0 should be +0" + ); + assert!( + exponent.is_infinite() && exponent.is_sign_negative(), + "Exponent of +0 should be -∞" + ); } #[test] fn test_fxtract_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -485,10 +550,14 @@ fn test_fxtract_negative_zero() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!(significand == 0.0 && significand.is_sign_negative(), - "Significand of -0 should be -0"); - assert!(exponent.is_infinite() && exponent.is_sign_negative(), - "Exponent of -0 should be -∞"); + assert!( + significand == 0.0 && significand.is_sign_negative(), + "Significand of -0 should be -0" + ); + assert!( + exponent.is_infinite() && exponent.is_sign_negative(), + "Exponent of -0 should be -∞" + ); } // ============================================================================ @@ -497,12 +566,10 @@ fn test_fxtract_negative_zero() { #[test] fn test_fxtract_large_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -513,21 +580,23 @@ fn test_fxtract_large_value() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!(significand >= 1.0 && significand < 2.0, - "Significand should be in [1.0, 2.0)"); + assert!( + significand >= 1.0 && significand < 2.0, + "Significand should be in [1.0, 2.0)" + ); let reconstructed = significand * 2.0_f64.powf(exponent); - assert!((reconstructed - 1.0e100).abs() / 1.0e100 < 1e-15, - "Reconstruction should match original value"); + assert!( + (reconstructed - 1.0e100).abs() / 1.0e100 < 1e-15, + "Reconstruction should match original value" + ); } #[test] fn test_fxtract_small_value() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -538,11 +607,15 @@ fn test_fxtract_small_value() { let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!(significand >= 1.0 && significand < 2.0, - "Significand should be in [1.0, 2.0)"); + assert!( + significand >= 1.0 && significand < 2.0, + "Significand should be in [1.0, 2.0)" + ); let reconstructed = significand * 2.0_f64.powf(exponent); - assert!((reconstructed - 1.0e-100).abs() / 1.0e-100 < 1e-15, - "Reconstruction should match original value"); + assert!( + (reconstructed - 1.0e-100).abs() / 1.0e-100 < 1e-15, + "Reconstruction should match original value" + ); } // ============================================================================ @@ -551,14 +624,14 @@ fn test_fxtract_small_value() { #[test] fn test_fxtract_reconstruction_with_fscale() { - let mut emu = emu64(); // FXTRACT; FSCALE; FSTP ST(1); + let mut emu = emu64(); // FXTRACT; FSCALE; FSTP ST(1); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] - 0xD9, 0xF4, // FXTRACT (ST(0)=sig, ST(1)=exp) - 0xD9, 0xFD, // FSCALE (ST(0) = sig * 2^exp) - 0xDD, 0xD9, // FSTP ST(1) (pop exponent) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] + 0xD9, 0xF4, // FXTRACT (ST(0)=sig, ST(1)=exp) + 0xD9, 0xFD, // FSCALE (ST(0) = sig * 2^exp) + 0xDD, 0xD9, // FSTP ST(1) (pop exponent) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -568,18 +641,18 @@ fn test_fxtract_reconstruction_with_fscale() { emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - original).abs() < 1e-14, - "FXTRACT followed by FSCALE should restore original value"); + assert!( + (result - original).abs() < 1e-14, + "FXTRACT followed by FSCALE should restore original value" + ); } #[test] fn test_fxtract_reconstruction_manually() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -592,9 +665,13 @@ fn test_fxtract_reconstruction_manually() { let exponent = emu.maps.read_f64(0x3008).unwrap(); let reconstructed = significand * 2.0_f64.powf(exponent); - assert!((reconstructed - original).abs() < 1e-15, + assert!( + (reconstructed - original).abs() < 1e-15, "Manual reconstruction should match original: {} * 2^{} = {}", - significand, exponent, reconstructed); + significand, + exponent, + reconstructed + ); } // ============================================================================ @@ -603,12 +680,10 @@ fn test_fxtract_reconstruction_manually() { #[test] fn test_fxtract_hundred() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -626,12 +701,10 @@ fn test_fxtract_hundred() { #[test] fn test_fxtract_point_one() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -643,18 +716,18 @@ fn test_fxtract_point_one() { let exponent = emu.maps.read_f64(0x3008).unwrap(); let reconstructed = significand * 2.0_f64.powf(exponent); - assert!((reconstructed - 0.1).abs() < 1e-16, - "Reconstruction of 0.1 should match"); + assert!( + (reconstructed - 0.1).abs() < 1e-16, + "Reconstruction of 0.1 should match" + ); } #[test] fn test_fxtract_e() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -668,18 +741,18 @@ fn test_fxtract_e() { // e ≈ 2.718... = 1.359... * 2^1 assert!((exponent - 1.0).abs() < 1e-15, "Exponent of e should be 1"); let reconstructed = significand * 2.0_f64.powf(exponent); - assert!((reconstructed - std::f64::consts::E).abs() < 1e-15, - "Reconstruction of e should match"); + assert!( + (reconstructed - std::f64::consts::E).abs() < 1e-15, + "Reconstruction of e should match" + ); } #[test] fn test_fxtract_sqrt_two() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, + 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); @@ -692,36 +765,43 @@ fn test_fxtract_sqrt_two() { // √2 ≈ 1.414... = 1.414... * 2^0 assert!((exponent - 0.0).abs() < 1e-15, "Exponent of √2 should be 0"); - assert!((significand - std::f64::consts::SQRT_2).abs() < 1e-15, - "Significand of √2 should be √2 itself"); + assert!( + (significand - std::f64::consts::SQRT_2).abs() < 1e-15, + "Significand of √2 should be √2 itself" + ); } #[test] fn test_fxtract_range_verification() { - let mut emu = emu64(); let test_values = [1.5, 3.7, 9.9, 15.3, 27.8, 50.5, 99.9, 127.5]; + let mut emu = emu64(); + let test_values = [1.5, 3.7, 9.9, 15.3, 27.8, 50.5, 99.9, 127.5]; for &value in &test_values { let code = [ - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, - 0xD9, 0xF4, - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, - 0xF4, + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, 0xD9, 0xF4, 0xDD, 0x1C, 0x25, 0x00, 0x30, + 0x00, 0x00, 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, 0xF4, ]; emu.load_code_bytes(&code); emu.maps.write_f64(0x2000, value); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let significand = emu.maps.read_f64(0x3000).unwrap(); let exponent = emu.maps.read_f64(0x3008).unwrap(); - assert!(significand >= 1.0 && significand < 2.0, - "Significand of {} should be in [1.0, 2.0), got {}", value, significand); + assert!( + significand >= 1.0 && significand < 2.0, + "Significand of {} should be in [1.0, 2.0), got {}", + value, + significand + ); let reconstructed = significand * 2.0_f64.powf(exponent); - assert!((reconstructed - value).abs() < 1e-14, - "Reconstruction of {} failed", value); + assert!( + (reconstructed - value).abs() < 1e-14, + "Reconstruction of {} failed", + value + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2x.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2x.rs index f6d06eb4..17809927 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2x.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2x.rs @@ -19,12 +19,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -35,18 +37,18 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fyl2x_log2_of_2() { - let mut emu = emu64(); // log2(2) = 1, so 1 * log2(2) = 1 + let mut emu = emu64(); // log2(2) = 1, so 1 * log2(2) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 2.0 - 0xD9, 0xF1, // FYL2X ; ST(1) * log2(ST(0)) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 2.0 + 0xD9, 0xF1, // FYL2X ; ST(1) * log2(ST(0)) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 2.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 2.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -56,18 +58,18 @@ fn test_fyl2x_log2_of_2() { #[test] fn test_fyl2x_log2_of_4() { - let mut emu = emu64(); // log2(4) = 2, so 1 * log2(4) = 2 + let mut emu = emu64(); // log2(4) = 2, so 1 * log2(4) = 2 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 4.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 4.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 4.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 4.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -77,18 +79,18 @@ fn test_fyl2x_log2_of_4() { #[test] fn test_fyl2x_log2_of_8() { - let mut emu = emu64(); // log2(8) = 3 + let mut emu = emu64(); // log2(8) = 3 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 8.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 8.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 8.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 8.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -98,18 +100,18 @@ fn test_fyl2x_log2_of_8() { #[test] fn test_fyl2x_log2_of_1() { - let mut emu = emu64(); // log2(1) = 0, so y * log2(1) = 0 for any y + let mut emu = emu64(); // log2(1) = 0, so y * log2(1) = 0 for any y let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 5.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 1.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 5.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 1.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // x - emu.maps.write_f64(0x2008, 5.0); // y + emu.maps.write_f64(0x2000, 1.0); // x + emu.maps.write_f64(0x2008, 5.0); // y emu.run(None).unwrap(); @@ -123,18 +125,18 @@ fn test_fyl2x_log2_of_1() { #[test] fn test_fyl2x_with_multiplier() { - let mut emu = emu64(); // 3 * log2(8) = 3 * 3 = 9 + let mut emu = emu64(); // 3 * log2(8) = 3 * 3 = 9 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 3.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 8.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 3.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 8.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 8.0); // x - emu.maps.write_f64(0x2008, 3.0); // y + emu.maps.write_f64(0x2000, 8.0); // x + emu.maps.write_f64(0x2008, 3.0); // y emu.run(None).unwrap(); @@ -144,39 +146,42 @@ fn test_fyl2x_with_multiplier() { #[test] fn test_fyl2x_negative_multiplier() { - let mut emu = emu64(); // -2 * log2(4) = -2 * 2 = -4 + let mut emu = emu64(); // -2 * log2(4) = -2 * 2 = -4 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = -2.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 4.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = -2.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 4.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 4.0); // x - emu.maps.write_f64(0x2008, -2.0); // y + emu.maps.write_f64(0x2000, 4.0); // x + emu.maps.write_f64(0x2008, -2.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - (-4.0)).abs() < 1e-10, "-2 * log2(4) should be -4.0"); + assert!( + (result - (-4.0)).abs() < 1e-10, + "-2 * log2(4) should be -4.0" + ); } #[test] fn test_fyl2x_fractional_multiplier() { - let mut emu = emu64(); // 0.5 * log2(16) = 0.5 * 4 = 2 + let mut emu = emu64(); // 0.5 * log2(16) = 0.5 * 4 = 2 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.5 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 16.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.5 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 16.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 16.0); // x - emu.maps.write_f64(0x2008, 0.5); // y + emu.maps.write_f64(0x2000, 16.0); // x + emu.maps.write_f64(0x2008, 0.5); // y emu.run(None).unwrap(); @@ -190,44 +195,50 @@ fn test_fyl2x_fractional_multiplier() { #[test] fn test_fyl2x_log2_of_half() { - let mut emu = emu64(); // log2(0.5) = -1, so 1 * log2(0.5) = -1 + let mut emu = emu64(); // log2(0.5) = -1, so 1 * log2(0.5) = -1 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.5 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.5 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.5); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 0.5); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - (-1.0)).abs() < 1e-10, "1 * log2(0.5) should be -1.0"); + assert!( + (result - (-1.0)).abs() < 1e-10, + "1 * log2(0.5) should be -1.0" + ); } #[test] fn test_fyl2x_log2_of_quarter() { - let mut emu = emu64(); // log2(0.25) = -2 + let mut emu = emu64(); // log2(0.25) = -2 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.25 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.25 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.25); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 0.25); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - (-2.0)).abs() < 1e-10, "1 * log2(0.25) should be -2.0"); + assert!( + (result - (-2.0)).abs() < 1e-10, + "1 * log2(0.25) should be -2.0" + ); } // ============================================================================ @@ -236,40 +247,45 @@ fn test_fyl2x_log2_of_quarter() { #[test] fn test_fyl2x_log10_conversion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(10) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 100.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(10) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 100.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 100.0); // x + emu.maps.write_f64(0x2000, 100.0); // x let log2_10 = 10.0f64.log2(); - emu.maps.write_f64(0x2008, 1.0 / log2_10); // y = 1/log2(10) + emu.maps.write_f64(0x2008, 1.0 / log2_10); // y = 1/log2(10) emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 100.0f64.log10(); - assert!((result - expected).abs() < 1e-10, "log10(100) should be approximately 2.0"); + assert!( + (result - expected).abs() < 1e-10, + "log10(100) should be approximately 2.0" + ); } #[test] fn test_fyl2x_natural_log_conversion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(e) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(e) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, std::f64::consts::E); // x = e + emu.maps.write_f64(0x2000, std::f64::consts::E); // x = e let log2_e = std::f64::consts::E.log2(); - emu.maps.write_f64(0x2008, 1.0 / log2_e); // y = 1/log2(e) + emu.maps.write_f64(0x2008, 1.0 / log2_e); // y = 1/log2(e) emu.run(None).unwrap(); @@ -283,39 +299,42 @@ fn test_fyl2x_natural_log_conversion() { #[test] fn test_fyl2x_large_power_of_2() { - let mut emu = emu64(); // log2(1024) = 10 + let mut emu = emu64(); // log2(1024) = 10 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 1024.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 1024.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1024.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 1024.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - 10.0).abs() < 1e-10, "1 * log2(1024) should be 10.0"); + assert!( + (result - 10.0).abs() < 1e-10, + "1 * log2(1024) should be 10.0" + ); } #[test] fn test_fyl2x_very_large_value() { - let mut emu = emu64(); // log2(2^20) = 20 + let mut emu = emu64(); // log2(2^20) = 20 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); let x = 2.0f64.powi(20); - emu.maps.write_f64(0x2000, x); // x = 2^20 + emu.maps.write_f64(0x2000, x); // x = 2^20 emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -326,24 +345,27 @@ fn test_fyl2x_very_large_value() { #[test] fn test_fyl2x_very_small_value() { - let mut emu = emu64(); // log2(2^-10) = -10 + let mut emu = emu64(); // log2(2^-10) = -10 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); let x = 2.0f64.powi(-10); - emu.maps.write_f64(0x2000, x); // x = 2^-10 + emu.maps.write_f64(0x2000, x); // x = 2^-10 emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - (-10.0)).abs() < 1e-10, "log2(2^-10) should be -10.0"); + assert!( + (result - (-10.0)).abs() < 1e-10, + "log2(2^-10) should be -10.0" + ); } // ============================================================================ @@ -352,18 +374,18 @@ fn test_fyl2x_very_small_value() { #[test] fn test_fyl2x_log2_of_3() { - let mut emu = emu64(); // log2(3) ≈ 1.585 + let mut emu = emu64(); // log2(3) ≈ 1.585 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 3.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 3.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 3.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 3.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -374,18 +396,18 @@ fn test_fyl2x_log2_of_3() { #[test] fn test_fyl2x_log2_of_10() { - let mut emu = emu64(); // log2(10) ≈ 3.322 + let mut emu = emu64(); // log2(10) ≈ 3.322 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 10.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 10.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 10.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 10.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -400,39 +422,42 @@ fn test_fyl2x_log2_of_10() { #[test] fn test_fyl2x_with_infinity_x() { - let mut emu = emu64(); // log2(+infinity) = +infinity, y * infinity = infinity (for positive y) + let mut emu = emu64(); // log2(+infinity) = +infinity, y * infinity = infinity (for positive y) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = +infinity - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = +infinity + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, f64::INFINITY); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, f64::INFINITY); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite() && !result.is_sign_negative(), "log2(+infinity) * 1 should be +infinity"); + assert!( + result.is_infinite() && !result.is_sign_negative(), + "log2(+infinity) * 1 should be +infinity" + ); } #[test] fn test_fyl2x_with_zero_y() { - let mut emu = emu64(); // 0 * log2(x) = 0 (for finite x > 0) + let mut emu = emu64(); // 0 * log2(x) = 0 (for finite x > 0) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 2.0 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 2.0 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 2.0); // x - emu.maps.write_f64(0x2008, 0.0); // y + emu.maps.write_f64(0x2000, 2.0); // x + emu.maps.write_f64(0x2008, 0.0); // y emu.run(None).unwrap(); @@ -446,23 +471,24 @@ fn test_fyl2x_with_zero_y() { #[test] fn test_fyl2x_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x1 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; y2 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; x2 - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y1 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x1 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; y2 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; x2 + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 2.0); // x1 - emu.maps.write_f64(0x2008, 1.0); // y1 - emu.maps.write_f64(0x2010, 8.0); // x2 - emu.maps.write_f64(0x2018, 2.0); // y2 + emu.maps.write_f64(0x2000, 2.0); // x1 + emu.maps.write_f64(0x2008, 1.0); // y1 + emu.maps.write_f64(0x2010, 8.0); // x2 + emu.maps.write_f64(0x2018, 2.0); // y2 emu.run(None).unwrap(); @@ -478,33 +504,38 @@ fn test_fyl2x_sequence() { #[test] fn test_fyl2x_precision() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, std::f64::consts::PI); // x = PI - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, std::f64::consts::PI); // x = PI + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = std::f64::consts::PI.log2(); - assert!((result - expected).abs() < 1e-10, "log2(PI) should be precise"); + assert!( + (result - expected).abs() < 1e-10, + "log2(PI) should be precise" + ); } #[test] fn test_fyl2x_powers_of_two_exact() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![ @@ -523,27 +554,32 @@ fn test_fyl2x_powers_of_two_exact() { emu.maps.write_f64(0x2000, x); emu.maps.write_f64(0x2008, 1.0); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!((result - expected_log).abs() < 1e-15, "log2({}) should be exactly {}", x, expected_log); + assert!( + (result - expected_log).abs() < 1e-15, + "log2({}) should be exactly {}", + x, + expected_log + ); } } #[test] fn test_fyl2x_sqrt_2() { - let mut emu = emu64(); // log2(sqrt(2)) = 0.5 + let mut emu = emu64(); // log2(sqrt(2)) = 0.5 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = sqrt(2) - 0xD9, 0xF1, // FYL2X - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = sqrt(2) + 0xD9, 0xF1, // FYL2X + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 2.0f64.sqrt()); // x = sqrt(2) - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 2.0f64.sqrt()); // x = sqrt(2) + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2xp1.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2xp1.rs index a7ca21a0..852322d2 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2xp1.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/fyl2xp1.rs @@ -20,12 +20,14 @@ const DATA_ADDR: u64 = 0x7000; // Helper function to write f64 to memory fn write_f64(mem: u64, addr: u64, val: f64) { - let mut emu = emu64(); emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); + let mut emu = emu64(); + emu.maps.write_bytes_slice(addr, &val.to_le_bytes()); } // Helper function to read f64 from memory fn read_f64(mem: u64, addr: u64) -> f64 { - let emu = emu64(); let mut buf = [0u8; 8]; + let emu = emu64(); + let mut buf = [0u8; 8]; emu.maps.read_bytes_buff(&mut buf, addr); f64::from_le_bytes(buf) } @@ -36,18 +38,18 @@ fn read_f64(mem: u64, addr: u64) -> f64 { #[test] fn test_fyl2xp1_zero() { - let mut emu = emu64(); // log2(1 + 0) = log2(1) = 0, so y * log2(1+0) = 0 + let mut emu = emu64(); // log2(1 + 0) = log2(1) = 0, so y * log2(1+0) = 0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 5.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.0 - 0xD9, 0xF9, // FYL2XP1 ; ST(1) * log2(ST(0) + 1) - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 5.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.0 + 0xD9, 0xF9, // FYL2XP1 ; ST(1) * log2(ST(0) + 1) + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.0); // x - emu.maps.write_f64(0x2008, 5.0); // y + emu.maps.write_f64(0x2000, 0.0); // x + emu.maps.write_f64(0x2008, 5.0); // y emu.run(None).unwrap(); @@ -57,18 +59,18 @@ fn test_fyl2xp1_zero() { #[test] fn test_fyl2xp1_one() { - let mut emu = emu64(); // log2(1 + 1) = log2(2) = 1, so 1 * log2(1+1) = 1 + let mut emu = emu64(); // log2(1 + 1) = log2(2) = 1, so 1 * log2(1+1) = 1 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 1.0 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 1.0 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 1.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -78,18 +80,18 @@ fn test_fyl2xp1_one() { #[test] fn test_fyl2xp1_small_positive() { - let mut emu = emu64(); // log2(1 + 0.1) with y = 1 + let mut emu = emu64(); // log2(1 + 0.1) with y = 1 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.1); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 0.1); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -100,18 +102,18 @@ fn test_fyl2xp1_small_positive() { #[test] fn test_fyl2xp1_small_negative() { - let mut emu = emu64(); // log2(1 - 0.1) with y = 1 + let mut emu = emu64(); // log2(1 - 0.1) with y = 1 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = -0.1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = -0.1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -0.1); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, -0.1); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -126,68 +128,77 @@ fn test_fyl2xp1_small_negative() { #[test] fn test_fyl2xp1_with_multiplier() { - let mut emu = emu64(); // 3 * log2(1 + 0.5) = 3 * log2(1.5) + let mut emu = emu64(); // 3 * log2(1 + 0.5) = 3 * log2(1.5) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 3.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.5 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 3.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.5 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.5); // x - emu.maps.write_f64(0x2008, 3.0); // y + emu.maps.write_f64(0x2000, 0.5); // x + emu.maps.write_f64(0x2008, 3.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 3.0 * 1.5f64.log2(); - assert!((result - expected).abs() < 1e-10, "3 * log2(1.5) should match"); + assert!( + (result - expected).abs() < 1e-10, + "3 * log2(1.5) should match" + ); } #[test] fn test_fyl2xp1_negative_multiplier() { - let mut emu = emu64(); // -2 * log2(1 + 0.25) + let mut emu = emu64(); // -2 * log2(1 + 0.25) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = -2.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.25 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = -2.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.25 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.25); // x - emu.maps.write_f64(0x2008, -2.0); // y + emu.maps.write_f64(0x2000, 0.25); // x + emu.maps.write_f64(0x2008, -2.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = -2.0 * 1.25f64.log2(); - assert!((result - expected).abs() < 1e-10, "-2 * log2(1.25) should match"); + assert!( + (result - expected).abs() < 1e-10, + "-2 * log2(1.25) should match" + ); } #[test] fn test_fyl2xp1_fractional_multiplier() { - let mut emu = emu64(); // 0.5 * log2(1 + 0.2) + let mut emu = emu64(); // 0.5 * log2(1 + 0.2) let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.5 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.2 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.5 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.2 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.2); // x - emu.maps.write_f64(0x2008, 0.5); // y + emu.maps.write_f64(0x2000, 0.2); // x + emu.maps.write_f64(0x2008, 0.5); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 0.5 * 1.2f64.log2(); - assert!((result - expected).abs() < 1e-10, "0.5 * log2(1.2) should match"); + assert!( + (result - expected).abs() < 1e-10, + "0.5 * log2(1.2) should match" + ); } // ============================================================================ @@ -196,12 +207,13 @@ fn test_fyl2xp1_fractional_multiplier() { #[test] fn test_fyl2xp1_near_lower_bound() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -213,17 +225,21 @@ fn test_fyl2xp1_near_lower_bound() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (1.0 + x).log2(); - assert!((result - expected).abs() < 1e-10, "Near lower bound should work"); + assert!( + (result - expected).abs() < 1e-10, + "Near lower bound should work" + ); } #[test] fn test_fyl2xp1_near_upper_bound() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); @@ -235,28 +251,35 @@ fn test_fyl2xp1_near_upper_bound() { let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (1.0 + x).log2(); - assert!((result - expected).abs() < 1e-10, "Near upper bound should work"); + assert!( + (result - expected).abs() < 1e-10, + "Near upper bound should work" + ); } #[test] fn test_fyl2xp1_very_small_x() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.001 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.001 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.001); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 0.001); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1.001f64.log2(); - assert!((result - expected).abs() < 1e-12, "Very small x should be accurate"); + assert!( + (result - expected).abs() < 1e-12, + "Very small x should be accurate" + ); } // ============================================================================ @@ -265,38 +288,42 @@ fn test_fyl2xp1_very_small_x() { #[test] fn test_fyl2xp1_compound_interest_case() { - let mut emu = emu64(); // (1 + r)^n using y * log2(1+x) where x is interest rate + let mut emu = emu64(); // (1 + r)^n using y * log2(1+x) where x is interest rate let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.05 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.05 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.05); // 5% interest - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, 0.05); // 5% interest + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1.05f64.log2(); - assert!((result - expected).abs() < 1e-12, "Compound interest calculation"); + assert!( + (result - expected).abs() < 1e-12, + "Compound interest calculation" + ); } #[test] fn test_fyl2xp1_annuity_calculation() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.025); // 2.5% rate + emu.maps.write_f64(0x2000, 0.025); // 2.5% rate emu.maps.write_f64(0x2008, 1.0); emu.run(None).unwrap(); @@ -312,46 +339,54 @@ fn test_fyl2xp1_annuity_calculation() { #[test] fn test_fyl2xp1_natural_log_conversion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(e) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(e) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.1); // x + emu.maps.write_f64(0x2000, 0.1); // x let log2_e = std::f64::consts::E.log2(); - emu.maps.write_f64(0x2008, 1.0 / log2_e); // y = 1/log2(e) + emu.maps.write_f64(0x2008, 1.0 / log2_e); // y = 1/log2(e) emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1.1f64.ln(); - assert!((result - expected).abs() < 1e-10, "ln(1.1) conversion should match"); + assert!( + (result - expected).abs() < 1e-10, + "ln(1.1) conversion should match" + ); } #[test] fn test_fyl2xp1_log10_conversion() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(10) - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1/log2(10) + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.1); // x + emu.maps.write_f64(0x2000, 0.1); // x let log2_10 = 10.0f64.log2(); - emu.maps.write_f64(0x2008, 1.0 / log2_10); // y = 1/log2(10) + emu.maps.write_f64(0x2008, 1.0 / log2_10); // y = 1/log2(10) emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = 1.1f64.log10(); - assert!((result - expected).abs() < 1e-10, "log10(1.1) conversion should match"); + assert!( + (result - expected).abs() < 1e-10, + "log10(1.1) conversion should match" + ); } // ============================================================================ @@ -360,18 +395,18 @@ fn test_fyl2xp1_log10_conversion() { #[test] fn test_fyl2xp1_with_zero_y() { - let mut emu = emu64(); // 0 * log2(1+x) = 0 + let mut emu = emu64(); // 0 * log2(1+x) = 0 let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 0.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.1); // x - emu.maps.write_f64(0x2008, 0.0); // y + emu.maps.write_f64(0x2000, 0.1); // x + emu.maps.write_f64(0x2008, 0.0); // y emu.run(None).unwrap(); @@ -381,38 +416,42 @@ fn test_fyl2xp1_with_zero_y() { #[test] fn test_fyl2xp1_with_infinity_y() { - let mut emu = emu64(); // infinity * log2(1+x) for x > 0 should be infinity + let mut emu = emu64(); // infinity * log2(1+x) for x > 0 should be infinity let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = infinity - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = infinity + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.1); // x - emu.maps.write_f64(0x2008, f64::INFINITY); // y + emu.maps.write_f64(0x2000, 0.1); // x + emu.maps.write_f64(0x2008, f64::INFINITY); // y emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); - assert!(result.is_infinite() && !result.is_sign_negative(), "infinity * log2(1.1) should be infinity"); + assert!( + result.is_infinite() && !result.is_sign_negative(), + "infinity * log2(1.1) should be infinity" + ); } #[test] fn test_fyl2xp1_negative_zero() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = -0.0 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = -0.0 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, -0.0); // x - emu.maps.write_f64(0x2008, 1.0); // y + emu.maps.write_f64(0x2000, -0.0); // x + emu.maps.write_f64(0x2008, 1.0); // y emu.run(None).unwrap(); @@ -426,23 +465,24 @@ fn test_fyl2xp1_negative_zero() { #[test] fn test_fyl2xp1_sequence() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y1 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x1 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; y2 - 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; x2 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y1 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x1 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xDD, 0x04, 0x25, 0x18, 0x20, 0x00, 0x00, // FLD qword [0x2018] ; y2 + 0xDD, 0x04, 0x25, 0x10, 0x20, 0x00, 0x00, // FLD qword [0x2010] ; x2 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x08, 0x30, 0x00, 0x00, // FSTP qword [0x3008] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 0.1); // x1 - emu.maps.write_f64(0x2008, 1.0); // y1 - emu.maps.write_f64(0x2010, 0.25); // x2 - emu.maps.write_f64(0x2018, 2.0); // y2 + emu.maps.write_f64(0x2000, 0.1); // x1 + emu.maps.write_f64(0x2008, 1.0); // y1 + emu.maps.write_f64(0x2010, 0.25); // x2 + emu.maps.write_f64(0x2018, 2.0); // y2 emu.run(None).unwrap(); @@ -460,34 +500,38 @@ fn test_fyl2xp1_sequence() { #[test] fn test_fyl2xp1_precision_small_values() { - let mut emu = emu64(); // FYL2XP1 should give better precision than FYL2X for small x + let mut emu = emu64(); // FYL2XP1 should give better precision than FYL2X for small x let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - emu.maps.write_f64(0x2000, 1e-10); // Very small x + emu.maps.write_f64(0x2000, 1e-10); // Very small x emu.maps.write_f64(0x2008, 1.0); emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (1.0_f64 + 1e-10).log2(); - assert!((result - expected).abs() < 1e-15, "High precision for small x"); + assert!( + (result - expected).abs() < 1e-15, + "High precision for small x" + ); } #[test] fn test_fyl2xp1_various_small_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![0.01, 0.05, 0.1, 0.15, 0.2, 0.25]; @@ -497,7 +541,7 @@ fn test_fyl2xp1_various_small_values() { emu.maps.write_f64(0x2000, x); emu.maps.write_f64(0x2008, 1.0); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (1.0 + x).log2(); @@ -507,12 +551,13 @@ fn test_fyl2xp1_various_small_values() { #[test] fn test_fyl2xp1_negative_small_values() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; let test_cases = vec![-0.01, -0.05, -0.1, -0.15, -0.2, -0.25]; @@ -522,7 +567,7 @@ fn test_fyl2xp1_negative_small_values() { emu.maps.write_f64(0x2000, x); emu.maps.write_f64(0x2008, 1.0); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let result = emu.maps.read_f64(0x3000).unwrap(); let expected = (1.0 + x).log2(); @@ -536,16 +581,17 @@ fn test_fyl2xp1_negative_small_values() { #[test] fn test_fyl2xp1_boundary_positive() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - let x = 1.0 - 2.0f64.sqrt() / 2.0; // Upper boundary + let x = 1.0 - 2.0f64.sqrt() / 2.0; // Upper boundary emu.maps.write_f64(0x2000, x); emu.maps.write_f64(0x2008, 1.0); @@ -558,16 +604,17 @@ fn test_fyl2xp1_boundary_positive() { #[test] fn test_fyl2xp1_boundary_negative() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); - let x = -(1.0 - 2.0f64.sqrt() / 2.0); // Lower boundary + let x = -(1.0 - 2.0f64.sqrt() / 2.0); // Lower boundary emu.maps.write_f64(0x2000, x); emu.maps.write_f64(0x2008, 1.0); @@ -580,12 +627,13 @@ fn test_fyl2xp1_boundary_negative() { #[test] fn test_fyl2xp1_mid_range() { - let mut emu = emu64(); let code = [ - 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 - 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.0 - 0xD9, 0xF9, // FYL2XP1 - 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] - 0xF4, // HLT + let mut emu = emu64(); + let code = [ + 0xDD, 0x04, 0x25, 0x08, 0x20, 0x00, 0x00, // FLD qword [0x2008] ; y = 1.0 + 0xDD, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // FLD qword [0x2000] ; x = 0.0 + 0xD9, 0xF9, // FYL2XP1 + 0xDD, 0x1C, 0x25, 0x00, 0x30, 0x00, 0x00, // FSTP qword [0x3000] + 0xF4, // HLT ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/mod.rs index ca1d4e74..96a98265 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/fpu/mod.rs @@ -26,6 +26,8 @@ mod fincstp_fdecstp; mod finit_fninit; mod fist_fistp; //mod fistp; +mod arithmetic_variants; +mod comparison_control; mod fisub; mod fisubr; mod fld; @@ -49,8 +51,8 @@ mod fsincos; mod fsqrt; mod fst_fstp; mod fstenv_fnstenv; -mod fsub; mod fstsw_fnstsw; +mod fsub; mod ftst; mod fucom_fucomp_fucompp; mod fucomi_fucomip; @@ -61,5 +63,3 @@ mod fxsave_fxrstor; mod fxtract; mod fyl2x; mod fyl2xp1; -mod arithmetic_variants; -mod comparison_control; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/and.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/and.rs index 572d3933..db7e5bc0 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/and.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/and.rs @@ -32,7 +32,7 @@ fn test_and_al_imm8_basic() { let mut emu = emu64(); let code = [ 0x24, 0x0F, // AND AL, 0x0F - 0xf4, // HLT + 0xf4, // HLT ]; emu.regs_mut().rax = 0xAB; // AL = 0xAB (10101011) emu.load_code_bytes(&code); @@ -100,7 +100,11 @@ fn test_and_ax_imm16_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0004, "AX: 0x1234 AND 0x000F = 0x0004"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0004, + "AX: 0x1234 AND 0x000F = 0x0004" + ); } #[test] @@ -165,7 +169,11 @@ fn test_and_rm16_imm16_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0x0FF0, "BX: 0xFFFF AND 0x0FF0 = 0x0FF0"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0x0FF0, + "BX: 0xFFFF AND 0x0FF0 = 0x0FF0" + ); } #[test] @@ -212,7 +220,11 @@ fn test_and_rm16_imm8_sign_extended() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0x1234, "BX: AND with 0xFFFF (no change)"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0x1234, + "BX: AND with 0xFFFF (no change)" + ); } #[test] @@ -228,7 +240,11 @@ fn test_and_rm32_imm8_sign_extended() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x0000000F, "EBX: AND with sign-extended imm8"); + assert_eq!( + emu.regs().rbx, + 0x0000000F, + "EBX: AND with sign-extended imm8" + ); } // ============================================================================ @@ -264,7 +280,11 @@ fn test_and_rm16_r16_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x00FF, "AX: 0xFFFF AND 0x00FF = 0x00FF"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x00FF, + "AX: 0xFFFF AND 0x00FF = 0x00FF" + ); } #[test] @@ -296,7 +316,11 @@ fn test_and_rm64_r64_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00000000FFFFFFFF, "RAX: mask to low 32 bits"); + assert_eq!( + emu.regs().rax, + 0x00000000FFFFFFFF, + "RAX: mask to low 32 bits" + ); } // ============================================================================ @@ -316,7 +340,11 @@ fn test_and_r8_rm8_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0, "AL: 0xAA AND 0x55 = 0 (no common bits)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0, + "AL: 0xAA AND 0x55 = 0 (no common bits)" + ); assert!(emu.flags().f_zf, "ZF should be set (zero result)"); } @@ -383,7 +411,11 @@ fn test_and_mask_low_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x07, "Extract low nibble: 0xB7 & 0x0F = 0x07"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x07, + "Extract low nibble: 0xB7 & 0x0F = 0x07" + ); } #[test] @@ -599,7 +631,8 @@ fn test_and_dword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x81, 0x25, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, // AND DWORD PTR [rip+0x0FF6], 0x000000FF + 0x81, 0x25, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, // AND DWORD PTR [rip+0x0FF6], 0x000000FF 0xf4, ]; emu.load_code_bytes(&code); @@ -616,7 +649,8 @@ fn test_and_qword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x48, 0x81, 0x25, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, // AND QWORD PTR [rip+0x0FF5], 0x0000FFFF + 0x48, 0x81, 0x25, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, // AND QWORD PTR [rip+0x0FF5], 0x0000FFFF 0xf4, ]; emu.load_code_bytes(&code); @@ -670,6 +704,10 @@ fn test_and_align_to_boundary() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "Aligned to 16-byte boundary"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "Aligned to 16-byte boundary" + ); assert_eq!(emu.regs().rax & 0x0F, 0, "Low 4 bits cleared"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/not.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/not.rs index 3e25ca73..46d7206a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/not.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/not.rs @@ -97,7 +97,11 @@ fn test_not_preserves_high_bytes_8bit() { emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x87, "AL: NOT 0x78 = 0x87"); - assert_eq!(emu.regs().rax & !0xFF, 0xDEADBEEF_12345600, "Upper bytes preserved"); + assert_eq!( + emu.regs().rax & !0xFF, + 0xDEADBEEF_12345600, + "Upper bytes preserved" + ); } // ============================================================================ @@ -159,7 +163,11 @@ fn test_not_eax_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xEDCBA987, "EAX: NOT 0x12345678 = 0xEDCBA987"); + assert_eq!( + emu.regs().rax, + 0xEDCBA987, + "EAX: NOT 0x12345678 = 0xEDCBA987" + ); } #[test] @@ -183,7 +191,11 @@ fn test_not_eax_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00FF00FF, "EAX: NOT 0xFF00FF00 = 0x00FF00FF"); + assert_eq!( + emu.regs().rax, + 0x00FF00FF, + "EAX: NOT 0xFF00FF00 = 0x00FF00FF" + ); } #[test] @@ -195,7 +207,11 @@ fn test_not_ebx_register() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x55555555, "EBX: NOT 0xAAAAAAAA = 0x55555555"); + assert_eq!( + emu.regs().rbx, + 0x55555555, + "EBX: NOT 0xAAAAAAAA = 0x55555555" + ); } // ============================================================================ @@ -214,7 +230,11 @@ fn test_not_rax_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xEDCBA9876543210F, "RAX: NOT 0x123456789ABCDEF0"); + assert_eq!( + emu.regs().rax, + 0xEDCBA9876543210F, + "RAX: NOT 0x123456789ABCDEF0" + ); } #[test] @@ -226,7 +246,11 @@ fn test_not_rax_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX: NOT 0 = 0xFFFF...FFFF"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX: NOT 0 = 0xFFFF...FFFF" + ); } #[test] @@ -238,7 +262,11 @@ fn test_not_rax_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000000, "RAX: NOT 0xFFFF...FFFF = 0"); + assert_eq!( + emu.regs().rax, + 0x0000000000000000, + "RAX: NOT 0xFFFF...FFFF = 0" + ); } #[test] @@ -250,7 +278,11 @@ fn test_not_rax_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00FF00FF00FF00FF, "RAX: invert alternating bytes"); + assert_eq!( + emu.regs().rax, + 0x00FF00FF00FF00FF, + "RAX: invert alternating bytes" + ); } #[test] @@ -411,14 +443,19 @@ fn test_not_preserves_flags() { let mut emu = emu64(); let code = [0xf6, 0xd0, 0xf4]; // NOT AL emu.regs_mut().rax = 0x00; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_PF | - flags::F_AF | flags::F_ZF | flags::F_SF | flags::F_OF); + emu.flags_mut().load( + 0x2 | flags::F_CF | flags::F_PF | flags::F_AF | flags::F_ZF | flags::F_SF | flags::F_OF, + ); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.flags().dump(), initial_flags, "NOT should not affect any flags"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "NOT should not affect any flags" + ); } // ============================================================================ @@ -477,5 +514,9 @@ fn test_not_equivalent_to_xor_minus_one() { emu2.load_code_bytes(&code_xor); emu2.run(None).unwrap(); - assert_eq!(emu1.regs().rax & 0xFF, emu2.regs().rax & 0xFF, "NOT x = x XOR 0xFF"); + assert_eq!( + emu1.regs().rax & 0xFF, + emu2.regs().rax & 0xFF, + "NOT x = x XOR 0xFF" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/or.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/or.rs index 835779c1..962bbac9 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/or.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/or.rs @@ -56,7 +56,11 @@ fn test_or_al_imm8_zero_with_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: 0x42 OR 0 = 0x42 (identity)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: 0x42 OR 0 = 0x42 (identity)" + ); } #[test] @@ -150,7 +154,11 @@ fn test_or_rm64_imm8_sign_extended() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0xFFFFFFFFFFFFFFFF, "RBX: OR with -1 sets all bits"); + assert_eq!( + emu.regs().rbx, + 0xFFFFFFFFFFFFFFFF, + "RBX: OR with -1 sets all bits" + ); } // ============================================================================ @@ -170,7 +178,11 @@ fn test_or_rm8_r8_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xFF, "AL: 0xAA OR 0x55 = 0xFF (all bits)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xFF, + "AL: 0xAA OR 0x55 = 0xFF (all bits)" + ); } #[test] @@ -461,7 +473,8 @@ fn test_or_dword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x81, 0x0d, 0xf6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, // OR DWORD PTR [rip+0x0FF6], 0x00FF0000 + 0x81, 0x0d, 0xf6, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x00, // OR DWORD PTR [rip+0x0FF6], 0x00FF0000 0xf4, ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/test.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/test.rs index 97ba5e2f..df27fc01 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/test.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic/test.rs @@ -155,7 +155,10 @@ fn test_test_rm64_imm32_basic() { emu.run(None).unwrap(); assert_eq!(emu.regs().rbx, 0xFFFFFFFF00000000, "RBX unchanged"); - assert!(!emu.flags().f_zf, "ZF clear (sign-extended imm32 tests all bits)"); + assert!( + !emu.flags().f_zf, + "ZF clear (sign-extended imm32 tests all bits)" + ); } // ============================================================================ @@ -467,7 +470,8 @@ fn test_test_dword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xf7, 0x05, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, // TEST DWORD PTR [rip+0x0FF6], 0x000000FF + 0xf7, 0x05, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, // TEST DWORD PTR [rip+0x0FF6], 0x000000FF 0xf4, ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic_xor/xor.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic_xor/xor.rs index 8f4bb604..20ebd54b 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic_xor/xor.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/basic_logic_xor/xor.rs @@ -56,7 +56,11 @@ fn test_xor_al_imm8_identity() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: 0x42 XOR 0 = 0x42 (identity)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: 0x42 XOR 0 = 0x42 (identity)" + ); } #[test] @@ -69,7 +73,11 @@ fn test_xor_al_imm8_invert() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x55, "AL: 0xAA XOR 0xFF = 0x55 (inverted)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x55, + "AL: 0xAA XOR 0xFF = 0x55 (inverted)" + ); } #[test] @@ -183,7 +191,11 @@ fn test_xor_rm8_r8_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xFF, "AL: 0xAA XOR 0x55 = 0xFF (all different)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xFF, + "AL: 0xAA XOR 0x55 = 0xFF (all different)" + ); } #[test] @@ -232,7 +244,11 @@ fn test_xor_rm64_r64_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX: all bits different"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX: all bits different" + ); } // ============================================================================ @@ -272,7 +288,11 @@ fn test_xor_eax_eax_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0, "EAX: XOR EAX, EAX = 0 (common zero idiom)"); + assert_eq!( + emu.regs().rax, + 0, + "EAX: XOR EAX, EAX = 0 (common zero idiom)" + ); assert!(emu.flags().f_zf, "ZF set"); assert!(!emu.flags().f_sf, "SF clear"); assert!(!emu.flags().f_cf, "CF clear"); @@ -323,14 +343,22 @@ fn test_xor_toggle_specific_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x1F, "Toggle bit 4 on: 0x0F ^ 0x10 = 0x1F"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x1F, + "Toggle bit 4 on: 0x0F ^ 0x10 = 0x1F" + ); let code = [0x34, 0x10, 0xf4]; // XOR AL, 0x10 emu.regs_mut().rax = 0x1F; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x0F, "Toggle bit 4 off: 0x1F ^ 0x10 = 0x0F"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0F, + "Toggle bit 4 off: 0x1F ^ 0x10 = 0x0F" + ); } #[test] @@ -504,7 +532,8 @@ fn test_xor_dword_ptr_mem() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x81, 0x35, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, // XOR DWORD PTR [rip+0x0FF6], 0x0000FFFF + 0x81, 0x35, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, // XOR DWORD PTR [rip+0x0FF6], 0x0000FFFF 0xf4, ]; emu.load_code_bytes(&code); @@ -538,7 +567,11 @@ fn test_xor_encryption_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, plaintext, "XOR encryption/decryption"); + assert_eq!( + emu.regs().rax & 0xFF, + plaintext, + "XOR encryption/decryption" + ); } #[test] @@ -561,7 +594,11 @@ fn test_xor_commutative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, emu.regs().rax & 0xFF, "XOR is commutative"); + assert_eq!( + emu.regs().rax & 0xFF, + emu.regs().rax & 0xFF, + "XOR is commutative" + ); } #[test] @@ -585,5 +622,9 @@ fn test_xor_associative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, emu.regs().rax & 0xFF, "XOR is associative"); + assert_eq!( + emu.regs().rax & 0xFF, + emu.regs().rax & 0xFF, + "XOR is associative" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/bswap.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/bswap.rs index bd57ca01..3db93826 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/bswap.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/bswap.rs @@ -23,7 +23,11 @@ fn test_bswap_eax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78563412, "EAX bytes should be reversed"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78563412, + "EAX bytes should be reversed" + ); } #[test] @@ -39,7 +43,11 @@ fn test_bswap_ebx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0xDDCCBBAA, "EBX bytes should be reversed"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0xDDCCBBAA, + "EBX bytes should be reversed" + ); } #[test] @@ -55,7 +63,11 @@ fn test_bswap_ecx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0x04030201, "ECX bytes should be reversed"); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0x04030201, + "ECX bytes should be reversed" + ); } #[test] @@ -71,7 +83,11 @@ fn test_bswap_edx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0xEFBEADDE, "EDX bytes should be reversed"); + assert_eq!( + emu.regs().rdx & 0xFFFFFFFF, + 0xEFBEADDE, + "EDX bytes should be reversed" + ); } #[test] @@ -87,7 +103,11 @@ fn test_bswap_rax_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xEFCDAB8967452301, "RAX bytes should be reversed"); + assert_eq!( + emu.regs().rax, + 0xEFCDAB8967452301, + "RAX bytes should be reversed" + ); } #[test] @@ -103,7 +123,11 @@ fn test_bswap_rbx_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x1032547698BADCFE, "RBX bytes should be reversed"); + assert_eq!( + emu.regs().rbx, + 0x1032547698BADCFE, + "RBX bytes should be reversed" + ); } #[test] @@ -119,7 +143,11 @@ fn test_bswap_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX should remain zero"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX should remain zero" + ); } #[test] @@ -135,7 +163,11 @@ fn test_bswap_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX should remain all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX should remain all ones" + ); } #[test] @@ -151,7 +183,11 @@ fn test_bswap_alternating_bytes() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x55AA55AA, "EAX bytes should be reversed"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x55AA55AA, + "EAX bytes should be reversed" + ); } #[test] @@ -167,7 +203,11 @@ fn test_bswap_sequential_bytes() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x03020100, "EAX bytes should be reversed"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x03020100, + "EAX bytes should be reversed" + ); } #[test] @@ -183,7 +223,11 @@ fn test_bswap_with_extended_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0x44332211, "R8D bytes should be reversed"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0x44332211, + "R8D bytes should be reversed" + ); } #[test] @@ -199,7 +243,11 @@ fn test_bswap_r9d() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r9 & 0xFFFFFFFF, 0x01EFCDAB, "R9D bytes should be reversed"); + assert_eq!( + emu.regs().r9 & 0xFFFFFFFF, + 0x01EFCDAB, + "R9D bytes should be reversed" + ); } #[test] @@ -215,7 +263,11 @@ fn test_bswap_r15_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x7766554433221100, "R15 bytes should be reversed"); + assert_eq!( + emu.regs().r15, + 0x7766554433221100, + "R15 bytes should be reversed" + ); } #[test] @@ -231,7 +283,11 @@ fn test_bswap_idempotent() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should return to original after double BSWAP"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should return to original after double BSWAP" + ); } #[test] @@ -247,7 +303,11 @@ fn test_bswap_endianness_conversion() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000080, "Endianness should be converted"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000080, + "Endianness should be converted" + ); } #[test] @@ -265,8 +325,16 @@ fn test_bswap_preserves_other_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0xAABBCCDD, "EBX should be unchanged"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0x11111111, "ECX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0xAABBCCDD, + "EBX should be unchanged" + ); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0x11111111, + "ECX should be unchanged" + ); } #[test] @@ -287,9 +355,15 @@ fn test_bswap_single_byte_values() { ]; emu.regs_mut().rax = input; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "BSWAP(0x{:08X}) should be 0x{:08X}", input, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "BSWAP(0x{:08X}) should be 0x{:08X}", + input, + expected + ); } } @@ -305,7 +379,11 @@ fn test_bswap_network_byte_order() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00010000, "Should convert network to host byte order"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00010000, + "Should convert network to host byte order" + ); } #[test] @@ -320,7 +398,11 @@ fn test_bswap_64bit_symmetric() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0102030404030201, "Symmetric pattern should equal itself when swapped"); + assert_eq!( + emu.regs().rax, + 0x0102030404030201, + "Symmetric pattern should equal itself when swapped" + ); } #[test] @@ -335,7 +417,11 @@ fn test_bswap_64bit_asymmetric() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0807060504030201, "RAX bytes should be reversed"); + assert_eq!( + emu.regs().rax, + 0x0807060504030201, + "RAX bytes should be reversed" + ); } #[test] @@ -351,7 +437,11 @@ fn test_bswap_high_low_word_swap() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00003412, "High word moves to low with byte swap"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00003412, + "High word moves to low with byte swap" + ); } #[test] @@ -367,7 +457,11 @@ fn test_bswap_ascii_to_reversed() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x44434241, "ASCII bytes should be reversed"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x44434241, + "ASCII bytes should be reversed" + ); } #[test] @@ -375,10 +469,10 @@ fn test_bswap_powers_of_256() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (0x00000001, 0x01000000), // 256^0 - (0x00000100, 0x00010000), // 256^1 - (0x00010000, 0x00000100), // 256^2 - (0x01000000, 0x00000001), // 256^3 + (0x00000001, 0x01000000), // 256^0 + (0x00000100, 0x00010000), // 256^1 + (0x00010000, 0x00000100), // 256^2 + (0x01000000, 0x00000001), // 256^3 ]; for (input, expected) in test_cases { @@ -388,9 +482,15 @@ fn test_bswap_powers_of_256() { ]; emu.regs_mut().rax = input; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "BSWAP(0x{:08X}) should be 0x{:08X}", input, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "BSWAP(0x{:08X}) should be 0x{:08X}", + input, + expected + ); } } @@ -411,9 +511,21 @@ fn test_bswap_sequential_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x11111111, "EAX should be swapped"); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x22222222, "EBX should be swapped"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0x33333333, "ECX should be swapped"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x11111111, + "EAX should be swapped" + ); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x22222222, + "EBX should be swapped" + ); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0x33333333, + "ECX should be swapped" + ); } #[test] @@ -428,5 +540,9 @@ fn test_bswap_64bit_upper_lower_independence() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xF0DEBC9A_78563412, "Both halves should be byte-swapped and position-swapped"); + assert_eq!( + emu.regs().rax, + 0xF0DEBC9A_78563412, + "Both halves should be byte-swapped and position-swapped" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/lzcnt.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/lzcnt.rs index d0998ade..44804f3c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/lzcnt.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/lzcnt.rs @@ -24,7 +24,11 @@ fn test_lzcnt_ax_bx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 16, "AX should contain 16 (all bits are zero)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 16, + "AX should contain 16 (all bits are zero)" + ); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); assert!(!emu.flags().f_zf, "ZF should be clear (count is non-zero)"); } @@ -42,7 +46,11 @@ fn test_lzcnt_ax_bx_msb_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0, "AX should contain 0 (no leading zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0, + "AX should contain 0 (no leading zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear (source is non-zero)"); assert!(emu.flags().f_zf, "ZF should be set (count is zero)"); } @@ -60,7 +68,11 @@ fn test_lzcnt_eax_ebx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 32, "EAX should contain 32 (all bits are zero)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 32, + "EAX should contain 32 (all bits are zero)" + ); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); } @@ -77,7 +89,11 @@ fn test_lzcnt_eax_ebx_msb_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (no leading zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (no leading zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear (source is non-zero)"); assert!(emu.flags().f_zf, "ZF should be set (count is zero)"); } @@ -95,7 +111,11 @@ fn test_lzcnt_rax_rbx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 64, "RAX should contain 64 (all bits are zero)"); + assert_eq!( + emu.regs().rax, + 64, + "RAX should contain 64 (all bits are zero)" + ); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); } @@ -130,7 +150,11 @@ fn test_lzcnt_eax_ebx_one_leading_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain 1 (one leading zero)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain 1 (one leading zero)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -147,7 +171,11 @@ fn test_lzcnt_eax_ebx_multiple_leading_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 8, "EAX should contain 8 (eight leading zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 8, + "EAX should contain 8 (eight leading zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -162,10 +190,16 @@ fn test_lzcnt_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = 31 - bit_pos; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "LZCNT(2^{}) should be {}", bit_pos, expected); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "LZCNT(2^{}) should be {}", + bit_pos, + expected + ); } } @@ -262,7 +296,11 @@ fn test_lzcnt_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -278,7 +316,11 @@ fn test_lzcnt_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (no leading zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (no leading zeros)" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -304,9 +346,15 @@ fn test_lzcnt_single_bit_patterns() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "LZCNT(0x{:08X}) should be {}", value, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "LZCNT(0x{:08X}) should be {}", + value, + expected + ); } } @@ -323,7 +371,11 @@ fn test_lzcnt_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (MSB is set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (MSB is set)" + ); } #[test] @@ -392,9 +444,15 @@ fn test_lzcnt_byte_values() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "LZCNT(0x{:08X}) should be {}", value, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "LZCNT(0x{:08X}) should be {}", + value, + expected + ); } } @@ -410,7 +468,11 @@ fn test_lzcnt_complement_of_tzcnt_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 4, "EAX should contain 4 (31 - 27 = 4)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 4, + "EAX should contain 4 (31 - 27 = 4)" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/tzcnt.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/tzcnt.rs index 3302cf27..7cd212bb 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/tzcnt.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_counting_swap/tzcnt.rs @@ -24,7 +24,11 @@ fn test_tzcnt_ax_bx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 16, "AX should contain 16 (all bits are zero)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 16, + "AX should contain 16 (all bits are zero)" + ); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); assert!(!emu.flags().f_zf, "ZF should be clear (count is non-zero)"); } @@ -42,7 +46,11 @@ fn test_tzcnt_ax_bx_lsb_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0, "AX should contain 0 (no trailing zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0, + "AX should contain 0 (no trailing zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear (source is non-zero)"); assert!(emu.flags().f_zf, "ZF should be set (count is zero)"); } @@ -60,7 +68,11 @@ fn test_tzcnt_eax_ebx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 32, "EAX should contain 32 (all bits are zero)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 32, + "EAX should contain 32 (all bits are zero)" + ); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); } @@ -77,7 +89,11 @@ fn test_tzcnt_eax_ebx_lsb_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (no trailing zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (no trailing zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear (source is non-zero)"); assert!(emu.flags().f_zf, "ZF should be set (count is zero)"); } @@ -95,7 +111,11 @@ fn test_tzcnt_rax_rbx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 64, "RAX should contain 64 (all bits are zero)"); + assert_eq!( + emu.regs().rax, + 64, + "RAX should contain 64 (all bits are zero)" + ); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); } @@ -112,7 +132,11 @@ fn test_tzcnt_rax_rbx_lsb_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0, "RAX should contain 0 (no trailing zeros)"); + assert_eq!( + emu.regs().rax, + 0, + "RAX should contain 0 (no trailing zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear (source is non-zero)"); assert!(emu.flags().f_zf, "ZF should be set (count is zero)"); } @@ -130,7 +154,11 @@ fn test_tzcnt_eax_ebx_one_trailing_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain 1 (one trailing zero)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain 1 (one trailing zero)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -147,7 +175,11 @@ fn test_tzcnt_eax_ebx_multiple_trailing_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 16, "EAX should contain 16 (sixteen trailing zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 16, + "EAX should contain 16 (sixteen trailing zeros)" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -162,9 +194,15 @@ fn test_tzcnt_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, bit_pos as u64, "TZCNT(2^{}) should be {}", bit_pos, bit_pos); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + bit_pos as u64, + "TZCNT(2^{}) should be {}", + bit_pos, + bit_pos + ); } } @@ -261,7 +299,11 @@ fn test_tzcnt_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -277,7 +319,11 @@ fn test_tzcnt_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (no trailing zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (no trailing zeros)" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -303,9 +349,15 @@ fn test_tzcnt_single_bit_patterns() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "TZCNT(0x{:08X}) should be {}", value, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "TZCNT(0x{:08X}) should be {}", + value, + expected + ); } } @@ -322,7 +374,11 @@ fn test_tzcnt_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain 1 (one trailing zero)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain 1 (one trailing zero)" + ); } #[test] @@ -391,9 +447,15 @@ fn test_tzcnt_byte_values() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "TZCNT(0x{:08X}) should be {}", value, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "TZCNT(0x{:08X}) should be {}", + value, + expected + ); } } @@ -410,7 +472,11 @@ fn test_tzcnt_vs_bsf_similarity() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 16, "TZCNT should find first set bit at position 16"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 16, + "TZCNT should find first set bit at position 16" + ); } #[test] @@ -451,10 +517,10 @@ fn test_tzcnt_alignment_detection() { let mut emu = emu64(); // TZCNT can detect alignment (power of 2 divisibility) let test_cases = vec![ - (0x00000001, 0), // 2^0 aligned - (0x00000002, 1), // 2^1 aligned - (0x00000004, 2), // 2^2 aligned - (0x00000008, 3), // 2^3 aligned + (0x00000001, 0), // 2^0 aligned + (0x00000002, 1), // 2^1 aligned + (0x00000004, 2), // 2^2 aligned + (0x00000008, 3), // 2^3 aligned (0x00001000, 12), // 2^12 aligned (4KB) ]; @@ -465,9 +531,15 @@ fn test_tzcnt_alignment_detection() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Value 0x{:08X} is 2^{} aligned", value, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Value 0x{:08X} is 2^{} aligned", + value, + expected + ); } } @@ -484,9 +556,14 @@ fn test_tzcnt_odd_numbers() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "Odd number {} should have 0 trailing zeros", value); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "Odd number {} should have 0 trailing zeros", + value + ); } } @@ -495,12 +572,12 @@ fn test_tzcnt_even_numbers() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (2, 1), // one trailing zero - (4, 2), // two trailing zeros - (6, 1), // one trailing zero - (8, 3), // three trailing zeros - (12, 2), // two trailing zeros - (16, 4), // four trailing zeros + (2, 1), // one trailing zero + (4, 2), // two trailing zeros + (6, 1), // one trailing zero + (8, 3), // three trailing zeros + (12, 2), // two trailing zeros + (16, 4), // four trailing zeros ]; for (value, expected) in test_cases { @@ -510,8 +587,14 @@ fn test_tzcnt_even_numbers() { ]; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Even number {} should have {} trailing zeros", value, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Even number {} should have {} trailing zeros", + value, + expected + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsf.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsf.rs index 8218b876..4952aed8 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsf.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsf.rs @@ -26,7 +26,11 @@ fn test_bsf_ax_bx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0, "AX should contain 0 (bit 0 is LSB)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0, + "AX should contain 0 (bit 0 is LSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -43,7 +47,11 @@ fn test_bsf_ax_bx_bit_15() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 15, "AX should contain 15 (bit 15 is LSB)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 15, + "AX should contain 15 (bit 15 is LSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -60,7 +68,11 @@ fn test_bsf_eax_ebx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (bit 0 is LSB)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (bit 0 is LSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -77,7 +89,11 @@ fn test_bsf_eax_ebx_bit_31() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 31, "EAX should contain 31 (bit 31 is LSB)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 31, + "EAX should contain 31 (bit 31 is LSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -144,7 +160,11 @@ fn test_bsf_multiple_bits_finds_lowest() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 3, "EAX should contain 3 (lowest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 3, + "EAX should contain 3 (lowest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -161,7 +181,11 @@ fn test_bsf_all_bits_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (bit 0 is lowest)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (bit 0 is lowest)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -178,7 +202,11 @@ fn test_bsf_alternating_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain 1 (lowest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain 1 (lowest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -195,7 +223,11 @@ fn test_bsf_alternating_bits_inverted() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (lowest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (lowest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -210,9 +242,15 @@ fn test_bsf_single_bit_positions() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, bit_pos as u64, "EAX should contain {} for bit {}", bit_pos, bit_pos); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + bit_pos as u64, + "EAX should contain {} for bit {}", + bit_pos, + bit_pos + ); assert!(!emu.flags().f_zf, "ZF should be clear for bit {}", bit_pos); } } @@ -365,7 +403,11 @@ fn test_bsf_sparse_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 12, "EAX should contain 12 (lower bit)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 12, + "EAX should contain 12 (lower bit)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -382,7 +424,11 @@ fn test_bsf_consecutive_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 16, "EAX should contain 16 (lowest of consecutive bits)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 16, + "EAX should contain 16 (lowest of consecutive bits)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -399,7 +445,11 @@ fn test_bsf_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -431,9 +481,15 @@ fn test_bsf_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << i; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, i as u64, "EAX should contain {} for 2^{}", i, i); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + i as u64, + "EAX should contain {} for 2^{}", + i, + i + ); } } @@ -450,7 +506,11 @@ fn test_bsf_trailing_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 12, "EAX should contain 12 (12 trailing zeros)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 12, + "EAX should contain 12 (12 trailing zeros)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsr.rs index a01db810..011b07e1 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/bsr.rs @@ -26,7 +26,11 @@ fn test_bsr_ax_bx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0, "AX should contain 0 (bit 0 is MSB)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0, + "AX should contain 0 (bit 0 is MSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -43,7 +47,11 @@ fn test_bsr_ax_bx_bit_15() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 15, "AX should contain 15 (bit 15 is MSB)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 15, + "AX should contain 15 (bit 15 is MSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -60,7 +68,11 @@ fn test_bsr_eax_ebx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should contain 0 (bit 0 is MSB)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should contain 0 (bit 0 is MSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -77,7 +89,11 @@ fn test_bsr_eax_ebx_bit_31() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 31, "EAX should contain 31 (bit 31 is MSB)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 31, + "EAX should contain 31 (bit 31 is MSB)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); } @@ -144,7 +160,11 @@ fn test_bsr_multiple_bits_finds_highest() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 7, "EAX should contain 7 (highest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 7, + "EAX should contain 7 (highest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -161,7 +181,11 @@ fn test_bsr_all_bits_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 31, "EAX should contain 31 (bit 31 is highest)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 31, + "EAX should contain 31 (bit 31 is highest)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -178,7 +202,11 @@ fn test_bsr_alternating_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 31, "EAX should contain 31 (highest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 31, + "EAX should contain 31 (highest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -195,7 +223,11 @@ fn test_bsr_alternating_bits_inverted() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 30, "EAX should contain 30 (highest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 30, + "EAX should contain 30 (highest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -210,9 +242,15 @@ fn test_bsr_single_bit_positions() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, bit_pos as u64, "EAX should contain {} for bit {}", bit_pos, bit_pos); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + bit_pos as u64, + "EAX should contain {} for bit {}", + bit_pos, + bit_pos + ); assert!(!emu.flags().f_zf, "ZF should be clear for bit {}", bit_pos); } } @@ -365,7 +403,11 @@ fn test_bsr_sparse_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 31, "EAX should contain 31 (higher bit)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 31, + "EAX should contain 31 (higher bit)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -382,7 +424,11 @@ fn test_bsr_consecutive_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 23, "EAX should contain 23 (highest of consecutive bits)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 23, + "EAX should contain 23 (highest of consecutive bits)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -399,7 +445,11 @@ fn test_bsr_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -431,9 +481,15 @@ fn test_bsr_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << i; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, i as u64, "EAX should contain {} for 2^{}", i, i); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + i as u64, + "EAX should contain {} for 2^{}", + i, + i + ); } } @@ -450,7 +506,11 @@ fn test_bsr_leading_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 11, "EAX should contain 11 (highest bit set)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 11, + "EAX should contain 11 (highest bit set)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/mod.rs index 4be91973..fef5ac61 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_scanning/mod.rs @@ -1,2 +1,2 @@ -mod bsr; mod bsf; +mod bsr; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bt.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bt.rs index 73d6ecda..63d04016 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bt.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bt.rs @@ -242,7 +242,10 @@ fn test_bt_eax_ebx_alternating_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be set (bit 1 is 1 in 0xAAAAAAAA)"); + assert!( + emu.flags().f_cf, + "CF should be set (bit 1 is 1 in 0xAAAAAAAA)" + ); } #[test] @@ -258,7 +261,10 @@ fn test_bt_eax_ebx_alternating_bits_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert!(!emu.flags().f_cf, "CF should be clear (bit 0 is 0 in 0xAAAAAAAA)"); + assert!( + !emu.flags().f_cf, + "CF should be clear (bit 0 is 0 in 0xAAAAAAAA)" + ); } #[test] @@ -275,7 +281,11 @@ fn test_bt_does_not_modify_operand() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: BT should not modify operand"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: BT should not modify operand" + ); } #[test] @@ -293,7 +303,11 @@ fn test_bt_with_extended_registers() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 is 1)"); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0000_0001, "R8D: BT should not modify operand"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0000_0001, + "R8D: BT should not modify operand" + ); } #[test] @@ -424,7 +438,10 @@ fn test_bt_bit_position_modulo_16() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be set (bit position 16 wraps to 0)"); + assert!( + emu.flags().f_cf, + "CF should be set (bit position 16 wraps to 0)" + ); } #[test] @@ -440,7 +457,10 @@ fn test_bt_bit_position_modulo_32() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be set (bit position 32 wraps to 0)"); + assert!( + emu.flags().f_cf, + "CF should be set (bit position 32 wraps to 0)" + ); } #[test] @@ -456,7 +476,10 @@ fn test_bt_bit_position_modulo_64() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be set (bit position 64 wraps to 0)"); + assert!( + emu.flags().f_cf, + "CF should be set (bit position 64 wraps to 0)" + ); } #[test] @@ -502,10 +525,22 @@ fn test_bt_preserves_other_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should be unchanged"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should be unchanged" + ); assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 5, "EBX should be unchanged"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0xABCDEF00, "ECX should be unchanged"); - assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0x11223344, "EDX should be unchanged"); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0xABCDEF00, + "ECX should be unchanged" + ); + assert_eq!( + emu.regs().rdx & 0xFFFFFFFF, + 0x11223344, + "EDX should be unchanged" + ); } #[test] @@ -536,7 +571,7 @@ fn test_bt_single_bit_patterns() { emu.regs_mut().rax = 1u64 << bit_pos; emu.regs_mut().rbx = bit_pos as u64; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set for bit {}", bit_pos); } @@ -595,7 +630,8 @@ fn test_bt_imm8_upper_bits_ignored() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x0f, 0xba, 0xe0, 0xff, // BT EAX, 0xFF (only lower 5 bits matter for 32-bit: 0x1F = 31) + 0x0f, 0xba, 0xe0, + 0xff, // BT EAX, 0xFF (only lower 5 bits matter for 32-bit: 0x1F = 31) 0xf4, ]; emu.regs_mut().rax = 0x80000000; // bit 31 set diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btc.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btc.rs index 655187d9..5710f3bb 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btc.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btc.rs @@ -30,7 +30,11 @@ fn test_btc_ax_bx_bit_0_set() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0000, "AX: bit 0 should be complemented to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0000, + "AX: bit 0 should be complemented to 0" + ); } #[test] @@ -48,7 +52,11 @@ fn test_btc_ax_bx_bit_0_clear() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0001, "AX: bit 0 should be complemented to 1"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0001, + "AX: bit 0 should be complemented to 1" + ); } #[test] @@ -66,7 +74,11 @@ fn test_btc_ax_bx_bit_15() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 15 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX: bit 15 should be complemented to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0000, + "AX: bit 15 should be complemented to 0" + ); } #[test] @@ -84,7 +96,11 @@ fn test_btc_eax_ebx_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0000, "EAX: bit 0 should be complemented to 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0000, + "EAX: bit 0 should be complemented to 0" + ); } #[test] @@ -102,7 +118,11 @@ fn test_btc_eax_ebx_bit_31() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 31 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: bit 31 should be complemented to 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: bit 31 should be complemented to 0" + ); } #[test] @@ -120,7 +140,11 @@ fn test_btc_rax_rbx_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax, 0b0000_0000, "RAX: bit 0 should be complemented to 0"); + assert_eq!( + emu.regs().rax, + 0b0000_0000, + "RAX: bit 0 should be complemented to 0" + ); } #[test] @@ -138,7 +162,11 @@ fn test_btc_rax_rbx_bit_63() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 63 was 1)"); - assert_eq!(emu.regs().rax, 0x0000_0000_0000_0000, "RAX: bit 63 should be complemented to 0"); + assert_eq!( + emu.regs().rax, + 0x0000_0000_0000_0000, + "RAX: bit 63 should be complemented to 0" + ); } #[test] @@ -155,7 +183,11 @@ fn test_btc_ax_imm8_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0000, "AX: bit 0 should be complemented to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0000, + "AX: bit 0 should be complemented to 0" + ); } #[test] @@ -172,7 +204,11 @@ fn test_btc_ax_imm8_bit_15() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 15 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: bit 15 should be complemented to 1"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: bit 15 should be complemented to 1" + ); } #[test] @@ -189,7 +225,11 @@ fn test_btc_eax_imm8_bit_0() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0001, "EAX: bit 0 should be complemented to 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0001, + "EAX: bit 0 should be complemented to 1" + ); } #[test] @@ -206,7 +246,11 @@ fn test_btc_eax_imm8_bit_31() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 31 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: bit 31 should be complemented to 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: bit 31 should be complemented to 1" + ); } #[test] @@ -223,7 +267,11 @@ fn test_btc_rax_imm8_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax, 0b0000_0000, "RAX: bit 0 should be complemented to 0"); + assert_eq!( + emu.regs().rax, + 0b0000_0000, + "RAX: bit 0 should be complemented to 0" + ); } #[test] @@ -240,7 +288,11 @@ fn test_btc_rax_imm8_bit_63() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 63 was 0)"); - assert_eq!(emu.regs().rax, 0x8000_0000_0000_0000, "RAX: bit 63 should be complemented to 1"); + assert_eq!( + emu.regs().rax, + 0x8000_0000_0000_0000, + "RAX: bit 63 should be complemented to 1" + ); } #[test] @@ -257,7 +309,11 @@ fn test_btc_double_complement() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: double complement should return to original"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: double complement should return to original" + ); } #[test] @@ -274,7 +330,11 @@ fn test_btc_alternating_bits() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 1 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA & !0x2, "EAX: bit 1 should be complemented"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAAAAAA & !0x2, + "EAX: bit 1 should be complemented" + ); } #[test] @@ -291,7 +351,11 @@ fn test_btc_preserves_other_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF & !(1 << 5), "EAX: only bit 5 should change"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF & !(1 << 5), + "EAX: only bit 5 should change" + ); } #[test] @@ -309,7 +373,11 @@ fn test_btc_with_extended_registers() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0000_0000, "R8D: bit 0 should be complemented to 0"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0000_0000, + "R8D: bit 0 should be complemented to 0" + ); } #[test] @@ -326,7 +394,11 @@ fn test_btc_r15_imm8() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 32 was 0)"); - assert_eq!(emu.regs().r15, 0x1_0000_0000, "R15: bit 32 should be complemented to 1"); + assert_eq!( + emu.regs().r15, + 0x1_0000_0000, + "R15: bit 32 should be complemented to 1" + ); } #[test] @@ -364,7 +436,10 @@ fn test_btc_mem32_reg() { assert!(!emu.flags().f_cf, "CF should be clear (bit 16 was 0)"); let result = emu.maps.read_dword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x00010000, "Memory: bit 16 should be complemented to 1"); + assert_eq!( + result, 0x00010000, + "Memory: bit 16 should be complemented to 1" + ); } #[test] @@ -383,7 +458,10 @@ fn test_btc_mem64_reg() { assert!(emu.flags().f_cf, "CF should be set (bit 40 was 1)"); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x000_0000_0000, "Memory: bit 40 should be complemented to 0"); + assert_eq!( + result, 0x000_0000_0000, + "Memory: bit 40 should be complemented to 0" + ); } #[test] @@ -419,7 +497,11 @@ fn test_btc_toggle_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 10, "EAX: bit 10 should be set after 3 toggles"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 10, + "EAX: bit 10 should be set after 3 toggles" + ); } #[test] @@ -436,7 +518,11 @@ fn test_btc_all_bits_set() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 17 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF & !(1 << 17), "EAX: bit 17 should be clear"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF & !(1 << 17), + "EAX: bit 17 should be clear" + ); } #[test] @@ -453,7 +539,11 @@ fn test_btc_all_bits_clear() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 17 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 17, "EAX: bit 17 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 17, + "EAX: bit 17 should be set" + ); } #[test] @@ -470,7 +560,11 @@ fn test_btc_bit_position_modulo_16() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX: bit 0 should be complemented"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0000, + "AX: bit 0 should be complemented" + ); } #[test] @@ -487,7 +581,11 @@ fn test_btc_bit_position_modulo_32() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0000, "EAX: bit 0 should be complemented"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0000, + "EAX: bit 0 should be complemented" + ); } #[test] @@ -520,7 +618,11 @@ fn test_btc_creates_single_bit_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 20, "EAX: only bit 20 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 20, + "EAX: only bit 20 should be set" + ); } #[test] @@ -536,7 +638,11 @@ fn test_btc_clears_single_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF & !(1 << 20), "EAX: only bit 20 should be clear"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF & !(1 << 20), + "EAX: only bit 20 should be clear" + ); } #[test] @@ -552,7 +658,11 @@ fn test_btc_multiple_different_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 5, "EAX: bit 5 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 5, + "EAX: bit 5 should be set" + ); let code = [ 0x0f, 0xbb, 0xd8, // BTC EAX, EBX @@ -562,5 +672,9 @@ fn test_btc_multiple_different_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, (1 << 5) | (1 << 10), "EAX: bits 5 and 10 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + (1 << 5) | (1 << 10), + "EAX: bits 5 and 10 should be set" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btr.rs index d11bd950..32a8d103 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/btr.rs @@ -30,7 +30,11 @@ fn test_btr_ax_bx_bit_0_set() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0000, "AX: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0000, + "AX: bit 0 should be reset to 0" + ); } #[test] @@ -48,7 +52,11 @@ fn test_btr_ax_bx_bit_0_clear() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0000, "AX: bit 0 should remain 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0000, + "AX: bit 0 should remain 0" + ); } #[test] @@ -66,7 +74,11 @@ fn test_btr_ax_bx_bit_15() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 15 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX: bit 15 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0000, + "AX: bit 15 should be reset to 0" + ); } #[test] @@ -84,7 +96,11 @@ fn test_btr_eax_ebx_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0000, "EAX: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0000, + "EAX: bit 0 should be reset to 0" + ); } #[test] @@ -102,7 +118,11 @@ fn test_btr_eax_ebx_bit_31() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 31 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: bit 31 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: bit 31 should be reset to 0" + ); } #[test] @@ -120,7 +140,11 @@ fn test_btr_rax_rbx_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax, 0b0000_0000, "RAX: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().rax, + 0b0000_0000, + "RAX: bit 0 should be reset to 0" + ); } #[test] @@ -138,7 +162,11 @@ fn test_btr_rax_rbx_bit_63() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 63 was 1)"); - assert_eq!(emu.regs().rax, 0x0000_0000_0000_0000, "RAX: bit 63 should be reset to 0"); + assert_eq!( + emu.regs().rax, + 0x0000_0000_0000_0000, + "RAX: bit 63 should be reset to 0" + ); } #[test] @@ -155,7 +183,11 @@ fn test_btr_ax_imm8_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0000, "AX: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0000, + "AX: bit 0 should be reset to 0" + ); } #[test] @@ -172,7 +204,11 @@ fn test_btr_ax_imm8_bit_15() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 15 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0000, "AX: bit 15 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0000, + "AX: bit 15 should be reset to 0" + ); } #[test] @@ -189,7 +225,11 @@ fn test_btr_eax_imm8_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0000, "EAX: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0000, + "EAX: bit 0 should be reset to 0" + ); } #[test] @@ -206,7 +246,11 @@ fn test_btr_eax_imm8_bit_31() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 31 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: bit 31 should be reset to 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: bit 31 should be reset to 0" + ); } #[test] @@ -223,7 +267,11 @@ fn test_btr_rax_imm8_bit_0() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax, 0b0000_0000, "RAX: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().rax, + 0b0000_0000, + "RAX: bit 0 should be reset to 0" + ); } #[test] @@ -240,7 +288,11 @@ fn test_btr_rax_imm8_bit_63() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 63 was 1)"); - assert_eq!(emu.regs().rax, 0x0000_0000_0000_0000, "RAX: bit 63 should be reset to 0"); + assert_eq!( + emu.regs().rax, + 0x0000_0000_0000_0000, + "RAX: bit 63 should be reset to 0" + ); } #[test] @@ -258,7 +310,11 @@ fn test_btr_idempotent() { emu.run(None).unwrap(); let expected = 0x12345678 & !(1 << 5); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "EAX: double reset should have same result"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "EAX: double reset should have same result" + ); } #[test] @@ -275,7 +331,11 @@ fn test_btr_alternating_bits() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 1 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA & !0x2, "EAX: bit 1 should be reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAAAAAA & !0x2, + "EAX: bit 1 should be reset" + ); } #[test] @@ -292,7 +352,11 @@ fn test_btr_preserves_other_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF & !(1 << 5), "EAX: only bit 5 should change"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF & !(1 << 5), + "EAX: only bit 5 should change" + ); } #[test] @@ -310,7 +374,11 @@ fn test_btr_with_extended_registers() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0000_0000, "R8D: bit 0 should be reset to 0"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0000_0000, + "R8D: bit 0 should be reset to 0" + ); } #[test] @@ -384,7 +452,10 @@ fn test_btr_mem64_reg() { assert!(emu.flags().f_cf, "CF should be set (bit 40 was 1)"); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x000_0000_0000, "Memory: bit 40 should be reset to 0"); + assert_eq!( + result, 0x000_0000_0000, + "Memory: bit 40 should be reset to 0" + ); } #[test] @@ -419,7 +490,11 @@ fn test_btr_all_bits_set() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 17 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF & !(1 << 17), "EAX: bit 17 should be clear"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF & !(1 << 17), + "EAX: bit 17 should be clear" + ); } #[test] @@ -436,7 +511,11 @@ fn test_btr_all_bits_clear() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 17 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: should remain zero"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: should remain zero" + ); } #[test] @@ -470,7 +549,11 @@ fn test_btr_bit_position_modulo_32() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0000, "EAX: bit 0 should be reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0000, + "EAX: bit 0 should be reset" + ); } #[test] @@ -503,7 +586,11 @@ fn test_btr_clears_to_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX: should be zero after resetting only bit"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX: should be zero after resetting only bit" + ); } #[test] @@ -519,7 +606,11 @@ fn test_btr_multiple_bits_sequential() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, (1 << 10) | (1 << 15), "EAX: bit 5 should be clear"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + (1 << 10) | (1 << 15), + "EAX: bit 5 should be clear" + ); let code = [ 0x0f, 0xb3, 0xd8, // BTR EAX, EBX @@ -529,7 +620,11 @@ fn test_btr_multiple_bits_sequential() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 15, "EAX: bits 5 and 10 should be clear"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 15, + "EAX: bits 5 and 10 should be clear" + ); } #[test] @@ -546,7 +641,11 @@ fn test_btr_no_effect_on_clear_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: should be unchanged"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: should be unchanged" + ); } #[test] @@ -563,7 +662,11 @@ fn test_btr_creates_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF & !(1 << 8), "EAX: creates mask with bit 8 clear"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF & !(1 << 8), + "EAX: creates mask with bit 8 clear" + ); } #[test] @@ -579,7 +682,11 @@ fn test_btr_sparse_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: bit 0 should be clear, bit 31 remains"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: bit 0 should be clear, bit 31 remains" + ); } #[test] @@ -595,5 +702,9 @@ fn test_btr_high_bit_64() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFF_FFFF_FFFF_FFFF & !(1u64 << 59), "RAX: bit 59 should be clear"); + assert_eq!( + emu.regs().rax, + 0xFFFF_FFFF_FFFF_FFFF & !(1u64 << 59), + "RAX: bit 59 should be clear" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bts.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bts.rs index b9c2b48d..5eb57412 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bts.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/bts.rs @@ -30,7 +30,11 @@ fn test_bts_ax_bx_bit_0_set() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 0 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0001, "AX: bit 0 should remain set"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0001, + "AX: bit 0 should remain set" + ); } #[test] @@ -48,7 +52,11 @@ fn test_bts_ax_bx_bit_0_clear() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0001, "AX: bit 0 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0001, + "AX: bit 0 should be set to 1" + ); } #[test] @@ -66,7 +74,11 @@ fn test_bts_ax_bx_bit_15() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 15 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: bit 15 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: bit 15 should be set to 1" + ); } #[test] @@ -84,7 +96,11 @@ fn test_bts_eax_ebx_bit_0() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0001, "EAX: bit 0 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0001, + "EAX: bit 0 should be set to 1" + ); } #[test] @@ -102,7 +118,11 @@ fn test_bts_eax_ebx_bit_31() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 31 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: bit 31 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: bit 31 should be set to 1" + ); } #[test] @@ -138,7 +158,11 @@ fn test_bts_rax_rbx_bit_63() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 63 was 0)"); - assert_eq!(emu.regs().rax, 0x8000_0000_0000_0000, "RAX: bit 63 should be set to 1"); + assert_eq!( + emu.regs().rax, + 0x8000_0000_0000_0000, + "RAX: bit 63 should be set to 1" + ); } #[test] @@ -155,7 +179,11 @@ fn test_bts_ax_imm8_bit_0() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0b0000_0000_0000_0001, "AX: bit 0 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0b0000_0000_0000_0001, + "AX: bit 0 should be set to 1" + ); } #[test] @@ -172,7 +200,11 @@ fn test_bts_ax_imm8_bit_15() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 15 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: bit 15 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: bit 15 should be set to 1" + ); } #[test] @@ -189,7 +221,11 @@ fn test_bts_eax_imm8_bit_0() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0001, "EAX: bit 0 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0001, + "EAX: bit 0 should be set to 1" + ); } #[test] @@ -206,7 +242,11 @@ fn test_bts_eax_imm8_bit_31() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 31 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: bit 31 should be set to 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: bit 31 should be set to 1" + ); } #[test] @@ -240,7 +280,11 @@ fn test_bts_rax_imm8_bit_63() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 63 was 0)"); - assert_eq!(emu.regs().rax, 0x8000_0000_0000_0000, "RAX: bit 63 should be set to 1"); + assert_eq!( + emu.regs().rax, + 0x8000_0000_0000_0000, + "RAX: bit 63 should be set to 1" + ); } #[test] @@ -258,7 +302,11 @@ fn test_bts_idempotent() { emu.run(None).unwrap(); let expected = 0x12345678 | (1 << 5); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "EAX: double set should have same result"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "EAX: double set should have same result" + ); } #[test] @@ -275,7 +323,11 @@ fn test_bts_alternating_bits() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA | 0x1, "EAX: bit 0 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAAAAAA | 0x1, + "EAX: bit 0 should be set" + ); } #[test] @@ -292,7 +344,11 @@ fn test_bts_preserves_other_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 5, "EAX: only bit 5 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 5, + "EAX: only bit 5 should be set" + ); } #[test] @@ -310,7 +366,11 @@ fn test_bts_with_extended_registers() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0000_0001, "R8D: bit 0 should be set to 1"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0000_0001, + "R8D: bit 0 should be set to 1" + ); } #[test] @@ -327,7 +387,11 @@ fn test_bts_r15_imm8() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 32 was 0)"); - assert_eq!(emu.regs().r15, 0x1_0000_0000, "R15: bit 32 should be set to 1"); + assert_eq!( + emu.regs().r15, + 0x1_0000_0000, + "R15: bit 32 should be set to 1" + ); } #[test] @@ -419,7 +483,11 @@ fn test_bts_all_bits_set() { emu.run(None).unwrap(); assert!(emu.flags().f_cf, "CF should be set (bit 17 was 1)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: should remain all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: should remain all ones" + ); } #[test] @@ -436,7 +504,11 @@ fn test_bts_all_bits_clear() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 17 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 17, "EAX: bit 17 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 17, + "EAX: bit 17 should be set" + ); } #[test] @@ -470,7 +542,11 @@ fn test_bts_bit_position_modulo_32() { emu.run(None).unwrap(); assert!(!emu.flags().f_cf, "CF should be clear (bit 0 was 0)"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0001, "EAX: bit 0 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0001, + "EAX: bit 0 should be set" + ); } #[test] @@ -503,7 +579,11 @@ fn test_bts_creates_single_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 20, "EAX: only bit 20 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 20, + "EAX: only bit 20 should be set" + ); } #[test] @@ -519,7 +599,11 @@ fn test_bts_multiple_bits_sequential() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 5, "EAX: bit 5 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 5, + "EAX: bit 5 should be set" + ); let code = [ 0x0f, 0xab, 0xd8, // BTS EAX, EBX @@ -529,7 +613,11 @@ fn test_bts_multiple_bits_sequential() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, (1 << 5) | (1 << 10), "EAX: bits 5 and 10 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + (1 << 5) | (1 << 10), + "EAX: bits 5 and 10 should be set" + ); } #[test] @@ -546,7 +634,11 @@ fn test_bts_no_effect_on_set_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345679, "EAX: should be unchanged"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345679, + "EAX: should be unchanged" + ); } #[test] @@ -563,7 +655,11 @@ fn test_bts_creates_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1 << 8, "EAX: creates mask with bit 8 set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1 << 8, + "EAX: creates mask with bit 8 set" + ); } #[test] @@ -579,7 +675,11 @@ fn test_bts_sparse_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000001, "EAX: bits 0 and 31 should be set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000001, + "EAX: bits 0 and 31 should be set" + ); } #[test] @@ -612,7 +712,7 @@ fn test_bts_build_bitmask() { emu.regs_mut().rax = result as u64; emu.regs_mut().rbx = bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); result = (emu.regs().rax & 0xFFFFFFFF) as u32; } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/mod.rs index 542707d8..e67bb07d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bit_testing/mod.rs @@ -1,4 +1,4 @@ +mod bt; mod btc; mod btr; -mod bt; mod bts; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/bextr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/bextr.rs index d5d7f317..2ce56175 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/bextr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/bextr.rs @@ -27,7 +27,11 @@ fn test_bextr_eax_ebx_ecx_basic() { emu.run(None).unwrap(); // 0x12345678 >> 4 = 0x01234567, mask 8 bits = 0x67 - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x67, "EAX should contain extracted bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x67, + "EAX should contain extracted bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear (result is non-zero)"); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -65,7 +69,11 @@ fn test_bextr_eax_ebx_ecx_start_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFF, "EAX should contain lower 16 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFF, + "EAX should contain lower 16 bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -101,7 +109,11 @@ fn test_bextr_eax_ebx_ecx_length_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (length=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (length=0)" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -119,7 +131,11 @@ fn test_bextr_eax_ebx_ecx_full_32bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should contain all bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should contain all bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -174,7 +190,11 @@ fn test_bextr_start_beyond_operand_size() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (start beyond size)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (start beyond size)" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -192,7 +212,11 @@ fn test_bextr_length_exceeds_remaining() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFF, "EAX should contain remaining bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFF, + "EAX should contain remaining bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -211,7 +235,11 @@ fn test_bextr_with_extended_registers() { emu.run(None).unwrap(); let expected = (0xABCDEF01 >> 4) & 0xFFF; - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, expected, "R8D should contain extracted bits"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + expected, + "R8D should contain extracted bits" + ); } #[test] @@ -220,7 +248,8 @@ fn test_bextr_mem32() { let mut emu = emu64(); // BEXTR EAX, [mem], ECX let code = [ - 0xc4, 0xe2, 0x70, 0xf7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // BEXTR EAX, [DATA_ADDR], ECX + 0xc4, 0xe2, 0x70, 0xf7, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // BEXTR EAX, [DATA_ADDR], ECX 0xf4, ]; emu.regs_mut().rcx = (8 << 8) | 8; // length=8, start=8 @@ -228,7 +257,11 @@ fn test_bextr_mem32() { emu.maps.write_dword(DATA_ADDR, 0xAABBCCDD); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xCC, "EAX should contain extracted bits from memory"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xCC, + "EAX should contain extracted bits from memory" + ); } #[test] @@ -237,7 +270,8 @@ fn test_bextr_mem64() { let mut emu = emu64(); // BEXTR RAX, [mem], RCX let code = [ - 0xc4, 0xe2, 0xf0, 0xf7, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // BEXTR RAX, [DATA_ADDR], RCX + 0xc4, 0xe2, 0xf0, 0xf7, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // BEXTR RAX, [DATA_ADDR], RCX 0xf4, ]; emu.regs_mut().rcx = (16 << 8) | 16; // length=16, start=16 @@ -245,7 +279,11 @@ fn test_bextr_mem64() { emu.maps.write_qword(DATA_ADDR, 0x0123456789ABCDEF); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x89AB, "RAX should contain extracted bits from memory"); + assert_eq!( + emu.regs().rax, + 0x89AB, + "RAX should contain extracted bits from memory" + ); } #[test] @@ -262,10 +300,15 @@ fn test_bextr_nibble_extraction() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = (4 << 8) | (nibble_idx * 4); // length=4, start=nibble_idx*4 emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (value >> (nibble_idx * 4)) & 0xF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Should extract nibble {}", nibble_idx); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Should extract nibble {}", + nibble_idx + ); } } @@ -283,10 +326,15 @@ fn test_bextr_byte_extraction() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = (8 << 8) | (byte_idx * 8); // length=8, start=byte_idx*8 emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (value >> (byte_idx * 8)) & 0xFF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Should extract byte {}", byte_idx); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Should extract byte {}", + byte_idx + ); } } @@ -303,7 +351,11 @@ fn test_bextr_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAA, "EAX should contain extracted pattern"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAA, + "EAX should contain extracted pattern" + ); } #[test] @@ -320,10 +372,15 @@ fn test_bextr_single_bit_scan() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = (1 << 8) | bit_idx; // length=1, start=bit_idx emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = ((value >> bit_idx) & 1) as u64; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Should extract bit {}", bit_idx); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Should extract bit {}", + bit_idx + ); } } @@ -341,7 +398,11 @@ fn test_bextr_max_length_255() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX should contain all 32 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX should contain all 32 bits" + ); } #[test] @@ -358,8 +419,16 @@ fn test_bextr_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, (8 << 8) | 4, "ECX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + (8 << 8) | 4, + "ECX should be unchanged" + ); } #[test] @@ -377,7 +446,11 @@ fn test_bextr_zero_extension() { emu.run(None).unwrap(); // 32-bit operation should zero upper 32 bits of RAX - assert_eq!(emu.regs().rax, 0xFF, "RAX should be zero-extended (upper bits cleared)"); + assert_eq!( + emu.regs().rax, + 0xFF, + "RAX should be zero-extended (upper bits cleared)" + ); } #[test] @@ -394,7 +467,11 @@ fn test_bextr_mask_creation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFF, "EAX should contain 16-bit mask"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFF, + "EAX should contain 16-bit mask" + ); } #[test] @@ -410,7 +487,11 @@ fn test_bextr_field_alignment() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xDEAD, "EAX should contain upper 16 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xDEAD, + "EAX should contain upper 16 bits" + ); } #[test] @@ -427,7 +508,11 @@ fn test_bextr_unaligned_field() { emu.run(None).unwrap(); let expected = (0xFFFFFFFF >> 7) & 0x3FF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "EAX should contain 10 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "EAX should contain 10 bits" + ); } #[test] @@ -443,5 +528,9 @@ fn test_bextr_64bit_full_extraction() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX should contain all 64 bits"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX should contain all 64 bits" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsi.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsi.rs index 93cd1f77..151a59c2 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsi.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsi.rs @@ -23,7 +23,11 @@ fn test_blsi_eax_ebx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0001, "EAX should contain isolated bit 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0001, + "EAX should contain isolated bit 0" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); assert!(emu.flags().f_cf, "CF should be set (source is non-zero)"); } @@ -41,7 +45,11 @@ fn test_blsi_eax_ebx_bit_31() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX should contain isolated bit 31"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX should contain isolated bit 31" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -58,7 +66,11 @@ fn test_blsi_rax_rbx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0b0000_0001, "RAX should contain isolated bit 0"); + assert_eq!( + emu.regs().rax, + 0b0000_0001, + "RAX should contain isolated bit 0" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -75,7 +87,11 @@ fn test_blsi_rax_rbx_bit_63() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000_0000_0000_0000, "RAX should contain isolated bit 63"); + assert_eq!( + emu.regs().rax, + 0x8000_0000_0000_0000, + "RAX should contain isolated bit 63" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -110,7 +126,11 @@ fn test_blsi_multiple_bits_isolates_lowest() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_1000, "EAX should contain only bit 3 (lowest)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_1000, + "EAX should contain only bit 3 (lowest)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -144,7 +164,11 @@ fn test_blsi_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b10, "EAX should contain bit 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b10, + "EAX should contain bit 1" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -176,9 +200,14 @@ fn test_blsi_single_bit_positions() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1u64 << bit_pos, "EAX should contain isolated bit {}", bit_pos); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1u64 << bit_pos, + "EAX should contain isolated bit {}", + bit_pos + ); assert!(!emu.flags().f_zf, "ZF should be clear for bit {}", bit_pos); } } @@ -196,7 +225,11 @@ fn test_blsi_with_extended_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0000_1000, "R8D should contain bit 3"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0000_1000, + "R8D should contain bit 3" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -213,7 +246,11 @@ fn test_blsi_r15() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x1_0000_0000, "R15 should contain isolated bit 32"); + assert_eq!( + emu.regs().r15, + 0x1_0000_0000, + "R15 should contain isolated bit 32" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -230,7 +267,11 @@ fn test_blsi_mem32() { emu.maps.write_dword(DATA_ADDR, 0xFFFFF000); // bits 12-31 set emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x1000, "EAX should contain isolated bit 12"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x1000, + "EAX should contain isolated bit 12" + ); } #[test] @@ -246,7 +287,11 @@ fn test_blsi_mem64() { emu.maps.write_qword(DATA_ADDR, 0x100_0000_0000); // bit 40 set emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x100_0000_0000, "RAX should contain isolated bit 40"); + assert_eq!( + emu.regs().rax, + 0x100_0000_0000, + "RAX should contain isolated bit 40" + ); } #[test] @@ -262,7 +307,11 @@ fn test_blsi_trailing_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x1000, "EAX should contain bit 12"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x1000, + "EAX should contain bit 12" + ); } #[test] @@ -278,7 +327,11 @@ fn test_blsi_sparse_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x1000, "EAX should contain bit 12 (lowest)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x1000, + "EAX should contain bit 12 (lowest)" + ); } #[test] @@ -294,7 +347,11 @@ fn test_blsi_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -312,7 +369,11 @@ fn test_blsi_vs_and_neg() { emu.run(None).unwrap(); let expected = value & value.wrapping_neg(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "BLSI should equal src & -src"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "BLSI should equal src & -src" + ); } #[test] @@ -327,9 +388,15 @@ fn test_blsi_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << i; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1u64 << i, "BLSI(2^{}) should equal 2^{}", i, i); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1u64 << i, + "BLSI(2^{}) should equal 2^{}", + i, + i + ); } } @@ -346,7 +413,11 @@ fn test_blsi_consecutive_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00010000, "EAX should contain bit 16 (lowest of consecutive)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00010000, + "EAX should contain bit 16 (lowest of consecutive)" + ); } #[test] @@ -362,7 +433,11 @@ fn test_blsi_sign_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX should contain bit 31"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX should contain bit 31" + ); } #[test] @@ -380,9 +455,14 @@ fn test_blsi_iterative_isolation() { for &expected_bit in &expected_bits { emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1u64 << expected_bit, "Should isolate bit {}", expected_bit); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1u64 << expected_bit, + "Should isolate bit {}", + expected_bit + ); // Remove lowest bit for next iteration value = value & (value - 1); @@ -402,7 +482,11 @@ fn test_blsi_high_bits_64() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0800_0000_0000_0000, "RAX should contain isolated bit 59"); + assert_eq!( + emu.regs().rax, + 0x0800_0000_0000_0000, + "RAX should contain isolated bit 59" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsmsk.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsmsk.rs index 31ec6d09..41697f1d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsmsk.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsmsk.rs @@ -23,7 +23,11 @@ fn test_blsmsk_eax_ebx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0001, "EAX should contain mask up to bit 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0001, + "EAX should contain mask up to bit 0" + ); assert!(!emu.flags().f_zf, "ZF should be clear (source is non-zero)"); assert!(!emu.flags().f_cf, "CF should be clear (source is non-zero)"); } @@ -41,7 +45,11 @@ fn test_blsmsk_eax_ebx_bit_3() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_1111, "EAX should contain mask up to bit 3 (bits 0-3)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_1111, + "EAX should contain mask up to bit 3 (bits 0-3)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -59,7 +67,11 @@ fn test_blsmsk_eax_ebx_bit_31() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX should contain mask up to bit 31 (all bits)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX should contain mask up to bit 31 (all bits)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -76,7 +88,11 @@ fn test_blsmsk_rax_rbx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0b0000_0001, "RAX should contain mask up to bit 0"); + assert_eq!( + emu.regs().rax, + 0b0000_0001, + "RAX should contain mask up to bit 0" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -93,7 +109,11 @@ fn test_blsmsk_rax_rbx_bit_63() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFF_FFFF_FFFF_FFFF, "RAX should contain mask up to bit 63 (all bits)"); + assert_eq!( + emu.regs().rax, + 0xFFFF_FFFF_FFFF_FFFF, + "RAX should contain mask up to bit 63 (all bits)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -110,7 +130,11 @@ fn test_blsmsk_zero_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX should be all ones (src ^ (src-1) = 0 ^ -1)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX should be all ones (src ^ (src-1) = 0 ^ -1)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (BLSMSK clears ZF)"); assert!(emu.flags().f_cf, "CF should be set (source is zero)"); } @@ -128,7 +152,11 @@ fn test_blsmsk_multiple_bits_uses_lowest() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_1111, "EAX should contain mask up to bit 3 (lowest)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_1111, + "EAX should contain mask up to bit 3 (lowest)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -145,7 +173,11 @@ fn test_blsmsk_all_bits_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain mask up to bit 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain mask up to bit 0" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -162,7 +194,11 @@ fn test_blsmsk_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b11, "EAX should contain mask up to bit 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b11, + "EAX should contain mask up to bit 1" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -179,7 +215,11 @@ fn test_blsmsk_alternating_pattern_inverted() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain mask up to bit 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain mask up to bit 0" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -194,10 +234,15 @@ fn test_blsmsk_single_bit_positions() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (1u64 << (bit_pos + 1)) - 1; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "EAX should contain mask for bit {}", bit_pos); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "EAX should contain mask for bit {}", + bit_pos + ); assert!(!emu.flags().f_zf, "ZF should be clear for bit {}", bit_pos); } } @@ -215,7 +260,11 @@ fn test_blsmsk_with_extended_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0001_1111, "R8D should contain mask up to bit 4"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0001_1111, + "R8D should contain mask up to bit 4" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -233,7 +282,11 @@ fn test_blsmsk_r15() { emu.run(None).unwrap(); let expected = (1u64 << 33) - 1; - assert_eq!(emu.regs().r15, expected, "R15 should contain mask up to bit 32"); + assert_eq!( + emu.regs().r15, + expected, + "R15 should contain mask up to bit 32" + ); } #[test] @@ -250,7 +303,11 @@ fn test_blsmsk_mem32() { emu.run(None).unwrap(); let expected = (1u32 << 13) - 1; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "EAX should contain mask up to bit 12"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "EAX should contain mask up to bit 12" + ); } #[test] @@ -267,7 +324,11 @@ fn test_blsmsk_mem64() { emu.run(None).unwrap(); let expected = (1u64 << 41) - 1; - assert_eq!(emu.regs().rax, expected, "RAX should contain mask up to bit 40"); + assert_eq!( + emu.regs().rax, + expected, + "RAX should contain mask up to bit 40" + ); } #[test] @@ -284,7 +345,11 @@ fn test_blsmsk_trailing_zeros() { emu.run(None).unwrap(); let expected = (1u32 << 13) - 1; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "EAX should contain 13-bit mask"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "EAX should contain 13-bit mask" + ); } #[test] @@ -301,7 +366,11 @@ fn test_blsmsk_sparse_pattern() { emu.run(None).unwrap(); let expected = (1u32 << 13) - 1; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "EAX should contain mask up to bit 12 (lowest)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "EAX should contain mask up to bit 12 (lowest)" + ); } #[test] @@ -317,7 +386,11 @@ fn test_blsmsk_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -335,7 +408,11 @@ fn test_blsmsk_vs_xor_sub1() { emu.run(None).unwrap(); let expected = value ^ (value.wrapping_sub(1)); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "BLSMSK should equal src ^ (src-1)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "BLSMSK should equal src ^ (src-1)" + ); } #[test] @@ -350,10 +427,16 @@ fn test_blsmsk_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << i; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (1u64 << (i + 1)) - 1; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "BLSMSK(2^{}) should create {}-bit mask", i, i + 1); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "BLSMSK(2^{}) should create {}-bit mask", + i, + i + 1 + ); } } @@ -371,7 +454,11 @@ fn test_blsmsk_consecutive_bits() { emu.run(None).unwrap(); let expected = (1u32 << 17) - 1; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "EAX should contain mask up to bit 16"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "EAX should contain mask up to bit 16" + ); } #[test] @@ -387,7 +474,11 @@ fn test_blsmsk_sign_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX should contain all bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX should contain all bits" + ); } #[test] @@ -412,9 +503,15 @@ fn test_blsmsk_creates_bit_masks() { ]; emu.regs_mut().rbx = input; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "BLSMSK(0x{:08X}) should be 0x{:08X}", input, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "BLSMSK(0x{:08X}) should be 0x{:08X}", + input, + expected + ); } } @@ -449,7 +546,11 @@ fn test_blsmsk_mixed_high_low() { emu.run(None).unwrap(); let expected = (1u64 << 9) - 1; - assert_eq!(emu.regs().rax, expected, "RAX should contain 9-bit mask (up to bit 8)"); + assert_eq!( + emu.regs().rax, + expected, + "RAX should contain 9-bit mask (up to bit 8)" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsr.rs index 46f2fa01..54aed9a7 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi1/blsr.rs @@ -23,9 +23,16 @@ fn test_blsr_eax_ebx_bit_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0000, "EAX should be zero (bit 0 reset)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0000, + "EAX should be zero (bit 0 reset)" + ); assert!(emu.flags().f_zf, "ZF should be set (result is zero)"); - assert!(!emu.flags().f_cf, "CF should be clear (source was non-zero)"); + assert!( + !emu.flags().f_cf, + "CF should be clear (source was non-zero)" + ); } #[test] @@ -41,7 +48,11 @@ fn test_blsr_eax_ebx_bit_3() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0000, "EAX should be zero"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0000, + "EAX should be zero" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -58,7 +69,11 @@ fn test_blsr_eax_ebx_multiple_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b1010_0000, "EAX should have bit 3 reset (bits 5,7 remain)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b1010_0000, + "EAX should have bit 3 reset (bits 5,7 remain)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (result is non-zero)"); } @@ -75,7 +90,11 @@ fn test_blsr_eax_ebx_bit_31() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX should be zero"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX should be zero" + ); assert!(emu.flags().f_zf, "ZF should be set"); } @@ -126,7 +145,11 @@ fn test_blsr_zero_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (0 & -1 = 0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (0 & -1 = 0)" + ); assert!(emu.flags().f_zf, "ZF should be set (result is zero)"); assert!(emu.flags().f_cf, "CF should be set (source was zero)"); } @@ -144,7 +167,11 @@ fn test_blsr_all_bits_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFE, "EAX should have bit 0 reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFE, + "EAX should have bit 0 reset" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -161,7 +188,11 @@ fn test_blsr_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAA8, "EAX should have bit 1 reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAAAAA8, + "EAX should have bit 1 reset" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -178,7 +209,11 @@ fn test_blsr_alternating_pattern_inverted() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x55555554, "EAX should have bit 0 reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x55555554, + "EAX should have bit 0 reset" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -193,9 +228,14 @@ fn test_blsr_single_bit_positions() { ]; emu.regs_mut().rbx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero for single bit {}", bit_pos); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero for single bit {}", + bit_pos + ); assert!(emu.flags().f_zf, "ZF should be set for bit {}", bit_pos); } } @@ -213,7 +253,11 @@ fn test_blsr_with_extended_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0b0001_0000, "R8D should have bit 3 reset (bit 4 remains)"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0b0001_0000, + "R8D should have bit 3 reset (bit 4 remains)" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -230,7 +274,11 @@ fn test_blsr_r15() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x1_0000_0000, "R15 should have bit 0 reset (bit 32 remains)"); + assert_eq!( + emu.regs().r15, + 0x1_0000_0000, + "R15 should have bit 0 reset (bit 32 remains)" + ); } #[test] @@ -246,7 +294,11 @@ fn test_blsr_mem32() { emu.maps.write_dword(DATA_ADDR, 0xFFFFF000); // bits 12-31 set emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFE000, "EAX should have bit 12 reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFE000, + "EAX should have bit 12 reset" + ); } #[test] @@ -262,7 +314,11 @@ fn test_blsr_mem64() { emu.maps.write_qword(DATA_ADDR, 0x100_0000_0001); // bits 0 and 40 set emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x100_0000_0000, "RAX should have bit 0 reset (bit 40 remains)"); + assert_eq!( + emu.regs().rax, + 0x100_0000_0000, + "RAX should have bit 0 reset (bit 40 remains)" + ); } #[test] @@ -278,7 +334,11 @@ fn test_blsr_trailing_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFE000, "EAX should have bit 12 reset"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFE000, + "EAX should have bit 12 reset" + ); } #[test] @@ -294,7 +354,11 @@ fn test_blsr_sparse_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX should have bit 12 reset (bit 31 remains)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX should have bit 12 reset (bit 31 remains)" + ); } #[test] @@ -310,7 +374,11 @@ fn test_blsr_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); } #[test] @@ -328,7 +396,11 @@ fn test_blsr_vs_and_sub1() { emu.run(None).unwrap(); let expected = value & (value.wrapping_sub(1)); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "BLSR should equal src & (src-1)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "BLSR should equal src & (src-1)" + ); } #[test] @@ -343,9 +415,14 @@ fn test_blsr_power_of_two() { ]; emu.regs_mut().rbx = 1u64 << i; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "BLSR(2^{}) should be zero", i); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "BLSR(2^{}) should be zero", + i + ); assert!(emu.flags().f_zf, "ZF should be set for 2^{}", i); } } @@ -363,7 +440,11 @@ fn test_blsr_consecutive_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00FE0000, "EAX should have bit 16 reset (bits 17-23 remain)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00FE0000, + "EAX should have bit 16 reset (bits 17-23 remain)" + ); } #[test] @@ -398,9 +479,13 @@ fn test_blsr_iterative_clearing() { for &expected in &expected_values { emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Should progressively clear bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Should progressively clear bits" + ); value = emu.regs().rax; } } @@ -435,7 +520,11 @@ fn test_blsr_mixed_high_low() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000_0000_0000_0000, "RAX should have bit 8 reset (bit 63 remains)"); + assert_eq!( + emu.regs().rax, + 0x8000_0000_0000_0000, + "RAX should have bit 8 reset (bit 63 remains)" + ); } #[test] @@ -455,11 +544,15 @@ fn test_blsr_count_set_bits() { count += 1; emu.regs_mut().rbx = value; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); value = emu.regs().rax & 0xFFFFFFFF; } - assert_eq!(count, 0x12345678u32.count_ones(), "Should count all set bits"); + assert_eq!( + count, + 0x12345678u32.count_ones(), + "Should count all set bits" + ); } #[test] @@ -507,7 +600,10 @@ fn test_blsr_complement_of_blsi() { // BLSR | BLSI should equal original value let combined = (emu_blsr.regs().rax | emu_blsi.regs().rax) & 0xFFFFFFFF; - assert_eq!(combined, value, "BLSR | BLSI should reconstruct original value"); + assert_eq!( + combined, value, + "BLSR | BLSI should reconstruct original value" + ); } #[test] @@ -523,6 +619,10 @@ fn test_blsr_two_bits_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0100, "EAX should have bit 0 reset (bit 2 remains)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0100, + "EAX should have bit 0 reset (bit 2 remains)" + ); assert!(!emu.flags().f_zf, "ZF should be clear (result is non-zero)"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/bzhi.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/bzhi.rs index cd23ebd6..9ee54027 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/bzhi.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/bzhi.rs @@ -24,7 +24,11 @@ fn test_bzhi_eax_ebx_ecx_index_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (all bits masked)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (all bits masked)" + ); assert!(emu.flags().f_zf, "ZF should be set (result is zero)"); assert!(!emu.flags().f_cf, "CF should be clear (index < 32)"); } @@ -43,7 +47,11 @@ fn test_bzhi_eax_ebx_ecx_index_8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78, "EAX should contain lower 8 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78, + "EAX should contain lower 8 bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear (result is non-zero)"); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -62,7 +70,11 @@ fn test_bzhi_eax_ebx_ecx_index_16() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x5678, "EAX should contain lower 16 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x5678, + "EAX should contain lower 16 bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -80,7 +92,11 @@ fn test_bzhi_eax_ebx_ecx_index_32() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should contain all bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should contain all bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); assert!(emu.flags().f_cf, "CF should be set (index >= 32)"); } @@ -99,7 +115,11 @@ fn test_bzhi_eax_ebx_ecx_index_beyond() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should contain all bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should contain all bits" + ); assert!(emu.flags().f_cf, "CF should be set (index >= 32)"); } @@ -135,7 +155,11 @@ fn test_bzhi_rax_rbx_rcx_index_32() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x9ABCDEF0, "RAX should contain lower 32 bits"); + assert_eq!( + emu.regs().rax, + 0x9ABCDEF0, + "RAX should contain lower 32 bits" + ); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -153,7 +177,11 @@ fn test_bzhi_rax_rbx_rcx_index_64() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX should contain all bits"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX should contain all bits" + ); assert!(emu.flags().f_cf, "CF should be set (index >= 64)"); } @@ -190,7 +218,11 @@ fn test_bzhi_with_extended_registers() { emu.run(None).unwrap(); let expected = 0xABCDEF01 & ((1u32 << 12) - 1); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, expected as u64, "R8D should contain lower 12 bits"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + expected as u64, + "R8D should contain lower 12 bits" + ); } #[test] @@ -199,7 +231,8 @@ fn test_bzhi_mem32() { let mut emu = emu64(); // BZHI EAX, [mem], ECX let code = [ - 0xc4, 0xe2, 0x70, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // BZHI EAX, [DATA_ADDR], ECX + 0xc4, 0xe2, 0x70, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // BZHI EAX, [DATA_ADDR], ECX 0xf4, ]; emu.regs_mut().rcx = 8; // index 8 @@ -207,7 +240,11 @@ fn test_bzhi_mem32() { emu.maps.write_dword(DATA_ADDR, 0xAABBCCDD); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xDD, "EAX should contain lower 8 bits from memory"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xDD, + "EAX should contain lower 8 bits from memory" + ); } #[test] @@ -216,7 +253,8 @@ fn test_bzhi_mem64() { let mut emu = emu64(); // BZHI RAX, [mem], RCX let code = [ - 0xc4, 0xe2, 0xf0, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // BZHI RAX, [DATA_ADDR], RCX + 0xc4, 0xe2, 0xf0, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // BZHI RAX, [DATA_ADDR], RCX 0xf4, ]; emu.regs_mut().rcx = 16; // index 16 @@ -225,7 +263,11 @@ fn test_bzhi_mem64() { emu.run(None).unwrap(); let expected = 0x0123456789ABCDEF & ((1u64 << 16) - 1); - assert_eq!(emu.regs().rax, expected, "RAX should contain lower 16 bits from memory"); + assert_eq!( + emu.regs().rax, + expected, + "RAX should contain lower 16 bits from memory" + ); } #[test] @@ -241,14 +283,19 @@ fn test_bzhi_mask_creation() { emu.regs_mut().rbx = 0xFFFFFFFF; emu.regs_mut().rcx = index; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = if index >= 32 { 0xFFFFFFFF } else { ((1u64 << index) - 1) & 0xFFFFFFFF }; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "Should create {}-bit mask", index); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "Should create {}-bit mask", + index + ); } } @@ -265,7 +312,11 @@ fn test_bzhi_nibble_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x8, "EAX should contain lower nibble"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x8, + "EAX should contain lower nibble" + ); } #[test] @@ -282,7 +333,11 @@ fn test_bzhi_preserves_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 16, "ECX should be unchanged"); } @@ -299,7 +354,11 @@ fn test_bzhi_index_modulo_behavior() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (index wraps to 0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (index wraps to 0)" + ); } #[test] @@ -316,7 +375,11 @@ fn test_bzhi_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAA, "EAX should contain lower 16 bits of pattern"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAA, + "EAX should contain lower 16 bits of pattern" + ); } #[test] @@ -332,7 +395,11 @@ fn test_bzhi_single_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "EAX should contain only bit 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "EAX should contain only bit 0" + ); } #[test] @@ -349,7 +416,11 @@ fn test_bzhi_sparse_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x1001, "EAX should contain bits 0 and 12 only"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x1001, + "EAX should contain bits 0 and 12 only" + ); } #[test] @@ -372,9 +443,16 @@ fn test_bzhi_field_extraction() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = index; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "BZHI(0x{:X}, {}) should be 0x{:X}", value, index, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "BZHI(0x{:X}, {}) should be 0x{:X}", + value, + index, + expected + ); } } @@ -414,7 +492,7 @@ fn test_bzhi_cf_boundary_32bit() { emu.regs_mut().rbx = 0xFFFFFFFF; emu.regs_mut().rcx = index; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); if expect_cf { assert!(emu.flags().f_cf, "CF should be set for index {}", index); @@ -442,7 +520,7 @@ fn test_bzhi_cf_boundary_64bit() { emu.regs_mut().rbx = 0xFFFFFFFFFFFFFFFF; emu.regs_mut().rcx = index; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); if expect_cf { assert!(emu.flags().f_cf, "CF should be set for index {}", index); @@ -467,5 +545,9 @@ fn test_bzhi_combines_with_shifts() { emu.run(None).unwrap(); let expected = (0x12345678 >> 8) & 0xFFFF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected as u64, "Should extract bits 8-23"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected as u64, + "Should extract bits 8-23" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pdep.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pdep.rs index 43556dd8..7cd2bc51 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pdep.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pdep.rs @@ -24,7 +24,11 @@ fn test_pdep_eax_ebx_ecx_all_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should equal source (identity with full mask)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should equal source (identity with full mask)" + ); } #[test] @@ -41,7 +45,11 @@ fn test_pdep_eax_ebx_ecx_zero_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (no deposit positions)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (no deposit positions)" + ); } #[test] @@ -58,7 +66,11 @@ fn test_pdep_eax_ebx_ecx_single_bit_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_1000, "EAX should have bit 3 set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_1000, + "EAX should have bit 3 set" + ); } #[test] @@ -75,7 +87,11 @@ fn test_pdep_eax_ebx_ecx_alternating_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x55555555, "EAX should have alternating pattern"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x55555555, + "EAX should have alternating pattern" + ); } #[test] @@ -91,7 +107,11 @@ fn test_pdep_eax_ebx_ecx_low_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0F00, "EAX should have bits 8-11 set"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0F00, + "EAX should have bits 8-11 set" + ); } #[test] @@ -108,7 +128,11 @@ fn test_pdep_rax_rbx_rcx_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFF00000000000000, "RAX should have high byte set"); + assert_eq!( + emu.regs().rax, + 0xFF00000000000000, + "RAX should have high byte set" + ); } #[test] @@ -125,7 +149,11 @@ fn test_pdep_sparse_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80001001, "EAX should have bits at mask positions"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80001001, + "EAX should have bits at mask positions" + ); } #[test] @@ -142,7 +170,11 @@ fn test_pdep_with_extended_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0x00FF0000, "R8D should have bits 16-23 set"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0x00FF0000, + "R8D should have bits 16-23 set" + ); } #[test] @@ -151,7 +183,8 @@ fn test_pdep_mem32() { let mut emu = emu64(); // PDEP EAX, EBX, [mem] let code = [ - 0xc4, 0xe2, 0x63, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // PDEP EAX, EBX, [DATA_ADDR] + 0xc4, 0xe2, 0x63, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // PDEP EAX, EBX, [DATA_ADDR] 0xf4, ]; emu.regs_mut().rbx = 0xF; @@ -159,7 +192,11 @@ fn test_pdep_mem32() { emu.maps.write_dword(DATA_ADDR, 0x000F0000); // mask bits 16-19 emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x000F0000, "EAX should have bits deposited from memory mask"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x000F0000, + "EAX should have bits deposited from memory mask" + ); } #[test] @@ -168,7 +205,8 @@ fn test_pdep_mem64() { let mut emu = emu64(); // PDEP RAX, RBX, [mem] let code = [ - 0xc4, 0xe2, 0xe3, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // PDEP RAX, RBX, [DATA_ADDR] + 0xc4, 0xe2, 0xe3, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // PDEP RAX, RBX, [DATA_ADDR] 0xf4, ]; emu.regs_mut().rbx = 0xFF; @@ -176,7 +214,11 @@ fn test_pdep_mem64() { emu.maps.write_qword(DATA_ADDR, 0x00FF000000000000); // mask bits 48-55 emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00FF000000000000, "RAX should have bits deposited from memory mask"); + assert_eq!( + emu.regs().rax, + 0x00FF000000000000, + "RAX should have bits deposited from memory mask" + ); } #[test] @@ -193,8 +235,16 @@ fn test_pdep_preserves_sources() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0xAAAAAAAA, "ECX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0xAAAAAAAA, + "ECX should be unchanged" + ); } #[test] @@ -216,9 +266,16 @@ fn test_pdep_sequential_deposits() { emu.regs_mut().rbx = src; emu.regs_mut().rcx = mask; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "PDEP(0x{:X}, 0x{:X}) should be 0x{:X}", src, mask, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "PDEP(0x{:X}, 0x{:X}) should be 0x{:X}", + src, + mask, + expected + ); } } @@ -235,7 +292,11 @@ fn test_pdep_extract_nibbles() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0A0B0C0D, "Should deposit nibbles to alternating positions"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0A0B0C0D, + "Should deposit nibbles to alternating positions" + ); } #[test] @@ -251,7 +312,11 @@ fn test_pdep_bit_scatter() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x01010101, "Should scatter bits across byte positions"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x01010101, + "Should scatter bits across byte positions" + ); } #[test] @@ -266,9 +331,14 @@ fn test_pdep_power_of_two_masks() { emu.regs_mut().rbx = 1; // single bit emu.regs_mut().rcx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1u64 << bit_pos, "Should deposit to bit {}", bit_pos); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1u64 << bit_pos, + "Should deposit to bit {}", + bit_pos + ); } } @@ -302,7 +372,11 @@ fn test_pdep_inverse_of_pext() { emu2.run(None).unwrap(); let masked_original = value & mask; - assert_eq!(emu2.regs().rax & 0xFFFFFFFF, masked_original, "PDEP(PEXT(x, mask), mask) should equal x & mask"); + assert_eq!( + emu2.regs().rax & 0xFFFFFFFF, + masked_original, + "PDEP(PEXT(x, mask), mask) should equal x & mask" + ); } #[test] @@ -318,7 +392,11 @@ fn test_pdep_excess_source_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0000000F, "Should use only first 4 source bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0000000F, + "Should use only first 4 source bits" + ); } #[test] @@ -334,7 +412,11 @@ fn test_pdep_byte_expansion() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x000000FF, "Should expand byte to separated positions"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x000000FF, + "Should expand byte to separated positions" + ); } #[test] @@ -350,7 +432,11 @@ fn test_pdep_zero_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "Zero source should produce zero"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "Zero source should produce zero" + ); } #[test] @@ -366,7 +452,11 @@ fn test_pdep_64bit_high_positions() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFF000000000000, "Should deposit to high positions"); + assert_eq!( + emu.regs().rax, + 0xFFFF000000000000, + "Should deposit to high positions" + ); } #[test] @@ -374,9 +464,9 @@ fn test_pdep_pattern_generation() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (0x1, 0x11111111, 0x00000001), // deposit single bit - (0x3, 0x33333333, 0x00000003), // deposit two bits - (0xF, 0x0F0F0F0F, 0x0000000F), // deposit nibble + (0x1, 0x11111111, 0x00000001), // deposit single bit + (0x3, 0x33333333, 0x00000003), // deposit two bits + (0xF, 0x0F0F0F0F, 0x0000000F), // deposit nibble ]; for (src, mask, expected) in test_cases { @@ -387,9 +477,16 @@ fn test_pdep_pattern_generation() { emu.regs_mut().rbx = src; emu.regs_mut().rcx = mask; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "PDEP(0x{:X}, 0x{:X}) should be 0x{:X}", src, mask, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "PDEP(0x{:X}, 0x{:X}) should be 0x{:X}", + src, + mask, + expected + ); } } @@ -406,7 +503,11 @@ fn test_pdep_consecutive_mask_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00005678, "Consecutive mask preserves lower bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00005678, + "Consecutive mask preserves lower bits" + ); } #[test] @@ -422,5 +523,9 @@ fn test_pdep_field_packing() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0F0000F0, "Should pack bits into fields"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0F0000F0, + "Should pack bits into fields" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pext.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pext.rs index 6ea10b4b..fd5de74a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pext.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/bmi2/pext.rs @@ -24,7 +24,11 @@ fn test_pext_eax_ebx_ecx_all_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX should equal source (identity with full mask)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX should equal source (identity with full mask)" + ); } #[test] @@ -41,7 +45,11 @@ fn test_pext_eax_ebx_ecx_zero_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX should be zero (no bits extracted)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX should be zero (no bits extracted)" + ); } #[test] @@ -58,7 +66,11 @@ fn test_pext_eax_ebx_ecx_single_bit_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b0000_0001, "EAX should have extracted bit at position 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b0000_0001, + "EAX should have extracted bit at position 0" + ); } #[test] @@ -75,7 +87,11 @@ fn test_pext_eax_ebx_ecx_alternating_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0000FFFF, "EAX should have 16 bits packed"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0000FFFF, + "EAX should have 16 bits packed" + ); } #[test] @@ -91,7 +107,11 @@ fn test_pext_eax_ebx_ecx_low_nibble() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x8, "EAX should contain extracted nibble"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x8, + "EAX should contain extracted nibble" + ); } #[test] @@ -108,7 +128,11 @@ fn test_pext_rax_rbx_rcx_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFF, "RAX should have extracted high byte at low position"); + assert_eq!( + emu.regs().rax, + 0xFF, + "RAX should have extracted high byte at low position" + ); } #[test] @@ -125,7 +149,11 @@ fn test_pext_sparse_mask() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0b111, "EAX should have 3 bits packed at low positions"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0b111, + "EAX should have 3 bits packed at low positions" + ); } #[test] @@ -142,7 +170,11 @@ fn test_pext_with_extended_registers() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFFFFFFFF, 0xFF, "R8D should have extracted byte"); + assert_eq!( + emu.regs().r8 & 0xFFFFFFFF, + 0xFF, + "R8D should have extracted byte" + ); } #[test] @@ -151,7 +183,8 @@ fn test_pext_mem32() { let mut emu = emu64(); // PEXT EAX, EBX, [mem] let code = [ - 0xc4, 0xe2, 0x62, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // PEXT EAX, EBX, [DATA_ADDR] + 0xc4, 0xe2, 0x62, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // PEXT EAX, EBX, [DATA_ADDR] 0xf4, ]; emu.regs_mut().rbx = 0x000F0000; @@ -159,7 +192,11 @@ fn test_pext_mem32() { emu.maps.write_dword(DATA_ADDR, 0x000F0000); // mask bits 16-19 emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xF, "EAX should have extracted nibble from memory mask"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xF, + "EAX should have extracted nibble from memory mask" + ); } #[test] @@ -168,7 +205,8 @@ fn test_pext_mem64() { let mut emu = emu64(); // PEXT RAX, RBX, [mem] let code = [ - 0xc4, 0xe2, 0xe2, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, 0x00, // PEXT RAX, RBX, [DATA_ADDR] + 0xc4, 0xe2, 0xe2, 0xf5, 0x04, 0x25, 0x00, 0x20, 0x00, + 0x00, // PEXT RAX, RBX, [DATA_ADDR] 0xf4, ]; emu.regs_mut().rbx = 0x00FF000000000000; @@ -176,7 +214,11 @@ fn test_pext_mem64() { emu.maps.write_qword(DATA_ADDR, 0x00FF000000000000); // mask bits 48-55 emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFF, "RAX should have extracted byte from memory mask"); + assert_eq!( + emu.regs().rax, + 0xFF, + "RAX should have extracted byte from memory mask" + ); } #[test] @@ -193,8 +235,16 @@ fn test_pext_preserves_sources() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX should be unchanged"); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0xAAAAAAAA, "ECX should be unchanged"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX should be unchanged" + ); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0xAAAAAAAA, + "ECX should be unchanged" + ); } #[test] @@ -216,9 +266,16 @@ fn test_pext_sequential_extracts() { emu.regs_mut().rbx = src; emu.regs_mut().rcx = mask; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "PEXT(0x{:X}, 0x{:X}) should be 0x{:X}", src, mask, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "PEXT(0x{:X}, 0x{:X}) should be 0x{:X}", + src, + mask, + expected + ); } } @@ -235,7 +292,11 @@ fn test_pext_extract_nibbles() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xDCBA, "Should extract alternating nibbles packed"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xDCBA, + "Should extract alternating nibbles packed" + ); } #[test] @@ -251,7 +312,11 @@ fn test_pext_bit_gather() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xF, "Should gather 4 scattered bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xF, + "Should gather 4 scattered bits" + ); } #[test] @@ -266,9 +331,13 @@ fn test_pext_power_of_two_masks() { emu.regs_mut().rbx = 1u64 << bit_pos; emu.regs_mut().rcx = 1u64 << bit_pos; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 1, "Should extract single bit to position 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 1, + "Should extract single bit to position 0" + ); } } @@ -308,7 +377,11 @@ fn test_pext_inverse_of_pdep() { } else { value & ((1u64 << bit_count) - 1) }; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "PEXT(PDEP(x, mask), mask) should recover deposited bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "PEXT(PDEP(x, mask), mask) should recover deposited bits" + ); } #[test] @@ -324,7 +397,11 @@ fn test_pext_byte_compaction() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0B0D, "Should compact separated bytes"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0B0D, + "Should compact separated bytes" + ); } #[test] @@ -340,7 +417,11 @@ fn test_pext_zero_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "Zero source should produce zero"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "Zero source should produce zero" + ); } #[test] @@ -356,7 +437,11 @@ fn test_pext_64bit_high_positions() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFF, "Should extract high bits to low positions"); + assert_eq!( + emu.regs().rax, + 0xFFFF, + "Should extract high bits to low positions" + ); } #[test] @@ -364,9 +449,9 @@ fn test_pext_pattern_extraction() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let test_cases = vec![ - (0x11111111, 0x11111111, 0x000000FF), // extract every 4th bit - (0x33333333, 0x33333333, 0x0000FFFF), // extract two bits per nibble - (0x0F0F0F0F, 0x0F0F0F0F, 0x0000FFFF), // extract nibbles + (0x11111111, 0x11111111, 0x000000FF), // extract every 4th bit + (0x33333333, 0x33333333, 0x0000FFFF), // extract two bits per nibble + (0x0F0F0F0F, 0x0F0F0F0F, 0x0000FFFF), // extract nibbles ]; for (src, mask, expected) in test_cases { @@ -377,9 +462,16 @@ fn test_pext_pattern_extraction() { emu.regs_mut().rbx = src; emu.regs_mut().rcx = mask; emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "PEXT(0x{:X}, 0x{:X}) should be 0x{:X}", src, mask, expected); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "PEXT(0x{:X}, 0x{:X}) should be 0x{:X}", + src, + mask, + expected + ); } } @@ -396,7 +488,11 @@ fn test_pext_consecutive_mask_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00005678, "Consecutive mask extracts lower bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00005678, + "Consecutive mask extracts lower bits" + ); } #[test] @@ -412,7 +508,11 @@ fn test_pext_field_unpacking() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFF, "Should unpack fields contiguously"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFF, + "Should unpack fields contiguously" + ); } #[test] @@ -428,7 +528,11 @@ fn test_pext_mask_population_count() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFF, "Result limited by mask popcount"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFF, + "Result limited by mask popcount" + ); } #[test] @@ -444,7 +548,11 @@ fn test_pext_interleaved_bytes() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xBBDD, "Should extract interleaved bytes"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xBBDD, + "Should extract interleaved bytes" + ); } #[test] @@ -461,7 +569,11 @@ fn test_pext_bit_reversal_aid() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFF, "Should extract all high nibbles"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFF, + "Should extract all high nibbles" + ); } #[test] @@ -476,8 +588,13 @@ fn test_pext_single_byte_from_dword() { emu.regs_mut().rbx = 0x03020100; emu.regs_mut().rcx = 0xFFu64 << (byte_idx * 8); emu.load_code_bytes(&code); - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rax & 0xFFFFFFFF, byte_idx as u64, "Should extract byte {}", byte_idx); + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + byte_idx as u64, + "Should extract byte {}", + byte_idx + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/mod.rs index e0bd39ec..f93cd5f5 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/mod.rs @@ -1,13 +1,13 @@ mod basic_logic; -mod bit_scanning; -mod bmi2; -mod shifts_arithmetic; -mod shifts_variable; mod basic_logic_xor; -mod bit_testing; -mod rotates_advanced; -mod shifts_double_precision; mod bit_counting_swap; +mod bit_scanning; +mod bit_testing; mod bmi1; +mod bmi2; +mod rotates_advanced; mod rotates_basic; +mod shifts_arithmetic; +mod shifts_double_precision; mod shifts_logical; +mod shifts_variable; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_advanced/rorx.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_advanced/rorx.rs index 1a80c964..c3742f3e 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_advanced/rorx.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_advanced/rorx.rs @@ -34,8 +34,16 @@ fn test_rorx_eax_ebx_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x81234567, "EAX: 0x12345678 RORX 4 = 0x81234567"); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX: source unchanged"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x81234567, + "EAX: 0x12345678 RORX 4 = 0x81234567" + ); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x12345678, + "EBX: source unchanged" + ); } #[test] @@ -48,13 +56,18 @@ fn test_rorx_eax_no_flags() { 0xf4, ]; emu.regs_mut().rbx = 0x12345678; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_PF | flags::F_AF | - flags::F_ZF | flags::F_SF | flags::F_OF); + emu.flags_mut().load( + 0x2 | flags::F_CF | flags::F_PF | flags::F_AF | flags::F_ZF | flags::F_SF | flags::F_OF, + ); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.flags().dump(), initial_flags, "Flags: RORX does not affect flags"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags: RORX does not affect flags" + ); } #[test] @@ -69,7 +82,11 @@ fn test_rorx_eax_rotate_8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: 0x12345678 RORX 8 = 0x78123456"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: 0x12345678 RORX 8 = 0x78123456" + ); } #[test] @@ -84,7 +101,11 @@ fn test_rorx_eax_rotate_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x091A2B3C, "EAX: 0x12345678 RORX 1 = 0x091A2B3C"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x091A2B3C, + "EAX: 0x12345678 RORX 1 = 0x091A2B3C" + ); } #[test] @@ -99,7 +120,11 @@ fn test_rorx_eax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: full rotation returns to original" + ); } #[test] @@ -115,7 +140,11 @@ fn test_rorx_eax_count_masked() { emu.run(None).unwrap(); // 0x28 & 0x1F = 8 - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: count masked to 8"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: count masked to 8" + ); } // ============================================================================ @@ -136,7 +165,11 @@ fn test_rorx_rax_rbx_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0123456789ABCDEF, "RAX: 0x123456789ABCDEF0 RORX 4"); + assert_eq!( + emu.regs().rax, + 0x0123456789ABCDEF, + "RAX: 0x123456789ABCDEF0 RORX 4" + ); assert_eq!(emu.regs().rbx, 0x123456789ABCDEF0, "RBX: source unchanged"); } @@ -150,12 +183,17 @@ fn test_rorx_rax_no_flags() { 0xf4, ]; emu.regs_mut().rbx = 0x123456789ABCDEF0; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.flags().dump(), initial_flags, "Flags: RORX does not affect flags"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags: RORX does not affect flags" + ); } #[test] @@ -200,7 +238,11 @@ fn test_rorx_rax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: full rotation returns to original" + ); } #[test] @@ -216,7 +258,11 @@ fn test_rorx_rax_count_masked() { emu.run(None).unwrap(); // 0x50 & 0x3F = 16 - assert_eq!(emu.regs().rax, 0xDEF0123456789ABC, "RAX: count masked to 16"); + assert_eq!( + emu.regs().rax, + 0xDEF0123456789ABC, + "RAX: count masked to 16" + ); } // ============================================================================ @@ -265,7 +311,12 @@ fn test_rorx_eax_dword_ptr() { let mut emu = emu64(); // RORX EAX, dword ptr [DATA_ADDR], imm8 let code = [ - 0xc4, 0xe3, 0x7b, 0xf0, 0x04, 0x25, // RORX EAX, dword ptr [DATA_ADDR], imm8 + 0xc4, + 0xe3, + 0x7b, + 0xf0, + 0x04, + 0x25, // RORX EAX, dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -279,7 +330,11 @@ fn test_rorx_eax_dword_ptr() { emu.run(None).unwrap(); let result = emu.maps.read_dword(DATA_ADDR).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: RORX from memory"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: RORX from memory" + ); assert_eq!(result, 0x12345678, "Memory: unchanged"); } @@ -289,7 +344,12 @@ fn test_rorx_rax_qword_ptr() { let mut emu = emu64(); // RORX RAX, qword ptr [DATA_ADDR], imm8 let code = [ - 0xc4, 0xe3, 0xfb, 0xf0, 0x04, 0x25, // RORX RAX, qword ptr [DATA_ADDR], imm8 + 0xc4, + 0xe3, + 0xfb, + 0xf0, + 0x04, + 0x25, // RORX RAX, qword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -325,7 +385,11 @@ fn test_rorx_separate_dest_source() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x81234567, "EAX: new rotated value"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x81234567, + "EAX: new rotated value" + ); assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x12345678, "EBX: preserved"); } @@ -372,7 +436,11 @@ fn test_rorx_byte_swap() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: bytes rotated"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: bytes rotated" + ); } #[test] @@ -387,7 +455,11 @@ fn test_rorx_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: all ones stay all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: all ones stay all ones" + ); } #[test] @@ -402,7 +474,11 @@ fn test_rorx_alternating_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x55555555, "EAX: alternating bits rotated"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x55555555, + "EAX: alternating bits rotated" + ); } #[test] @@ -417,5 +493,9 @@ fn test_rorx_nibble_swap() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x81234567, "EAX: nibbles rotated"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x81234567, + "EAX: nibbles rotated" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcl.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcl.rs index 10e6544b..f8f4c0f8 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcl.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcl.rs @@ -140,7 +140,11 @@ fn test_rcl_propagates_cf() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x01, "AL: CF propagated through rotations"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x01, + "AL: CF propagated through rotations" + ); assert!(!emu.flags().f_cf, "CF: cleared after second rotation"); } @@ -153,13 +157,18 @@ fn test_rcl_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -180,7 +189,11 @@ fn test_rcl_ax_1_cf_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8642, "AX: 0x4321 RCL 1 (CF=0) = 0x8642"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8642, + "AX: 0x4321 RCL 1 (CF=0) = 0x8642" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -198,7 +211,11 @@ fn test_rcl_ax_1_cf_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8643, "AX: 0x4321 RCL 1 (CF=1) = 0x8643"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8643, + "AX: 0x4321 RCL 1 (CF=1) = 0x8643" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -217,7 +234,11 @@ fn test_rcl_ax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: after 16 rotations of 17-bit value"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: after 16 rotations of 17-bit value" + ); } #[test] @@ -234,7 +255,11 @@ fn test_rcl_ax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1230, "AX: 0x0123 RCL 4 (CF=0) = 0x1230"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1230, + "AX: 0x0123 RCL 4 (CF=0) = 0x1230" + ); } // ============================================================================ @@ -255,7 +280,11 @@ fn test_rcl_eax_1_cf_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2468ACF0, "EAX: 0x12345678 RCL 1 (CF=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2468ACF0, + "EAX: 0x12345678 RCL 1 (CF=0)" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -273,7 +302,11 @@ fn test_rcl_eax_1_cf_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2468ACF1, "EAX: 0x12345678 RCL 1 (CF=1)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2468ACF1, + "EAX: 0x12345678 RCL 1 (CF=1)" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -292,7 +325,11 @@ fn test_rcl_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000001, "EAX: after full 33-bit rotation"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000001, + "EAX: after full 33-bit rotation" + ); } #[test] @@ -309,7 +346,11 @@ fn test_rcl_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x34567809, "EAX: 0x12345678 RCL 8 (CF=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x34567809, + "EAX: 0x12345678 RCL 8 (CF=0)" + ); } #[test] @@ -326,7 +367,11 @@ fn test_rcl_eax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000002, "EAX: 0x80000001 RCL 1 (CF=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000002, + "EAX: 0x80000001 RCL 1 (CF=0)" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -348,7 +393,11 @@ fn test_rcl_rax_1_cf_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x2468ACF13579BDE0, "RAX: 0x123456789ABCDEF0 RCL 1 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x2468ACF13579BDE0, + "RAX: 0x123456789ABCDEF0 RCL 1 (CF=0)" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -366,7 +415,11 @@ fn test_rcl_rax_1_cf_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x2468ACF13579BDE1, "RAX: 0x123456789ABCDEF0 RCL 1 (CF=1)"); + assert_eq!( + emu.regs().rax, + 0x2468ACF13579BDE1, + "RAX: 0x123456789ABCDEF0 RCL 1 (CF=1)" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -385,7 +438,11 @@ fn test_rcl_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC000000000000000, "RAX: bit rotated to MSB position"); + assert_eq!( + emu.regs().rax, + 0xC000000000000000, + "RAX: bit rotated to MSB position" + ); } #[test] @@ -402,7 +459,11 @@ fn test_rcl_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x56789ABCDEF0091A, "RAX: 0x123456789ABCDEF0 RCL 16 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x56789ABCDEF0091A, + "RAX: 0x123456789ABCDEF0 RCL 16 (CF=0)" + ); } #[test] @@ -419,7 +480,11 @@ fn test_rcl_rax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000002, "RAX: 0x8000000000000001 RCL 1 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000002, + "RAX: 0x8000000000000001 RCL 1 (CF=0)" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -459,7 +524,11 @@ fn test_rcl_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x2340, "R10W: 0x1234 RCL 4 (CF=0) = 0x2340"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x2340, + "R10W: 0x1234 RCL 4 (CF=0) = 0x2340" + ); } #[test] @@ -476,7 +545,11 @@ fn test_rcl_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0x34567809, "R12D: 0x12345678 RCL 8 (CF=0)"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0x34567809, + "R12D: 0x12345678 RCL 8 (CF=0)" + ); } #[test] @@ -493,7 +566,11 @@ fn test_rcl_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x02468ACF13579BDF, "R15: 0x0123456789ABCDEF RCL 1 (CF=1)"); + assert_eq!( + emu.regs().r15, + 0x02468ACF13579BDF, + "R15: 0x0123456789ABCDEF RCL 1 (CF=1)" + ); } // ============================================================================ @@ -506,7 +583,9 @@ fn test_rcl_byte_ptr_1() { let mut emu = emu64(); // RCL byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x14, 0x25, // RCL byte ptr [DATA_ADDR], 1 + 0xd0, + 0x14, + 0x25, // RCL byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -529,7 +608,10 @@ fn test_rcl_word_ptr_cl() { let mut emu = emu64(); // RCL word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x14, 0x25, // RCL word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x14, + 0x25, // RCL word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -553,7 +635,9 @@ fn test_rcl_dword_ptr_imm8() { let mut emu = emu64(); // RCL dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x14, 0x25, // RCL dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x14, + 0x25, // RCL dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -577,7 +661,10 @@ fn test_rcl_qword_ptr_cl() { let mut emu = emu64(); // RCL qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x14, 0x25, // RCL qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x14, + 0x25, // RCL qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -592,7 +679,10 @@ fn test_rcl_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x56789ABCDEF0091A, "Memory: 0x123456789ABCDEF0 RCL 16 (CF=0)"); + assert_eq!( + result, 0x56789ABCDEF0091A, + "Memory: 0x123456789ABCDEF0 RCL 16 (CF=0)" + ); } // ============================================================================ @@ -615,8 +705,16 @@ fn test_rcl_multi_precision_shift() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: low bits shifted"); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x2468ACF1, "EBX: high bits with CF from EAX"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: low bits shifted" + ); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x2468ACF1, + "EBX: high bits with CF from EAX" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcr.rs index 8d957583..6334d0f0 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rcr.rs @@ -140,7 +140,11 @@ fn test_rcr_propagates_cf() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x80, "AL: CF propagated through rotations"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x80, + "AL: CF propagated through rotations" + ); assert!(!emu.flags().f_cf, "CF: cleared after second rotation"); } @@ -153,13 +157,18 @@ fn test_rcr_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -180,7 +189,11 @@ fn test_rcr_ax_1_cf_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x2190, "AX: 0x4321 RCR 1 (CF=0) = 0x2190"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x2190, + "AX: 0x4321 RCR 1 (CF=0) = 0x2190" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -198,7 +211,11 @@ fn test_rcr_ax_1_cf_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xA190, "AX: 0x4320 RCR 1 (CF=1) = 0xA190"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xA190, + "AX: 0x4320 RCR 1 (CF=1) = 0xA190" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -217,7 +234,11 @@ fn test_rcr_ax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0001, "AX: after 16 rotations of 17-bit value"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0001, + "AX: after 16 rotations of 17-bit value" + ); } #[test] @@ -234,7 +255,11 @@ fn test_rcr_ax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8123, "AX: 0x1234 RCR 4 (CF=0) = 0x8123"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8123, + "AX: 0x1234 RCR 4 (CF=0) = 0x8123" + ); } // ============================================================================ @@ -255,7 +280,11 @@ fn test_rcr_eax_1_cf_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x091A2B3C, "EAX: 0x12345678 RCR 1 (CF=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x091A2B3C, + "EAX: 0x12345678 RCR 1 (CF=0)" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -273,7 +302,11 @@ fn test_rcr_eax_1_cf_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x891A2B3C, "EAX: 0x12345678 RCR 1 (CF=1)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x891A2B3C, + "EAX: 0x12345678 RCR 1 (CF=1)" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -292,7 +325,11 @@ fn test_rcr_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: after full 33-bit rotation"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: after full 33-bit rotation" + ); } #[test] @@ -309,7 +346,11 @@ fn test_rcr_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xF0123456, "EAX: 0x12345678 RCR 8 (CF=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xF0123456, + "EAX: 0x12345678 RCR 8 (CF=0)" + ); } #[test] @@ -326,7 +367,11 @@ fn test_rcr_eax_with_lsb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: 0x00000001 RCR 1 (CF=0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: 0x00000001 RCR 1 (CF=0)" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -348,7 +393,11 @@ fn test_rcr_rax_1_cf_clear() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x091A2B3C4D5E6F78, "RAX: 0x123456789ABCDEF0 RCR 1 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x091A2B3C4D5E6F78, + "RAX: 0x123456789ABCDEF0 RCR 1 (CF=0)" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -366,7 +415,11 @@ fn test_rcr_rax_1_cf_set() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x891A2B3C4D5E6F78, "RAX: 0x123456789ABCDEF0 RCR 1 (CF=1)"); + assert_eq!( + emu.regs().rax, + 0x891A2B3C4D5E6F78, + "RAX: 0x123456789ABCDEF0 RCR 1 (CF=1)" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -385,7 +438,11 @@ fn test_rcr_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000003, "RAX: bit rotated from MSB"); + assert_eq!( + emu.regs().rax, + 0x0000000000000003, + "RAX: bit rotated from MSB" + ); } #[test] @@ -402,7 +459,11 @@ fn test_rcr_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xBDE0123456789ABC, "RAX: 0x123456789ABCDEF0 RCR 16 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0xBDE0123456789ABC, + "RAX: 0x123456789ABCDEF0 RCR 16 (CF=0)" + ); } #[test] @@ -419,7 +480,11 @@ fn test_rcr_rax_with_lsb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000000, "RAX: 0x0000000000000001 RCR 1 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000000, + "RAX: 0x0000000000000001 RCR 1 (CF=0)" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -459,7 +524,11 @@ fn test_rcr_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x8123, "R10W: 0x1234 RCR 4 (CF=0) = 0x8123"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x8123, + "R10W: 0x1234 RCR 4 (CF=0) = 0x8123" + ); } #[test] @@ -476,7 +545,11 @@ fn test_rcr_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0xF0123456, "R12D: 0x12345678 RCR 8 (CF=0)"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0xF0123456, + "R12D: 0x12345678 RCR 8 (CF=0)" + ); } #[test] @@ -493,7 +566,11 @@ fn test_rcr_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0xFF6E5D4C3B2A1908, "R15: 0xFEDCBA9876543210 RCR 1 (CF=1)"); + assert_eq!( + emu.regs().r15, + 0xFF6E5D4C3B2A1908, + "R15: 0xFEDCBA9876543210 RCR 1 (CF=1)" + ); } // ============================================================================ @@ -506,7 +583,9 @@ fn test_rcr_byte_ptr_1() { let mut emu = emu64(); // RCR byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x1c, 0x25, // RCR byte ptr [DATA_ADDR], 1 + 0xd0, + 0x1c, + 0x25, // RCR byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -529,7 +608,10 @@ fn test_rcr_word_ptr_cl() { let mut emu = emu64(); // RCR word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x1c, 0x25, // RCR word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x1c, + 0x25, // RCR word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -553,7 +635,9 @@ fn test_rcr_dword_ptr_imm8() { let mut emu = emu64(); // RCR dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x1c, 0x25, // RCR dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x1c, + 0x25, // RCR dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -577,7 +661,10 @@ fn test_rcr_qword_ptr_cl() { let mut emu = emu64(); // RCR qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x1c, 0x25, // RCR qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x1c, + 0x25, // RCR qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -592,7 +679,10 @@ fn test_rcr_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0xBDE0123456789ABC, "Memory: 0x123456789ABCDEF0 RCR 16 (CF=0)"); + assert_eq!( + result, 0xBDE0123456789ABC, + "Memory: 0x123456789ABCDEF0 RCR 16 (CF=0)" + ); } // ============================================================================ @@ -615,8 +705,16 @@ fn test_rcr_multi_precision_shift() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x091A2B3C, "EBX: high bits shifted"); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: low bits with CF from EBX"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x091A2B3C, + "EBX: high bits shifted" + ); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: low bits with CF from EBX" + ); assert!(emu.flags().f_cf, "CF: LSB from EAX"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rol.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rol.rs index a9840b14..fa310268 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rol.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/rol.rs @@ -60,7 +60,11 @@ fn test_rol_al_1_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x03, "AL: 0x81 ROL 1 = 0x03 (MSB rotates to LSB)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x03, + "AL: 0x81 ROL 1 = 0x03 (MSB rotates to LSB)" + ); assert!(emu.flags().f_cf, "CF: receives MSB (was 1)"); } @@ -112,7 +116,11 @@ fn test_rol_full_rotation_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: full rotation returns to original" + ); } #[test] @@ -141,13 +149,18 @@ fn test_rol_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -185,7 +198,11 @@ fn test_rol_ax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: 0x0001 ROL 15 = 0x8000"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: 0x0001 ROL 15 = 0x8000" + ); assert!(!emu.flags().f_cf, "CF: last bit rotated was 0"); } @@ -218,7 +235,11 @@ fn test_rol_full_rotation_16bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: full rotation returns to original" + ); } // ============================================================================ @@ -238,7 +259,11 @@ fn test_rol_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2468ACF0, "EAX: 0x12345678 ROL 1 = 0x2468ACF0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2468ACF0, + "EAX: 0x12345678 ROL 1 = 0x2468ACF0" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -256,7 +281,11 @@ fn test_rol_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x00000001 ROL 31 = 0x80000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x00000001 ROL 31 = 0x80000000" + ); } #[test] @@ -272,7 +301,11 @@ fn test_rol_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x34567812, "EAX: 0x12345678 ROL 8 = 0x34567812"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x34567812, + "EAX: 0x12345678 ROL 8 = 0x34567812" + ); } #[test] @@ -288,7 +321,11 @@ fn test_rol_eax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000003, "EAX: 0x80000001 ROL 1 = 0x00000003"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000003, + "EAX: 0x80000001 ROL 1 = 0x00000003" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -306,7 +343,11 @@ fn test_rol_full_rotation_32bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: full rotation returns to original" + ); } // ============================================================================ @@ -326,7 +367,11 @@ fn test_rol_rax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x2468ACF13579BDE0, "RAX: 0x123456789ABCDEF0 ROL 1"); + assert_eq!( + emu.regs().rax, + 0x2468ACF13579BDE0, + "RAX: 0x123456789ABCDEF0 ROL 1" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -344,7 +389,11 @@ fn test_rol_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000000000000000, "RAX: 0x0000000000000001 ROL 63"); + assert_eq!( + emu.regs().rax, + 0x8000000000000000, + "RAX: 0x0000000000000001 ROL 63" + ); } #[test] @@ -360,7 +409,11 @@ fn test_rol_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x56789ABCDEF01234, "RAX: 0x123456789ABCDEF0 ROL 16"); + assert_eq!( + emu.regs().rax, + 0x56789ABCDEF01234, + "RAX: 0x123456789ABCDEF0 ROL 16" + ); } #[test] @@ -376,7 +429,11 @@ fn test_rol_rax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000003, "RAX: 0x8000000000000001 ROL 1"); + assert_eq!( + emu.regs().rax, + 0x0000000000000003, + "RAX: 0x8000000000000001 ROL 1" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -394,7 +451,11 @@ fn test_rol_full_rotation_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: full rotation returns to original" + ); } // ============================================================================ @@ -431,7 +492,11 @@ fn test_rol_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x2341, "R10W: 0x1234 ROL 4 = 0x2341"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x2341, + "R10W: 0x1234 ROL 4 = 0x2341" + ); } #[test] @@ -447,7 +512,11 @@ fn test_rol_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0x34567812, "R12D: 0x12345678 ROL 8 = 0x34567812"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0x34567812, + "R12D: 0x12345678 ROL 8 = 0x34567812" + ); } #[test] @@ -463,7 +532,11 @@ fn test_rol_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x02468ACF13579BDE, "R15: 0x0123456789ABCDEF ROL 1"); + assert_eq!( + emu.regs().r15, + 0x02468ACF13579BDE, + "R15: 0x0123456789ABCDEF ROL 1" + ); } // ============================================================================ @@ -476,7 +549,9 @@ fn test_rol_byte_ptr_1() { let mut emu = emu64(); // ROL byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x04, 0x25, // ROL byte ptr [DATA_ADDR], 1 + 0xd0, + 0x04, + 0x25, // ROL byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -498,7 +573,10 @@ fn test_rol_word_ptr_cl() { let mut emu = emu64(); // ROL word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x04, 0x25, // ROL word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x04, + 0x25, // ROL word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -521,7 +599,9 @@ fn test_rol_dword_ptr_imm8() { let mut emu = emu64(); // ROL dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x04, 0x25, // ROL dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x04, + 0x25, // ROL dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -544,7 +624,10 @@ fn test_rol_qword_ptr_cl() { let mut emu = emu64(); // ROL qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x04, 0x25, // ROL qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x04, + 0x25, // ROL qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -558,7 +641,10 @@ fn test_rol_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x56789ABCDEF01234, "Memory: 0x123456789ABCDEF0 ROL 16"); + assert_eq!( + result, 0x56789ABCDEF01234, + "Memory: 0x123456789ABCDEF0 ROL 16" + ); } // ============================================================================ @@ -594,7 +680,11 @@ fn test_rol_overflow_flag_1bit_same() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x40000000 ROL 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x40000000 ROL 1" + ); assert!(emu.flags().f_of, "OF: MSB changed from 0 to 1"); } @@ -611,7 +701,11 @@ fn test_rol_overflow_flag_1bit_different() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000001, "EAX: 0xC0000000 ROL 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000001, + "EAX: 0xC0000000 ROL 1" + ); assert!(!emu.flags().f_of, "OF: MSB stayed the same"); } @@ -628,7 +722,11 @@ fn test_rol_circular_buffer_indexing() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x91A2B3C0, "EAX: rotated by 3 bits"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x91A2B3C0, + "EAX: rotated by 3 bits" + ); } #[test] @@ -645,7 +743,11 @@ fn test_rol_chained_rotations() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x91A2B3C0, "EAX: three 1-bit rotations"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x91A2B3C0, + "EAX: three 1-bit rotations" + ); } #[test] @@ -660,7 +762,11 @@ fn test_rol_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: all ones stay all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: all ones stay all ones" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/ror.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/ror.rs index 54d17b17..876a79da 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/ror.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/rotates_basic/ror.rs @@ -59,7 +59,11 @@ fn test_ror_al_1_with_lsb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xA1, "AL: 0x43 ROR 1 = 0xA1 (LSB rotates to MSB)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xA1, + "AL: 0x43 ROR 1 = 0xA1 (LSB rotates to MSB)" + ); assert!(emu.flags().f_cf, "CF: receives LSB (was 1)"); } @@ -111,7 +115,11 @@ fn test_ror_full_rotation_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: full rotation returns to original" + ); } #[test] @@ -123,13 +131,18 @@ fn test_ror_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -167,7 +180,11 @@ fn test_ror_ax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0001, "AX: 0x8000 ROR 15 = 0x0001"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0001, + "AX: 0x8000 ROR 15 = 0x0001" + ); assert!(!emu.flags().f_cf, "CF: last bit rotated was 0"); } @@ -200,7 +217,11 @@ fn test_ror_full_rotation_16bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: full rotation returns to original" + ); } // ============================================================================ @@ -220,7 +241,11 @@ fn test_ror_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x091A2B3C, "EAX: 0x12345678 ROR 1 = 0x091A2B3C"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x091A2B3C, + "EAX: 0x12345678 ROR 1 = 0x091A2B3C" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -238,7 +263,11 @@ fn test_ror_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000001, "EAX: 0x80000000 ROR 31 = 0x00000001"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000001, + "EAX: 0x80000000 ROR 31 = 0x00000001" + ); } #[test] @@ -254,7 +283,11 @@ fn test_ror_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: 0x12345678 ROR 8 = 0x78123456"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: 0x12345678 ROR 8 = 0x78123456" + ); } #[test] @@ -270,7 +303,11 @@ fn test_ror_eax_with_lsb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x00000001 ROR 1 = 0x80000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x00000001 ROR 1 = 0x80000000" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -288,7 +325,11 @@ fn test_ror_full_rotation_32bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: full rotation returns to original" + ); } // ============================================================================ @@ -308,7 +349,11 @@ fn test_ror_rax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x091A2B3C4D5E6F78, "RAX: 0x123456789ABCDEF0 ROR 1"); + assert_eq!( + emu.regs().rax, + 0x091A2B3C4D5E6F78, + "RAX: 0x123456789ABCDEF0 ROR 1" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } @@ -326,7 +371,11 @@ fn test_ror_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "RAX: 0x8000000000000000 ROR 63"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "RAX: 0x8000000000000000 ROR 63" + ); } #[test] @@ -342,7 +391,11 @@ fn test_ror_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xDEF0123456789ABC, "RAX: 0x123456789ABCDEF0 ROR 16"); + assert_eq!( + emu.regs().rax, + 0xDEF0123456789ABC, + "RAX: 0x123456789ABCDEF0 ROR 16" + ); } #[test] @@ -358,7 +411,11 @@ fn test_ror_rax_with_lsb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000000000000000, "RAX: 0x0000000000000001 ROR 1"); + assert_eq!( + emu.regs().rax, + 0x8000000000000000, + "RAX: 0x0000000000000001 ROR 1" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -376,7 +433,11 @@ fn test_ror_full_rotation_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: full rotation returns to original" + ); } // ============================================================================ @@ -414,7 +475,11 @@ fn test_ror_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x4123, "R10W: 0x1234 ROR 4 = 0x4123"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x4123, + "R10W: 0x1234 ROR 4 = 0x4123" + ); } #[test] @@ -430,7 +495,11 @@ fn test_ror_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0x78123456, "R12D: 0x12345678 ROR 8 = 0x78123456"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0x78123456, + "R12D: 0x12345678 ROR 8 = 0x78123456" + ); } #[test] @@ -446,7 +515,11 @@ fn test_ror_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x7F6E5D4C3B2A1908, "R15: 0xFEDCBA9876543210 ROR 1"); + assert_eq!( + emu.regs().r15, + 0x7F6E5D4C3B2A1908, + "R15: 0xFEDCBA9876543210 ROR 1" + ); } // ============================================================================ @@ -459,7 +532,9 @@ fn test_ror_byte_ptr_1() { let mut emu = emu64(); // ROR byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x0c, 0x25, // ROR byte ptr [DATA_ADDR], 1 + 0xd0, + 0x0c, + 0x25, // ROR byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -481,7 +556,10 @@ fn test_ror_word_ptr_cl() { let mut emu = emu64(); // ROR word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x0c, 0x25, // ROR word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x0c, + 0x25, // ROR word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -504,7 +582,9 @@ fn test_ror_dword_ptr_imm8() { let mut emu = emu64(); // ROR dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x0c, 0x25, // ROR dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x0c, + 0x25, // ROR dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -527,7 +607,10 @@ fn test_ror_qword_ptr_cl() { let mut emu = emu64(); // ROR qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x0c, 0x25, // ROR qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x0c, + 0x25, // ROR qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -541,7 +624,10 @@ fn test_ror_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0xDEF0123456789ABC, "Memory: 0x123456789ABCDEF0 ROR 16"); + assert_eq!( + result, 0xDEF0123456789ABC, + "Memory: 0x123456789ABCDEF0 ROR 16" + ); } // ============================================================================ @@ -560,7 +646,11 @@ fn test_ror_byte_swap_endianness() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: bytes rotated"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: bytes rotated" + ); } #[test] @@ -576,7 +666,11 @@ fn test_ror_overflow_flag_1bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x00000001 ROR 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x00000001 ROR 1" + ); assert!(emu.flags().f_of, "OF: MSB XOR next-to-MSB = 1"); } @@ -610,7 +704,11 @@ fn test_ror_chained_rotations() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x02468ACF, "EAX: three 1-bit rotations"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x02468ACF, + "EAX: three 1-bit rotations" + ); } #[test] @@ -625,7 +723,11 @@ fn test_ror_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: all ones stay all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: all ones stay all ones" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -657,7 +759,11 @@ fn test_ror_extract_low_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00001234, "EAX: high word moved to low"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00001234, + "EAX: high word moved to low" + ); } #[test] @@ -672,6 +778,10 @@ fn test_ror_alternating_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x55555555, "EAX: alternating bits rotated"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x55555555, + "EAX: alternating bits rotated" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_arithmetic/sar.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_arithmetic/sar.rs index 8d4a7a7a..9272a53e 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_arithmetic/sar.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_arithmetic/sar.rs @@ -25,7 +25,6 @@ // - AF: Undefined for non-zero count // - Count is 0: No flags affected - use crate::*; // ============================================================================ @@ -45,7 +44,11 @@ fn test_sar_al_1_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x21, "AL: 0x42 >> 1 = 0x21 (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x21, + "AL: 0x42 >> 1 = 0x21 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: LSB shifted out was 0"); assert!(!emu.flags().f_of, "OF: always cleared for 1-bit SAR"); assert!(!emu.flags().f_sf, "SF: result is positive"); @@ -65,7 +68,11 @@ fn test_sar_al_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xC1, "AL: 0x82 >> 1 = 0xC1 (sign bit extended)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xC1, + "AL: 0x82 >> 1 = 0xC1 (sign bit extended)" + ); assert!(!emu.flags().f_cf, "CF: LSB shifted out was 0"); assert!(!emu.flags().f_of, "OF: always cleared for 1-bit SAR"); assert!(emu.flags().f_sf, "SF: result is still negative"); @@ -103,7 +110,11 @@ fn test_sar_al_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xFF, "AL: 0x80 >> 7 = 0xFF (all bits set by sign extension)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xFF, + "AL: 0x80 >> 7 = 0xFF (all bits set by sign extension)" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out"); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -121,7 +132,11 @@ fn test_sar_al_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xF1, "AL: 0x88 >> 3 = 0xF1 (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xF1, + "AL: 0x88 >> 3 = 0xF1 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -157,7 +172,11 @@ fn test_sar_count_masked_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xF1, "AL: 0x88 >> 3 = 0xF1 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xF1, + "AL: 0x88 >> 3 = 0xF1 (count masked)" + ); } #[test] @@ -169,13 +188,18 @@ fn test_sar_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -213,7 +237,11 @@ fn test_sar_ax_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xC000, "AX: 0x8000 >> 1 = 0xC000 (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xC000, + "AX: 0x8000 >> 1 = 0xC000 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -232,7 +260,11 @@ fn test_sar_ax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xFFFF, "AX: 0xFF00 >> 8 = 0xFFFF (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xFFFF, + "AX: 0xFF00 >> 8 = 0xFFFF (sign extended)" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -270,7 +302,11 @@ fn test_sar_eax_1_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x091A2B3C, "EAX: 0x12345678 >> 1 = 0x091A2B3C"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x091A2B3C, + "EAX: 0x12345678 >> 1 = 0x091A2B3C" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); assert!(!emu.flags().f_of, "OF: cleared for 1-bit SAR"); } @@ -288,7 +324,11 @@ fn test_sar_eax_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xC0000000, "EAX: 0x80000000 >> 1 = 0xC0000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xC0000000, + "EAX: 0x80000000 >> 1 = 0xC0000000" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); assert!(emu.flags().f_sf, "SF: result is still negative"); } @@ -307,7 +347,11 @@ fn test_sar_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: 0xFFFF0000 >> 16 = 0xFFFFFFFF"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: 0xFFFF0000 >> 16 = 0xFFFFFFFF" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -324,7 +368,11 @@ fn test_sar_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00123456, "EAX: 0x12345600 >> 8 = 0x00123456"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00123456, + "EAX: 0x12345600 >> 8 = 0x00123456" + ); assert!(!emu.flags().f_sf, "SF: result is positive"); } @@ -341,7 +389,11 @@ fn test_sar_count_masked_32bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: 0x80000000 >> 31 = 0xFFFFFFFF (all ones)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: 0x80000000 >> 31 = 0xFFFFFFFF (all ones)" + ); } // ============================================================================ @@ -361,7 +413,11 @@ fn test_sar_rax_1_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x091A2B3C4D5E6F78, "RAX: 0x123456789ABCDEF0 >> 1"); + assert_eq!( + emu.regs().rax, + 0x091A2B3C4D5E6F78, + "RAX: 0x123456789ABCDEF0 >> 1" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); assert!(!emu.flags().f_of, "OF: cleared for 1-bit SAR"); } @@ -379,7 +435,11 @@ fn test_sar_rax_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC000000000000000, "RAX: 0x8000000000000000 >> 1 = 0xC000000000000000"); + assert_eq!( + emu.regs().rax, + 0xC000000000000000, + "RAX: 0x8000000000000000 >> 1 = 0xC000000000000000" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); assert!(emu.flags().f_sf, "SF: result is still negative"); } @@ -398,7 +458,11 @@ fn test_sar_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX: 0xFFFFFFFFFFFF0000 >> 16 = 0xFFFFFFFFFFFFFFFF"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX: 0xFFFFFFFFFFFF0000 >> 16 = 0xFFFFFFFFFFFFFFFF" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -415,7 +479,11 @@ fn test_sar_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000012345678, "RAX: high 32 bits shifted to low 32"); + assert_eq!( + emu.regs().rax, + 0x0000000012345678, + "RAX: high 32 bits shifted to low 32" + ); assert!(!emu.flags().f_sf, "SF: result is positive"); } @@ -432,7 +500,11 @@ fn test_sar_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX: sign extended to all ones"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX: sign extended to all ones" + ); } // ============================================================================ @@ -452,7 +524,11 @@ fn test_sar_r8b_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFF, 0xD5, "R8B: 0xAA >> 1 = 0xD5 (sign extended)"); + assert_eq!( + emu.regs().r8 & 0xFF, + 0xD5, + "R8B: 0xAA >> 1 = 0xD5 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: LSB was 0"); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -471,7 +547,11 @@ fn test_sar_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0xFF00, "R10W: 0xF000 >> 4 = 0xFF00 (sign extended)"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0xFF00, + "R10W: 0xF000 >> 4 = 0xFF00 (sign extended)" + ); } #[test] @@ -487,7 +567,11 @@ fn test_sar_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0x00123456, "R12D: 0x12345678 >> 8 = 0x00123456"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0x00123456, + "R12D: 0x12345678 >> 8 = 0x00123456" + ); } #[test] @@ -503,7 +587,11 @@ fn test_sar_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0xFF6E5D4C3B2A1908, "R15: signed right shift by 1"); + assert_eq!( + emu.regs().r15, + 0xFF6E5D4C3B2A1908, + "R15: signed right shift by 1" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -517,7 +605,9 @@ fn test_sar_byte_ptr_1() { let mut emu = emu64(); // SAR byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x3c, 0x25, // SAR byte ptr [DATA_ADDR], 1 + 0xd0, + 0x3c, + 0x25, // SAR byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -540,7 +630,10 @@ fn test_sar_word_ptr_cl() { let mut emu = emu64(); // SAR word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x3c, 0x25, // SAR word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x3c, + 0x25, // SAR word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -554,7 +647,10 @@ fn test_sar_word_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_word(DATA_ADDR).unwrap(); - assert_eq!(result, 0xFFF0, "Memory: 0xF000 >> 8 = 0xFFF0 (sign extended)"); + assert_eq!( + result, 0xFFF0, + "Memory: 0xF000 >> 8 = 0xFFF0 (sign extended)" + ); } #[test] @@ -563,7 +659,9 @@ fn test_sar_dword_ptr_imm8() { let mut emu = emu64(); // SAR dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x3c, 0x25, // SAR dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x3c, + 0x25, // SAR dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -586,7 +684,10 @@ fn test_sar_qword_ptr_cl() { let mut emu = emu64(); // SAR qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x3c, 0x25, // SAR qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x3c, + 0x25, // SAR qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -600,7 +701,10 @@ fn test_sar_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0xFFFFFFFFFFFFFFFF, "Memory: 0xFFFFFFFF00000000 >> 32 = all ones"); + assert_eq!( + result, 0xFFFFFFFFFFFFFFFF, + "Memory: 0xFFFFFFFF00000000 >> 32 = all ones" + ); } // ============================================================================ @@ -621,7 +725,11 @@ fn test_sar_signed_divide_by_power_of_2() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rax & 0xFFFFFFFF) as i32, -4, "EAX: -16 / 4 = -4"); + assert_eq!( + (emu.regs().rax & 0xFFFFFFFF) as i32, + -4, + "EAX: -16 / 4 = -4" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -639,7 +747,11 @@ fn test_sar_rounding_toward_negative_infinity() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rax & 0xFFFFFFFF) as i32, -3, "EAX: -9 >> 2 = -3 (rounds toward -∞)"); + assert_eq!( + (emu.regs().rax & 0xFFFFFFFF) as i32, + -3, + "EAX: -9 >> 2 = -3 (rounds toward -∞)" + ); } #[test] @@ -672,7 +784,11 @@ fn test_sar_all_ones_stays_negative_one() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: -1 >> 1 = -1 (stays all ones)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: -1 >> 1 = -1 (stays all ones)" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -689,7 +805,11 @@ fn test_sar_to_zero_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0, "EAX: positive number >> 31 = 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0, + "EAX: positive number >> 31 = 0" + ); assert!(emu.flags().f_zf, "ZF: result is zero"); assert!(!emu.flags().f_sf, "SF: result is not negative"); } @@ -706,7 +826,11 @@ fn test_sar_to_negative_one() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: negative number >> 31 = -1 (all ones)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: negative number >> 31 = -1 (all ones)" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } @@ -734,7 +858,11 @@ fn test_sar_extract_sign_bit() { emu.load_code_bytes(&code2); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "EAX: negative >> 31 = -1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "EAX: negative >> 31 = -1" + ); } #[test] @@ -769,7 +897,11 @@ fn test_sar_chained_shifts() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFF000000, "EAX: 0xF8000000 >> 3 = 0xFF000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFF000000, + "EAX: 0xF8000000 >> 3 = 0xFF000000" + ); assert!(emu.flags().f_sf, "SF: result is still negative"); } @@ -785,6 +917,10 @@ fn test_sar_sign_extension_propagation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0x8000000000000000, 0x8000000000000000, "MSB should remain 1"); + assert_eq!( + emu.regs().rax & 0x8000000000000000, + 0x8000000000000000, + "MSB should remain 1" + ); assert!(emu.flags().f_sf, "SF: result is negative"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/mod.rs index 41a95b72..0ebd9e8d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/mod.rs @@ -1,2 +1,2 @@ -mod shrd; mod shld; +mod shrd; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shld.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shld.rs index 4e6dce79..781ea5e0 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shld.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shld.rs @@ -40,7 +40,11 @@ fn test_shld_ax_bx_imm8() { emu.run(None).unwrap(); // AX: 0001_0010_0011_0100 shifted left by 4 - assert_eq!(emu.regs().rax & 0xFFFF, 0x234A, "AX: 0x1234 SHLD 4 from 0xABCD = 0x234A"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x234A, + "AX: 0x1234 SHLD 4 from 0xABCD = 0x234A" + ); assert!(emu.flags().f_cf, "CF: bit shifted out was 1"); } @@ -60,7 +64,11 @@ fn test_shld_ax_bx_cl() { emu.run(None).unwrap(); // AX high byte = 0x34, fill with BX high byte = 0xAB - assert_eq!(emu.regs().rax & 0xFFFF, 0x34AB, "AX: 0x1234 SHLD 8 from 0xABCD = 0x34AB"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x34AB, + "AX: 0x1234 SHLD 8 from 0xABCD = 0x34AB" + ); } #[test] @@ -77,7 +85,11 @@ fn test_shld_ax_bx_1bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: 0x4000 SHLD 1 = 0x8000"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: 0x4000 SHLD 1 = 0x8000" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); assert!(emu.flags().f_of, "OF: sign changed from + to -"); } @@ -96,7 +108,11 @@ fn test_shld_ax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xABCD, "AX: completely replaced by BX"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xABCD, + "AX: completely replaced by BX" + ); } // ============================================================================ @@ -117,7 +133,11 @@ fn test_shld_eax_ebx_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2345678A, "EAX: 0x12345678 SHLD 4 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2345678A, + "EAX: 0x12345678 SHLD 4 from 0xABCDEF01" + ); } #[test] @@ -135,7 +155,11 @@ fn test_shld_eax_ebx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x345678AB, "EAX: 0x12345678 SHLD 8 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x345678AB, + "EAX: 0x12345678 SHLD 8 from 0xABCDEF01" + ); } #[test] @@ -169,7 +193,11 @@ fn test_shld_eax_count_masked() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x345678AB, "EAX: count masked to 8"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x345678AB, + "EAX: count masked to 8" + ); } #[test] @@ -244,7 +272,11 @@ fn test_shld_rax_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x56789ABCDEF0FEDC, "RAX: count masked to 16"); + assert_eq!( + emu.regs().rax, + 0x56789ABCDEF0FEDC, + "RAX: count masked to 16" + ); } #[test] @@ -261,7 +293,11 @@ fn test_shld_rax_full_width() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: unchanged when count masks to 0"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: unchanged when count masks to 0" + ); } // ============================================================================ @@ -300,7 +336,11 @@ fn test_shld_r10d_r11d_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFFFFFF, 0x345678AB, "R10D: SHLD from R11D"); + assert_eq!( + emu.regs().r10 & 0xFFFFFFFF, + 0x345678AB, + "R10D: SHLD from R11D" + ); } #[test] @@ -330,7 +370,11 @@ fn test_shld_word_ptr_imm8() { let mut emu = emu64(); // SHLD word ptr [DATA_ADDR], BX, imm8 let code = [ - 0x66, 0x0f, 0xa4, 0x1c, 0x25, // SHLD word ptr [DATA_ADDR], BX, imm8 + 0x66, + 0x0f, + 0xa4, + 0x1c, + 0x25, // SHLD word ptr [DATA_ADDR], BX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -354,7 +398,10 @@ fn test_shld_dword_ptr_cl() { let mut emu = emu64(); // SHLD dword ptr [DATA_ADDR], EBX, CL let code = [ - 0x0f, 0xa5, 0x1c, 0x25, // SHLD dword ptr [DATA_ADDR], EBX, CL + 0x0f, + 0xa5, + 0x1c, + 0x25, // SHLD dword ptr [DATA_ADDR], EBX, CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -369,7 +416,10 @@ fn test_shld_dword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_dword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x345678AB, "Memory: 0x12345678 SHLD 8 from 0xABCDEF01"); + assert_eq!( + result, 0x345678AB, + "Memory: 0x12345678 SHLD 8 from 0xABCDEF01" + ); } #[test] @@ -378,7 +428,11 @@ fn test_shld_qword_ptr_imm8() { let mut emu = emu64(); // SHLD qword ptr [DATA_ADDR], RBX, imm8 let code = [ - 0x48, 0x0f, 0xa4, 0x1c, 0x25, // SHLD qword ptr [DATA_ADDR], RBX, imm8 + 0x48, + 0x0f, + 0xa4, + 0x1c, + 0x25, // SHLD qword ptr [DATA_ADDR], RBX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -417,9 +471,17 @@ fn test_shld_multi_precision_shift() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xEDCBA98765432100, "RAX: low 64 bits shifted"); + assert_eq!( + emu.regs().rax, + 0xEDCBA98765432100, + "RAX: low 64 bits shifted" + ); // RBX: 0x123456789ABCDEF0 << 4 with high 4 bits of 0xEDCBA98765432100 - assert_eq!(emu.regs().rbx, 0x23456789ABCDEF0E, "RBX: high 64 bits with fill from RAX"); + assert_eq!( + emu.regs().rbx, + 0x23456789ABCDEF0E, + "RBX: high 64 bits with fill from RAX" + ); } #[test] @@ -436,7 +498,11 @@ fn test_shld_extract_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x0000ABCD, "EAX: extracted high 16 bits from EBX"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x0000ABCD, + "EAX: extracted high 16 bits from EBX" + ); } #[test] @@ -452,7 +518,11 @@ fn test_shld_flag_behavior() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: 0x80000000 SHLD 1 = 0x00000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: 0x80000000 SHLD 1 = 0x00000000" + ); assert!(emu.flags().f_cf, "CF: bit shifted out was 1"); // OF: sign changed from negative to positive assert!(emu.flags().f_of, "OF: sign changed"); @@ -474,7 +544,11 @@ fn test_shld_concatenate_values() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: concatenated result"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: concatenated result" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shrd.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shrd.rs index 656f03d6..827f4d35 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shrd.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_double_precision/shrd.rs @@ -40,7 +40,11 @@ fn test_shrd_ax_bx_imm8() { emu.run(None).unwrap(); // AX: 0001_0010_0011_0100 shifted right by 4 - assert_eq!(emu.regs().rax & 0xFFFF, 0xD123, "AX: 0x1234 SHRD 4 from 0xABCD = 0xD123"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xD123, + "AX: 0x1234 SHRD 4 from 0xABCD = 0xD123" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); } @@ -60,7 +64,11 @@ fn test_shrd_ax_bx_cl() { emu.run(None).unwrap(); // AX low byte = 0x12, fill with BX low byte = 0xCD - assert_eq!(emu.regs().rax & 0xFFFF, 0xCD12, "AX: 0x1234 SHRD 8 from 0xABCD = 0xCD12"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xCD12, + "AX: 0x1234 SHRD 8 from 0xABCD = 0xCD12" + ); } #[test] @@ -77,7 +85,11 @@ fn test_shrd_ax_bx_1bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0001, "AX: 0x0002 SHRD 1 = 0x0001"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0001, + "AX: 0x0002 SHRD 1 = 0x0001" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); assert!(!emu.flags().f_of, "OF: no sign change"); } @@ -96,7 +108,11 @@ fn test_shrd_ax_full_replacement() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xABCD, "AX: completely replaced by BX"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xABCD, + "AX: completely replaced by BX" + ); } // ============================================================================ @@ -117,7 +133,11 @@ fn test_shrd_eax_ebx_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x11234567, "EAX: 0x12345678 SHRD 4 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x11234567, + "EAX: 0x12345678 SHRD 4 from 0xABCDEF01" + ); } #[test] @@ -135,7 +155,11 @@ fn test_shrd_eax_ebx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x01123456, "EAX: 0x12345678 SHRD 8 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x01123456, + "EAX: 0x12345678 SHRD 8 from 0xABCDEF01" + ); } #[test] @@ -169,7 +193,11 @@ fn test_shrd_eax_count_masked() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x01123456, "EAX: count masked to 8"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x01123456, + "EAX: count masked to 8" + ); } #[test] @@ -244,7 +272,11 @@ fn test_shrd_rax_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x3210123456789ABC, "RAX: count masked to 16"); + assert_eq!( + emu.regs().rax, + 0x3210123456789ABC, + "RAX: count masked to 16" + ); } #[test] @@ -261,7 +293,11 @@ fn test_shrd_rax_full_width() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: unchanged when count masks to 0"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: unchanged when count masks to 0" + ); } // ============================================================================ @@ -300,7 +336,11 @@ fn test_shrd_r10d_r11d_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFFFFFF, 0x01123456, "R10D: SHRD from R11D"); + assert_eq!( + emu.regs().r10 & 0xFFFFFFFF, + 0x01123456, + "R10D: SHRD from R11D" + ); } #[test] @@ -330,7 +370,11 @@ fn test_shrd_word_ptr_imm8() { let mut emu = emu64(); // SHRD word ptr [DATA_ADDR], BX, imm8 let code = [ - 0x66, 0x0f, 0xac, 0x1c, 0x25, // SHRD word ptr [DATA_ADDR], BX, imm8 + 0x66, + 0x0f, + 0xac, + 0x1c, + 0x25, // SHRD word ptr [DATA_ADDR], BX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -354,7 +398,10 @@ fn test_shrd_dword_ptr_cl() { let mut emu = emu64(); // SHRD dword ptr [DATA_ADDR], EBX, CL let code = [ - 0x0f, 0xad, 0x1c, 0x25, // SHRD dword ptr [DATA_ADDR], EBX, CL + 0x0f, + 0xad, + 0x1c, + 0x25, // SHRD dword ptr [DATA_ADDR], EBX, CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -369,7 +416,10 @@ fn test_shrd_dword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_dword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x01123456, "Memory: 0x12345678 SHRD 8 from 0xABCDEF01"); + assert_eq!( + result, 0x01123456, + "Memory: 0x12345678 SHRD 8 from 0xABCDEF01" + ); } #[test] @@ -378,7 +428,11 @@ fn test_shrd_qword_ptr_imm8() { let mut emu = emu64(); // SHRD qword ptr [DATA_ADDR], RBX, imm8 let code = [ - 0x48, 0x0f, 0xac, 0x1c, 0x25, // SHRD qword ptr [DATA_ADDR], RBX, imm8 + 0x48, + 0x0f, + 0xac, + 0x1c, + 0x25, // SHRD qword ptr [DATA_ADDR], RBX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -419,8 +473,16 @@ fn test_shrd_multi_precision_shift() { // RAX: 0x123456789ABCDEF0, low 4 bits = 0x0 // RBX: 0xFEDCBA9876543210 >> 4 with 0x0 from top = 0x0FEDCBA987654321 - assert_eq!(emu.regs().rbx, 0x0FEDCBA987654321, "RBX: low 64 bits with fill from RAX"); - assert_eq!(emu.regs().rax, 0x0123456789ABCDEF, "RAX: high 64 bits shifted"); + assert_eq!( + emu.regs().rbx, + 0x0FEDCBA987654321, + "RBX: low 64 bits with fill from RAX" + ); + assert_eq!( + emu.regs().rax, + 0x0123456789ABCDEF, + "RAX: high 64 bits shifted" + ); } #[test] @@ -437,7 +499,11 @@ fn test_shrd_extract_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xABCD0000, "EAX: extracted low 16 bits from EBX"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xABCD0000, + "EAX: extracted low 16 bits from EBX" + ); } #[test] @@ -453,7 +519,11 @@ fn test_shrd_flag_behavior() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: 0x00000001 SHRD 1 = 0x00000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: 0x00000001 SHRD 1 = 0x00000000" + ); assert!(emu.flags().f_cf, "CF: bit shifted out was 1"); // OF: sign changed from positive to negative? No, result is still positive assert!(!emu.flags().f_of, "OF: no sign change"); @@ -475,7 +545,11 @@ fn test_shrd_concatenate_values() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000000, "EAX: concatenated result"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000000, + "EAX: concatenated result" + ); } #[test] @@ -509,5 +583,9 @@ fn test_shrd_reverse_bytes() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x34567812, "EAX: byte manipulation"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x34567812, + "EAX: byte manipulation" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shl.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shl.rs index 4e68b647..88286490 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shl.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shl.rs @@ -22,7 +22,6 @@ // - AF: Undefined for non-zero count // - Count is 0: No flags affected - use crate::*; // ============================================================================ @@ -138,7 +137,11 @@ fn test_shl_count_masked_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x88, "AL: 0x11 << 3 = 0x88 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x88, + "AL: 0x11 << 3 = 0x88 (count masked)" + ); } #[test] @@ -150,13 +153,18 @@ fn test_shl_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -252,7 +260,11 @@ fn test_shl_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2468ACF0, "EAX: 0x12345678 << 1 = 0x2468ACF0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2468ACF0, + "EAX: 0x12345678 << 1 = 0x2468ACF0" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(!emu.flags().f_of, "OF should be clear"); } @@ -271,7 +283,11 @@ fn test_shl_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x00000001 << 31 = 0x80000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x00000001 << 31 = 0x80000000" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF should be set"); } @@ -289,7 +305,11 @@ fn test_shl_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345600, "EAX: 0x00123456 << 8 = 0x12345600"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345600, + "EAX: 0x00123456 << 8 = 0x12345600" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -305,7 +325,11 @@ fn test_shl_eax_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000002, "EAX: 0x80000001 << 1 = 0x00000002"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000002, + "EAX: 0x80000001 << 1 = 0x00000002" + ); assert!(emu.flags().f_cf, "CF should be set (MSB was 1)"); assert!(emu.flags().f_of, "OF: MSB XOR CF = 0 XOR 1 = 1"); } @@ -323,7 +347,11 @@ fn test_shl_count_masked_32bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x00000001 << 31 = 0x80000000 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x00000001 << 31 = 0x80000000 (count masked)" + ); } // ============================================================================ @@ -343,7 +371,11 @@ fn test_shl_rax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x2468ACF13579BDE0, "RAX: 0x123456789ABCDEF0 << 1"); + assert_eq!( + emu.regs().rax, + 0x2468ACF13579BDE0, + "RAX: 0x123456789ABCDEF0 << 1" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(!emu.flags().f_of, "OF should be clear"); } @@ -362,7 +394,11 @@ fn test_shl_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000000000000000, "RAX: 0x0000000000000001 << 63"); + assert_eq!( + emu.regs().rax, + 0x8000000000000000, + "RAX: 0x0000000000000001 << 63" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF should be set"); } @@ -380,7 +416,11 @@ fn test_shl_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABC0000, "RAX: 0x0000123456789ABC << 16"); + assert_eq!( + emu.regs().rax, + 0x123456789ABC0000, + "RAX: 0x0000123456789ABC << 16" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -396,7 +436,11 @@ fn test_shl_rax_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000002, "RAX: 0x8000000000000001 << 1"); + assert_eq!( + emu.regs().rax, + 0x0000000000000002, + "RAX: 0x8000000000000001 << 1" + ); assert!(emu.flags().f_cf, "CF should be set (MSB was 1)"); assert!(emu.flags().f_of, "OF: MSB XOR CF = 0 XOR 1 = 1"); } @@ -414,7 +458,11 @@ fn test_shl_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000000000000000, "RAX: 0x0000000000000001 << 63 (count masked to 6 bits)"); + assert_eq!( + emu.regs().rax, + 0x8000000000000000, + "RAX: 0x0000000000000001 << 63 (count masked to 6 bits)" + ); } // ============================================================================ @@ -453,7 +501,11 @@ fn test_shl_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x2340, "R10W: 0x1234 << 4 = 0x2340"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x2340, + "R10W: 0x1234 << 4 = 0x2340" + ); } #[test] @@ -469,7 +521,11 @@ fn test_shl_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0x34567800, "R12D: 0x12345678 << 8 = 0x34567800"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0x34567800, + "R12D: 0x12345678 << 8 = 0x34567800" + ); } #[test] @@ -485,7 +541,11 @@ fn test_shl_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x02468ACF13579BDE, "R15: 0x0123456789ABCDEF << 1"); + assert_eq!( + emu.regs().r15, + 0x02468ACF13579BDE, + "R15: 0x0123456789ABCDEF << 1" + ); } // ============================================================================ @@ -498,7 +558,9 @@ fn test_shl_byte_ptr_1() { let mut emu = emu64(); // SHL byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x24, 0x25, // SHL byte ptr [DATA_ADDR], 1 + 0xd0, + 0x24, + 0x25, // SHL byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -521,7 +583,10 @@ fn test_shl_word_ptr_cl() { let mut emu = emu64(); // SHL word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x24, 0x25, // SHL word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x24, + 0x25, // SHL word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -544,7 +609,9 @@ fn test_shl_dword_ptr_imm8() { let mut emu = emu64(); // SHL dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x24, 0x25, // SHL dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x24, + 0x25, // SHL dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -567,7 +634,10 @@ fn test_shl_qword_ptr_cl() { let mut emu = emu64(); // SHL qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x24, 0x25, // SHL qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x24, + 0x25, // SHL qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -581,7 +651,10 @@ fn test_shl_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x56789ABCDEF00000, "Memory: 0x123456789ABCDEF0 << 16"); + assert_eq!( + result, 0x56789ABCDEF00000, + "Memory: 0x123456789ABCDEF0 << 16" + ); } // ============================================================================ @@ -618,7 +691,11 @@ fn test_shl_align_to_page_boundary() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCD000, "RAX aligned to 4KB boundary"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCD000, + "RAX aligned to 4KB boundary" + ); } #[test] @@ -633,7 +710,11 @@ fn test_shl_extract_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFF00000000, "RAX: low 32 bits moved to high"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFF00000000, + "RAX: low 32 bits moved to high" + ); } #[test] @@ -649,7 +730,11 @@ fn test_shl_overflow_flag_1bit_same_sign() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x40000000 << 1 = 0x80000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x40000000 << 1 = 0x80000000" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); assert!(emu.flags().f_of, "OF: MSB(result) XOR CF = 1 XOR 0 = 1"); } @@ -667,7 +752,11 @@ fn test_shl_overflow_flag_1bit_different_sign() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0xC0000000 << 1 = 0x80000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0xC0000000 << 1 = 0x80000000" + ); assert!(emu.flags().f_cf, "CF: bit shifted out was 1"); assert!(!emu.flags().f_of, "OF: MSB(result) XOR CF = 1 XOR 1 = 0"); // OF = old_MSB XOR new_MSB = 1 XOR 1 = 0? Or is it MSB XOR CF? @@ -720,7 +809,11 @@ fn test_shl_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFE, "EAX: 0xFFFFFFFF << 1 = 0xFFFFFFFE"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFE, + "EAX: 0xFFFFFFFF << 1 = 0xFFFFFFFE" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); assert!(emu.flags().f_sf, "SF: result is negative"); assert!(!emu.flags().f_zf, "ZF: result is not zero"); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shr.rs index 0ed6c469..128ea470 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_logical/shr.rs @@ -45,7 +45,10 @@ fn test_shr_al_1() { assert_eq!(emu.regs().rax & 0xFF, 0x21, "AL: 0x42 >> 1 = 0x21"); assert!(!emu.flags().f_cf, "CF should be clear (LSB was 0)"); - assert!(!emu.flags().f_of, "OF should be clear (MSB of original was 0)"); + assert!( + !emu.flags().f_of, + "OF should be clear (MSB of original was 0)" + ); assert!(!emu.flags().f_sf, "SF should be clear"); assert!(!emu.flags().f_zf, "ZF should be clear"); } @@ -153,7 +156,11 @@ fn test_shr_count_masked_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x11, "AL: 0x88 >> 3 = 0x11 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x11, + "AL: 0x88 >> 3 = 0x11 (count masked)" + ); } #[test] @@ -165,13 +172,18 @@ fn test_shr_count_zero_preserves_flags() { 0xf4, ]; emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } // ============================================================================ @@ -229,7 +241,10 @@ fn test_shr_ax_imm8() { assert_eq!(emu.regs().rax & 0xFFFF, 0x0123, "AX: 0x1234 >> 4 = 0x0123"); // CF = bit 3 of 0x1234 = 0 (last bit shifted out) - assert!(!emu.flags().f_cf, "CF should be clear (bit 3 of 0x1234 was 0)"); + assert!( + !emu.flags().f_cf, + "CF should be clear (bit 3 of 0x1234 was 0)" + ); } #[test] @@ -244,7 +259,11 @@ fn test_shr_ax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x4000, "AX: 0x8000 >> 1 = 0x4000 (zero fill)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x4000, + "AX: 0x8000 >> 1 = 0x4000 (zero fill)" + ); assert!(!emu.flags().f_cf, "CF should be clear (LSB was 0)"); assert!(emu.flags().f_of, "OF should be set (MSB of original was 1)"); } @@ -266,7 +285,11 @@ fn test_shr_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x091A2B3C, "EAX: 0x12345678 >> 1 = 0x091A2B3C"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x091A2B3C, + "EAX: 0x12345678 >> 1 = 0x091A2B3C" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(!emu.flags().f_of, "OF should be clear"); } @@ -285,7 +308,11 @@ fn test_shr_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000001, "EAX: 0x80000000 >> 31 = 0x00000001"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000001, + "EAX: 0x80000000 >> 31 = 0x00000001" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); } @@ -302,7 +329,11 @@ fn test_shr_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00123456, "EAX: 0x12345678 >> 8 = 0x00123456"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00123456, + "EAX: 0x12345678 >> 8 = 0x00123456" + ); assert!(!emu.flags().f_cf, "CF should be clear"); } @@ -319,7 +350,11 @@ fn test_shr_eax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x40000000, "EAX: 0x80000000 >> 1 = 0x40000000 (zero fill)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x40000000, + "EAX: 0x80000000 >> 1 = 0x40000000 (zero fill)" + ); assert!(!emu.flags().f_cf, "CF should be clear (LSB was 0)"); assert!(emu.flags().f_of, "OF should be set (MSB of original was 1)"); } @@ -337,7 +372,11 @@ fn test_shr_count_masked_32bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000001, "EAX: 0x80000000 >> 31 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000001, + "EAX: 0x80000000 >> 31 (count masked)" + ); } // ============================================================================ @@ -357,7 +396,11 @@ fn test_shr_rax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x091A2B3C4D5E6F78, "RAX: 0x123456789ABCDEF0 >> 1"); + assert_eq!( + emu.regs().rax, + 0x091A2B3C4D5E6F78, + "RAX: 0x123456789ABCDEF0 >> 1" + ); assert!(!emu.flags().f_cf, "CF should be clear"); assert!(!emu.flags().f_of, "OF should be clear"); } @@ -376,7 +419,11 @@ fn test_shr_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "RAX: 0x8000000000000000 >> 63"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "RAX: 0x8000000000000000 >> 63" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); } @@ -393,9 +440,16 @@ fn test_shr_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000012345678, "RAX: high 32 bits shifted to low 32"); + assert_eq!( + emu.regs().rax, + 0x0000000012345678, + "RAX: high 32 bits shifted to low 32" + ); // CF = bit 31 of original = MSB of 0x9ABCDEF0 = 1 - assert!(emu.flags().f_cf, "CF should be set (bit 31 of 0x9ABCDEF0 is 1)"); + assert!( + emu.flags().f_cf, + "CF should be set (bit 31 of 0x9ABCDEF0 is 1)" + ); } #[test] @@ -411,7 +465,11 @@ fn test_shr_rax_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x4000000000000000, "RAX: 0x8000000000000000 >> 1 (zero fill)"); + assert_eq!( + emu.regs().rax, + 0x4000000000000000, + "RAX: 0x8000000000000000 >> 1 (zero fill)" + ); assert!(!emu.flags().f_cf, "CF should be clear (LSB was 0)"); assert!(emu.flags().f_of, "OF should be set (MSB of original was 1)"); } @@ -429,7 +487,11 @@ fn test_shr_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "RAX: 0x8000000000000000 >> 63 (count masked to 6 bits)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "RAX: 0x8000000000000000 >> 63 (count masked to 6 bits)" + ); } // ============================================================================ @@ -467,7 +529,11 @@ fn test_shr_r10w_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r10 & 0xFFFF, 0x0123, "R10W: 0x1234 >> 4 = 0x0123"); + assert_eq!( + emu.regs().r10 & 0xFFFF, + 0x0123, + "R10W: 0x1234 >> 4 = 0x0123" + ); } #[test] @@ -483,7 +549,11 @@ fn test_shr_r12d_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12 & 0xFFFFFFFF, 0x00123456, "R12D: 0x12345678 >> 8 = 0x00123456"); + assert_eq!( + emu.regs().r12 & 0xFFFFFFFF, + 0x00123456, + "R12D: 0x12345678 >> 8 = 0x00123456" + ); } #[test] @@ -499,7 +569,11 @@ fn test_shr_r15_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0x7F6E5D4C3B2A1908, "R15: logical right shift by 1 (zero fill)"); + assert_eq!( + emu.regs().r15, + 0x7F6E5D4C3B2A1908, + "R15: logical right shift by 1 (zero fill)" + ); assert!(!emu.flags().f_sf, "SF should be clear (result < 2^63)"); } @@ -513,7 +587,9 @@ fn test_shr_byte_ptr_1() { let mut emu = emu64(); // SHR byte ptr [DATA_ADDR], 1 let code = [ - 0xd0, 0x2c, 0x25, // SHR byte ptr [DATA_ADDR], 1 + 0xd0, + 0x2c, + 0x25, // SHR byte ptr [DATA_ADDR], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -536,7 +612,10 @@ fn test_shr_word_ptr_cl() { let mut emu = emu64(); // SHR word ptr [DATA_ADDR], CL let code = [ - 0x66, 0xd3, 0x2c, 0x25, // SHR word ptr [DATA_ADDR], CL + 0x66, + 0xd3, + 0x2c, + 0x25, // SHR word ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -559,7 +638,9 @@ fn test_shr_dword_ptr_imm8() { let mut emu = emu64(); // SHR dword ptr [DATA_ADDR], imm8 let code = [ - 0xc1, 0x2c, 0x25, // SHR dword ptr [DATA_ADDR], imm8 + 0xc1, + 0x2c, + 0x25, // SHR dword ptr [DATA_ADDR], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -582,7 +663,10 @@ fn test_shr_qword_ptr_cl() { let mut emu = emu64(); // SHR qword ptr [DATA_ADDR], CL let code = [ - 0x48, 0xd3, 0x2c, 0x25, // SHR qword ptr [DATA_ADDR], CL + 0x48, + 0xd3, + 0x2c, + 0x25, // SHR qword ptr [DATA_ADDR], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -596,7 +680,10 @@ fn test_shr_qword_ptr_cl() { emu.run(None).unwrap(); let result = emu.maps.read_qword(DATA_ADDR).unwrap(); - assert_eq!(result, 0x00000000FFFFFFFF, "Memory: 0xFFFFFFFF00000000 >> 32"); + assert_eq!( + result, 0x00000000FFFFFFFF, + "Memory: 0xFFFFFFFF00000000 >> 32" + ); } // ============================================================================ @@ -636,7 +723,11 @@ fn test_shr_vs_sar_negative_values() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x7FFFFFFF, "EAX: SHR fills with zero (not sign)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x7FFFFFFF, + "EAX: SHR fills with zero (not sign)" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); assert!(!emu.flags().f_sf, "SF: result is positive"); } @@ -653,7 +744,11 @@ fn test_shr_extract_high_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00000000FFFFFFFF, "RAX: high 32 bits moved to low"); + assert_eq!( + emu.regs().rax, + 0x00000000FFFFFFFF, + "RAX: high 32 bits moved to low" + ); } #[test] @@ -715,7 +810,11 @@ fn test_shr_chained_shifts() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x1F000000, "EAX: 0xF8000000 >> 3 = 0x1F000000"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x1F000000, + "EAX: 0xF8000000 >> 3 = 0x1F000000" + ); } #[test] @@ -730,7 +829,11 @@ fn test_shr_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x7FFFFFFF, "EAX: 0xFFFFFFFF >> 1 = 0x7FFFFFFF"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x7FFFFFFF, + "EAX: 0xFFFFFFFF >> 1 = 0x7FFFFFFF" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); assert!(!emu.flags().f_sf, "SF: result is positive (MSB = 0)"); assert!(!emu.flags().f_zf, "ZF: result is not zero"); @@ -749,5 +852,9 @@ fn test_shr_isolate_bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x56, "EAX: extracted byte at bits 8-15"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x56, + "EAX: extracted byte at bits 8-15" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/sarx.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/sarx.rs index 9226b21f..29644336 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/sarx.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/sarx.rs @@ -40,7 +40,11 @@ fn test_sarx_32bit_shift_by_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "Shift by 0 should preserve value"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "Shift by 0 should preserve value" + ); } #[test] @@ -56,7 +60,11 @@ fn test_sarx_32bit_shift_positive_by_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000080, "256 >> 1 = 128 (positive)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000080, + "256 >> 1 = 128 (positive)" + ); } #[test] @@ -91,7 +99,7 @@ fn test_sarx_32bit_all_shift_counts_positive() { emu.regs_mut().rbx = 0x7FFFFFFF; // Max positive 32-bit emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (0x7FFFFFFFi32 >> count) as u32; assert_eq!( @@ -115,7 +123,7 @@ fn test_sarx_32bit_all_shift_counts_negative() { emu.regs_mut().rbx = 0x80000000; // Min negative 32-bit emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (0x80000000u32 as i32 >> count) as u32; assert_eq!( @@ -189,7 +197,7 @@ fn test_sarx_32bit_sign_extension_pattern() { emu.regs_mut().rbx = value as u64; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!( emu.regs().rax & 0xFFFFFFFF, @@ -218,7 +226,11 @@ fn test_sarx_64bit_shift_by_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "Shift by 0 should preserve value"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "Shift by 0 should preserve value" + ); } #[test] @@ -234,7 +246,11 @@ fn test_sarx_64bit_shift_positive_by_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000080, "256 >> 1 = 128 (positive)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000080, + "256 >> 1 = 128 (positive)" + ); } #[test] @@ -250,7 +266,11 @@ fn test_sarx_64bit_shift_negative_by_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC000000000000000, "Sign bit should be extended"); + assert_eq!( + emu.regs().rax, + 0xC000000000000000, + "Sign bit should be extended" + ); } #[test] @@ -265,10 +285,15 @@ fn test_sarx_64bit_all_shift_counts_positive() { emu.regs_mut().rbx = 0x7FFFFFFFFFFFFFFF; // Max positive 64-bit emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (0x7FFFFFFFFFFFFFFFi64 >> count) as u64; - assert_eq!(emu.regs().rax, expected, "Positive value >> {} failed", count); + assert_eq!( + emu.regs().rax, + expected, + "Positive value >> {} failed", + count + ); } } @@ -284,10 +309,15 @@ fn test_sarx_64bit_all_shift_counts_negative() { emu.regs_mut().rbx = 0x8000000000000000; // Min negative 64-bit emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = (0x8000000000000000u64 as i64 >> count) as u64; - assert_eq!(emu.regs().rax, expected, "Negative value >> {} failed", count); + assert_eq!( + emu.regs().rax, + expected, + "Negative value >> {} failed", + count + ); } } @@ -349,12 +379,14 @@ fn test_sarx_64bit_sign_extension_pattern() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!( - emu.regs().rax, expected, + emu.regs().rax, + expected, "Sign extension for 0x{:016X} >> {} failed", - value, count + value, + count ); } } @@ -369,7 +401,7 @@ fn test_sarx_32bit_does_not_modify_cf() { let mut emu = emu64(); // SARX should not modify CF let code = [ - 0xf9, // STC (set CF) + 0xf9, // STC (set CF) 0xc4, 0xe2, 0x72, 0xf7, 0xc3, // SARX EAX, EBX, ECX 0xf4, ]; @@ -387,8 +419,8 @@ fn test_sarx_64bit_preserves_all_flags() { let mut emu = emu64(); let code = [ 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, // MOV RAX, 1 - 0x48, 0x83, 0xe8, 0x02, // SUB RAX, 2 (sets CF, SF, AF) - 0xc4, 0xe2, 0xf2, 0xf7, 0xc3, // SARX RAX, RBX, RCX + 0x48, 0x83, 0xe8, 0x02, // SUB RAX, 2 (sets CF, SF, AF) + 0xc4, 0xe2, 0xf2, 0xf7, 0xc3, // SARX RAX, RBX, RCX 0xf4, ]; emu.regs_mut().rbx = 0x8000000000000000; @@ -417,7 +449,7 @@ fn test_sarx_32bit_all_ones_stays_all_ones() { emu.regs_mut().rbx = 0xFFFFFFFF; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!( emu.regs().rax & 0xFFFFFFFF, @@ -440,7 +472,7 @@ fn test_sarx_64bit_all_ones_stays_all_ones() { emu.regs_mut().rbx = 0xFFFFFFFFFFFFFFFF; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!( emu.regs().rax, @@ -512,7 +544,11 @@ fn test_sarx_64bit_memory_operand_negative() { emu.maps.write_qword(DATA_ADDR, 0x8000000000000000); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFF80000000000000, "64-bit memory operand sign extended"); + assert_eq!( + emu.regs().rax, + 0xFF80000000000000, + "64-bit memory operand sign extended" + ); } // ============================================================================ @@ -554,7 +590,11 @@ fn test_sarx_64bit_r14_r15_r13() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r14, 0xFF80000000000000, "64-bit extended registers"); + assert_eq!( + emu.regs().r14, + 0xFF80000000000000, + "64-bit extended registers" + ); } // ============================================================================ @@ -584,7 +624,7 @@ fn test_sarx_consecutive_shifts() { let mut emu = emu64(); let code = [ 0xc4, 0xe2, 0x72, 0xf7, 0xc3, // SARX EAX, EBX, ECX - 0x48, 0x89, 0xc3, // MOV RBX, RAX + 0x48, 0x89, 0xc3, // MOV RBX, RAX 0xc4, 0xe2, 0x72, 0xf7, 0xc3, // SARX EAX, EBX, ECX 0xf4, ]; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shlx.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shlx.rs index 243a3b78..88c7ca5c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shlx.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shlx.rs @@ -38,7 +38,11 @@ fn test_shlx_32bit_shift_by_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "Shift by 0 should preserve value"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "Shift by 0 should preserve value" + ); } #[test] @@ -69,7 +73,7 @@ fn test_shlx_32bit_all_shift_counts() { emu.regs_mut().rbx = 0x00000001; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = if count < 32 { 1u64 << count } else { 0 }; assert_eq!( @@ -160,7 +164,7 @@ fn test_shlx_32bit_power_of_two_shifts() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!( emu.regs().rax & 0xFFFFFFFF, @@ -190,7 +194,11 @@ fn test_shlx_64bit_shift_by_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "Shift by 0 should preserve value"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "Shift by 0 should preserve value" + ); } #[test] @@ -221,10 +229,16 @@ fn test_shlx_64bit_all_shift_counts() { emu.regs_mut().rbx = 0x0000000000000001; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = 1u64 << count; - assert_eq!(emu.regs().rax, expected, "1 << {} should be {}", count, expected); + assert_eq!( + emu.regs().rax, + expected, + "1 << {} should be {}", + count, + expected + ); } } @@ -241,7 +255,11 @@ fn test_shlx_64bit_shift_to_sign_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x8000000000000000, "1 << 63 should set sign bit"); + assert_eq!( + emu.regs().rax, + 0x8000000000000000, + "1 << 63 should set sign bit" + ); } #[test] @@ -273,7 +291,11 @@ fn test_shlx_64bit_shift_by_32() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFF00000000, "Lower dword shifted to upper"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFF00000000, + "Lower dword shifted to upper" + ); } // ============================================================================ @@ -286,7 +308,7 @@ fn test_shlx_32bit_does_not_modify_cf() { let mut emu = emu64(); // SHLX should not modify CF even when bits shift out let code = [ - 0xf9, // STC (set CF) + 0xf9, // STC (set CF) 0xc4, 0xe2, 0x71, 0xf7, 0xc3, // SHLX EAX, EBX, ECX 0xf4, ]; @@ -305,7 +327,7 @@ fn test_shlx_32bit_does_not_clear_cf() { let mut emu = emu64(); // SHLX should not clear CF let code = [ - 0xf9, // STC (set CF) + 0xf9, // STC (set CF) 0xc4, 0xe2, 0x71, 0xf7, 0xc3, // SHLX EAX, EBX, ECX 0xf4, ]; @@ -323,8 +345,8 @@ fn test_shlx_64bit_preserves_all_flags() { let mut emu = emu64(); let code = [ 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, // MOV RAX, 1 - 0x48, 0x83, 0xe8, 0x02, // SUB RAX, 2 (sets CF, SF, AF) - 0xc4, 0xe2, 0xf1, 0xf7, 0xc3, // SHLX RAX, RBX, RCX + 0x48, 0x83, 0xe8, 0x02, // SUB RAX, 2 (sets CF, SF, AF) + 0xc4, 0xe2, 0xf1, 0xf7, 0xc3, // SHLX RAX, RBX, RCX 0xf4, ]; emu.regs_mut().rbx = 0x0000000000000001; @@ -374,7 +396,11 @@ fn test_shlx_32bit_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFF00, "All ones shifted left by 8"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFF00, + "All ones shifted left by 8" + ); } #[test] @@ -390,7 +416,11 @@ fn test_shlx_64bit_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xAAAAAAAAAAAAAAAA, "Alternating pattern shifted"); + assert_eq!( + emu.regs().rax, + 0xAAAAAAAAAAAAAAAA, + "Alternating pattern shifted" + ); } // ============================================================================ @@ -434,7 +464,11 @@ fn test_shlx_64bit_memory_operand() { emu.maps.write_qword(DATA_ADDR, 0x0000000012345678); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000001234567800, "64-bit memory operand shifted"); + assert_eq!( + emu.regs().rax, + 0x0000001234567800, + "64-bit memory operand shifted" + ); } // ============================================================================ @@ -476,7 +510,11 @@ fn test_shlx_64bit_r14_r15_r13() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r14, 0x0001000000000000, "64-bit extended registers"); + assert_eq!( + emu.regs().r14, + 0x0001000000000000, + "64-bit extended registers" + ); } // ============================================================================ @@ -496,7 +534,11 @@ fn test_shlx_32bit_shift_all_bits_out() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFF000000, "Shifted to high byte"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFF000000, + "Shifted to high byte" + ); } #[test] @@ -522,7 +564,7 @@ fn test_shlx_consecutive_shifts() { let mut emu = emu64(); let code = [ 0xc4, 0xe2, 0x71, 0xf7, 0xc3, // SHLX EAX, EBX, ECX - 0x48, 0x89, 0xc3, // MOV RBX, RAX + 0x48, 0x89, 0xc3, // MOV RBX, RAX 0xc4, 0xe2, 0x71, 0xf7, 0xc3, // SHLX EAX, EBX, ECX 0xf4, ]; @@ -531,5 +573,9 @@ fn test_shlx_consecutive_shifts() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 256, "Consecutive shifts accumulate"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 256, + "Consecutive shifts accumulate" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shrx.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shrx.rs index 9bb342d1..656c3e6d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shrx.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logic_and_bit_manipulation/shifts_variable/shrx.rs @@ -40,7 +40,11 @@ fn test_shrx_32bit_shift_by_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "Shift by 0 should preserve value"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "Shift by 0 should preserve value" + ); } #[test] @@ -71,7 +75,7 @@ fn test_shrx_32bit_all_shift_counts() { emu.regs_mut().rbx = 0x80000000; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = 0x80000000u32 >> count; assert_eq!( @@ -118,7 +122,11 @@ fn test_shrx_32bit_shift_to_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00000001, "High bit shifted to bit 0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00000001, + "High bit shifted to bit 0" + ); } #[test] @@ -179,7 +187,7 @@ fn test_shrx_32bit_power_of_two_shifts() { emu.regs_mut().rbx = value; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!( emu.regs().rax & 0xFFFFFFFF, @@ -209,7 +217,11 @@ fn test_shrx_64bit_shift_by_0() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "Shift by 0 should preserve value"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "Shift by 0 should preserve value" + ); } #[test] @@ -240,13 +252,15 @@ fn test_shrx_64bit_all_shift_counts() { emu.regs_mut().rbx = 0x8000000000000000; emu.regs_mut().rcx = count; emu.load_code_bytes(&code); - emu.run(None).unwrap(); + emu.run(None).unwrap(); let expected = 0x8000000000000000u64 >> count; assert_eq!( - emu.regs().rax, expected, + emu.regs().rax, + expected, "0x8000000000000000 >> {} should be 0x{:016X}", - count, expected + count, + expected ); } } @@ -281,7 +295,11 @@ fn test_shrx_64bit_shift_to_zero() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "High bit shifted to bit 0"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "High bit shifted to bit 0" + ); } #[test] @@ -313,7 +331,11 @@ fn test_shrx_64bit_shift_by_32() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00000000FFFFFFFF, "Upper dword shifted to lower"); + assert_eq!( + emu.regs().rax, + 0x00000000FFFFFFFF, + "Upper dword shifted to lower" + ); } // ============================================================================ @@ -326,7 +348,7 @@ fn test_shrx_32bit_does_not_modify_cf() { let mut emu = emu64(); // SHRX should not modify CF even when bits shift out let code = [ - 0xf9, // STC (set CF) + 0xf9, // STC (set CF) 0xc4, 0xe2, 0x73, 0xf7, 0xc3, // SHRX EAX, EBX, ECX 0xf4, ]; @@ -345,7 +367,7 @@ fn test_shrx_32bit_does_not_clear_cf() { let mut emu = emu64(); // SHRX should not clear CF let code = [ - 0xf9, // STC (set CF) + 0xf9, // STC (set CF) 0xc4, 0xe2, 0x73, 0xf7, 0xc3, // SHRX EAX, EBX, ECX 0xf4, ]; @@ -363,8 +385,8 @@ fn test_shrx_64bit_preserves_all_flags() { let mut emu = emu64(); let code = [ 0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, // MOV RAX, 1 - 0x48, 0x83, 0xe8, 0x02, // SUB RAX, 2 (sets CF, SF, AF) - 0xc4, 0xe2, 0xf3, 0xf7, 0xc3, // SHRX RAX, RBX, RCX + 0x48, 0x83, 0xe8, 0x02, // SUB RAX, 2 (sets CF, SF, AF) + 0xc4, 0xe2, 0xf3, 0xf7, 0xc3, // SHRX RAX, RBX, RCX 0xf4, ]; emu.regs_mut().rbx = 0x8000000000000000; @@ -414,7 +436,11 @@ fn test_shrx_32bit_all_ones() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00FFFFFF, "All ones shifted right by 8"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00FFFFFF, + "All ones shifted right by 8" + ); } #[test] @@ -430,7 +456,11 @@ fn test_shrx_64bit_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x5555555555555555, "Alternating pattern shifted"); + assert_eq!( + emu.regs().rax, + 0x5555555555555555, + "Alternating pattern shifted" + ); } // ============================================================================ @@ -474,7 +504,11 @@ fn test_shrx_64bit_memory_operand() { emu.maps.write_qword(DATA_ADDR, 0x1234567800000000); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0012345678000000, "64-bit memory operand shifted"); + assert_eq!( + emu.regs().rax, + 0x0012345678000000, + "64-bit memory operand shifted" + ); } // ============================================================================ @@ -516,7 +550,11 @@ fn test_shrx_64bit_r14_r15_r13() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r14, 0x0000000000008000, "64-bit extended registers"); + assert_eq!( + emu.regs().r14, + 0x0000000000008000, + "64-bit extended registers" + ); } // ============================================================================ @@ -562,7 +600,7 @@ fn test_shrx_consecutive_shifts() { let mut emu = emu64(); let code = [ 0xc4, 0xe2, 0x73, 0xf7, 0xc3, // SHRX EAX, EBX, ECX - 0x48, 0x89, 0xc3, // MOV RBX, RAX + 0x48, 0x89, 0xc3, // MOV RBX, RAX 0xc4, 0xe2, 0x73, 0xf7, 0xc3, // SHRX EAX, EBX, ECX 0xf4, ]; @@ -571,7 +609,11 @@ fn test_shrx_consecutive_shifts() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x00010000, "Consecutive shifts accumulate"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x00010000, + "Consecutive shifts accumulate" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/and.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/and.rs index 66b2440e..4ec6fa24 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/and.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/and.rs @@ -115,7 +115,11 @@ fn test_and_ax_imm16_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0004, "AX: 0x1234 AND 0x000F = 0x0004"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0004, + "AX: 0x1234 AND 0x000F = 0x0004" + ); } #[test] @@ -209,7 +213,11 @@ fn test_and_rax_imm32_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: no change with all ones"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: no change with all ones" + ); } // ============================================================================ @@ -249,7 +257,11 @@ fn test_and_rm8_imm8_dh() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rdx >> 8) & 0xFF, 0x55, "DH: 0xFF AND 0x55 = 0x55"); + assert_eq!( + (emu.regs().rdx >> 8) & 0xFF, + 0x55, + "DH: 0xFF AND 0x55 = 0x55" + ); } // ============================================================================ @@ -265,7 +277,11 @@ fn test_and_rm16_imm16_bx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0x0FF0, "BX: 0xFFFF AND 0x0FF0 = 0x0FF0"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0x0FF0, + "BX: 0xFFFF AND 0x0FF0 = 0x0FF0" + ); } #[test] @@ -349,7 +365,11 @@ fn test_and_rm16_imm8_sign_ext() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0x1234, "BX: AND with 0xFFFF (no change)"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0x1234, + "BX: AND with 0xFFFF (no change)" + ); } #[test] @@ -361,7 +381,11 @@ fn test_and_rm32_imm8_sign_ext() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x0000000F, "EBX: AND with sign-extended imm8"); + assert_eq!( + emu.regs().rbx, + 0x0000000F, + "EBX: AND with sign-extended imm8" + ); } #[test] @@ -373,7 +397,11 @@ fn test_and_rm64_imm8_sign_ext() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: align to 16-byte boundary"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: align to 16-byte boundary" + ); } // ============================================================================ @@ -403,7 +431,11 @@ fn test_and_rm16_r16_ax_bx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x00FF, "AX: 0xFFFF AND 0x00FF = 0x00FF"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x00FF, + "AX: 0xFFFF AND 0x00FF = 0x00FF" + ); } #[test] @@ -429,7 +461,11 @@ fn test_and_rm64_r64_rax_rbx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x00000000FFFFFFFF, "RAX: mask to low 32 bits"); + assert_eq!( + emu.regs().rax, + 0x00000000FFFFFFFF, + "RAX: mask to low 32 bits" + ); } // ============================================================================ @@ -460,7 +496,11 @@ fn test_and_r16_rm16_ax_bx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x0204, "AX: 0x1234 AND 0x0F0F = 0x0204"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x0204, + "AX: 0x1234 AND 0x0F0F = 0x0204" + ); } #[test] @@ -531,7 +571,11 @@ fn test_and_rsi_rdi() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi, 0xAAAAAAAAAAAAAAAA, "RSI: AND with same value"); + assert_eq!( + emu.regs().rsi, + 0xAAAAAAAAAAAAAAAA, + "RSI: AND with same value" + ); } // ============================================================================ @@ -639,7 +683,8 @@ fn test_and_word_ptr_imm16() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x66, 0x81, 0x25, 0xf7, 0x0f, 0x00, 0x00, 0xF0, 0x0F, // AND WORD PTR [rip+0x0FF7], 0x0FF0 + 0x66, 0x81, 0x25, 0xf7, 0x0f, 0x00, 0x00, 0xF0, + 0x0F, // AND WORD PTR [rip+0x0FF7], 0x0FF0 0xf4, ]; emu.load_code_bytes(&code); @@ -656,7 +701,8 @@ fn test_and_dword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x81, 0x25, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, // AND DWORD PTR [rip+0x0FF6], 0x000000FF + 0x81, 0x25, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, // AND DWORD PTR [rip+0x0FF6], 0x000000FF 0xf4, ]; emu.load_code_bytes(&code); @@ -673,7 +719,8 @@ fn test_and_qword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x48, 0x81, 0x25, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, // AND QWORD PTR [rip+0x0FF5], 0x0000FFFF + 0x48, 0x81, 0x25, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, // AND QWORD PTR [rip+0x0FF5], 0x0000FFFF 0xf4, ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/mod.rs index 593449a3..538b5d2c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/mod.rs @@ -1,10 +1,10 @@ // Logical instruction tests module mod and; -mod or; -mod xor; mod not; -mod test; +mod or; +mod sar; mod shl_sal; mod shr; -mod sar; +mod test; +mod xor; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/not.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/not.rs index e6a36ac2..d73305ea 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/not.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/not.rs @@ -141,7 +141,11 @@ fn test_not_eax_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x55555555, "EAX: NOT 0xAAAAAAAA = 0x55555555"); + assert_eq!( + emu.regs().rax, + 0x55555555, + "EAX: NOT 0xAAAAAAAA = 0x55555555" + ); } #[test] @@ -153,7 +157,11 @@ fn test_not_ebx_all_zeros() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0xFFFFFFFF, "EBX: NOT 0x00000000 = 0xFFFFFFFF"); + assert_eq!( + emu.regs().rbx, + 0xFFFFFFFF, + "EBX: NOT 0x00000000 = 0xFFFFFFFF" + ); } #[test] @@ -165,7 +173,11 @@ fn test_not_ecx_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0x0000FFFF, "ECX: NOT 0xFFFF0000 = 0x0000FFFF"); + assert_eq!( + emu.regs().rcx, + 0x0000FFFF, + "ECX: NOT 0xFFFF0000 = 0x0000FFFF" + ); } #[test] @@ -177,7 +189,11 @@ fn test_not_esi() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi, 0xEDCBA987, "ESI: NOT 0x12345678 = 0xEDCBA987"); + assert_eq!( + emu.regs().rsi, + 0xEDCBA987, + "ESI: NOT 0x12345678 = 0xEDCBA987" + ); } // ============================================================================ @@ -401,7 +417,11 @@ fn test_not_not_eax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x12345678, "Double NOT EAX returns original"); + assert_eq!( + emu.regs().rax, + 0x12345678, + "Double NOT EAX returns original" + ); } #[test] @@ -417,7 +437,11 @@ fn test_not_not_rax() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "Double NOT RAX returns original"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "Double NOT RAX returns original" + ); } // ============================================================================ @@ -435,5 +459,9 @@ fn test_not_preserves_flags() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.flags().dump() & 0x8D5, initial_flags & 0x8D5, "NOT preserves all flags"); + assert_eq!( + emu.flags().dump() & 0x8D5, + initial_flags & 0x8D5, + "NOT preserves all flags" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/or.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/or.rs index df9d32d7..22038e05 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/or.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/or.rs @@ -48,7 +48,11 @@ fn test_or_al_imm8_zero_identity() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: 0x42 OR 0 = 0x42 (identity)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: 0x42 OR 0 = 0x42 (identity)" + ); } #[test] @@ -128,7 +132,11 @@ fn test_or_ax_imm16_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x123F, "AX: 0x1230 OR 0x000F = 0x123F"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x123F, + "AX: 0x1230 OR 0x000F = 0x123F" + ); } #[test] @@ -261,7 +269,11 @@ fn test_or_rm8_imm8_dh() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rdx >> 8) & 0xFF, 0xFF, "DH: 0xAA OR 0x55 = 0xFF"); + assert_eq!( + (emu.regs().rdx >> 8) & 0xFF, + 0xFF, + "DH: 0xAA OR 0x55 = 0xFF" + ); } // ============================================================================ @@ -277,7 +289,11 @@ fn test_or_rm16_imm16_bx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0xFF0F, "BX: 0xFF00 OR 0x000F = 0xFF0F"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0xFF0F, + "BX: 0xFF00 OR 0x000F = 0xFF0F" + ); } #[test] @@ -373,7 +389,11 @@ fn test_or_rm32_imm8_sign_ext() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x0000000F, "EBX: OR with sign-extended imm8"); + assert_eq!( + emu.regs().rbx, + 0x0000000F, + "EBX: OR with sign-extended imm8" + ); } #[test] @@ -415,7 +435,11 @@ fn test_or_rm16_r16_ax_bx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xFFFF, "AX: 0xFF00 OR 0x00FF = 0xFFFF"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xFFFF, + "AX: 0xFF00 OR 0x00FF = 0xFFFF" + ); } #[test] @@ -471,7 +495,11 @@ fn test_or_r16_rm16_ax_bx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1F3F, "AX: 0x1234 OR 0x0F0F = 0x1F3F"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1F3F, + "AX: 0x1234 OR 0x0F0F = 0x1F3F" + ); } #[test] @@ -484,7 +512,11 @@ fn test_or_r32_rm32_eax_ebx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFF, "EAX: alternating bits OR = all ones"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFF, + "EAX: alternating bits OR = all ones" + ); } #[test] @@ -497,7 +529,11 @@ fn test_or_r64_rm64_rax_rbx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX: alternating bytes OR = all ones"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX: alternating bytes OR = all ones" + ); } // ============================================================================ @@ -527,7 +563,11 @@ fn test_or_ecx_edx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0xFFFFFFFF, "ECX: complementary patterns OR = all ones"); + assert_eq!( + emu.regs().rcx, + 0xFFFFFFFF, + "ECX: complementary patterns OR = all ones" + ); } #[test] @@ -647,7 +687,8 @@ fn test_or_word_ptr_imm16() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x66, 0x81, 0x0d, 0xf7, 0x0f, 0x00, 0x00, 0x0F, 0x00, // OR WORD PTR [rip+0x0FF7], 0x000F + 0x66, 0x81, 0x0d, 0xf7, 0x0f, 0x00, 0x00, 0x0F, + 0x00, // OR WORD PTR [rip+0x0FF7], 0x000F 0xf4, ]; emu.load_code_bytes(&code); @@ -664,7 +705,8 @@ fn test_or_dword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x81, 0x0d, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, // OR DWORD PTR [rip+0x0FF6], 0x000000FF + 0x81, 0x0d, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, // OR DWORD PTR [rip+0x0FF6], 0x000000FF 0xf4, ]; emu.load_code_bytes(&code); @@ -681,7 +723,8 @@ fn test_or_qword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x48, 0x81, 0x0d, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, // OR QWORD PTR [rip+0x0FF5], 0x0000FFFF + 0x48, 0x81, 0x0d, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, // OR QWORD PTR [rip+0x0FF5], 0x0000FFFF 0xf4, ]; emu.load_code_bytes(&code); @@ -736,7 +779,11 @@ fn test_or_combine_flags() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x05, "Combine flags: 0x01 | 0x04 = 0x05"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x05, + "Combine flags: 0x01 | 0x04 = 0x05" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/sar.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/sar.rs index a4f6c153..b972d63b 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/sar.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/sar.rs @@ -46,7 +46,11 @@ fn test_sar_al_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xC1, "AL: 0x82 >> 1 = 0xC1 (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xC1, + "AL: 0x82 >> 1 = 0xC1 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF clear (LSB was 0)"); assert!(emu.flags().f_sf, "SF set (result is negative)"); } @@ -74,7 +78,11 @@ fn test_sar_bl_cl_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFF, 0xFF, "BL: 0x80 >> 7 = 0xFF (sign extended)"); + assert_eq!( + emu.regs().rbx & 0xFF, + 0xFF, + "BL: 0x80 >> 7 = 0xFF (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF set"); } @@ -101,7 +109,11 @@ fn test_sar_cl_imm8_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFF, 0xF1, "CL: 0x88 >> 3 = 0xF1 (sign extended)"); + assert_eq!( + emu.regs().rcx & 0xFF, + 0xF1, + "CL: 0x88 >> 3 = 0xF1 (sign extended)" + ); } #[test] @@ -126,7 +138,11 @@ fn test_sar_al_to_ff_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xFF, "AL: negative value >> 8 = 0xFF"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xFF, + "AL: negative value >> 8 = 0xFF" + ); assert!(emu.flags().f_sf, "SF set"); assert!(!emu.flags().f_zf, "ZF clear"); } @@ -141,7 +157,11 @@ fn test_sar_count_masked_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xF1, "AL: 0x88 >> 3 = 0xF1 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xF1, + "AL: 0x88 >> 3 = 0xF1 (count masked)" + ); } #[test] @@ -150,13 +170,18 @@ fn test_sar_count_zero_preserves_flags() { let mut emu = emu64(); let code = [0xc0, 0xf8, 0x00, 0xf4]; // SAR AL, 0 emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } #[test] @@ -168,7 +193,11 @@ fn test_sar_dh_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!((emu.regs().rdx >> 8) & 0xFF, 0xC1, "DH: 0x82 >> 1 = 0xC1 (sign extended)"); + assert_eq!( + (emu.regs().rdx >> 8) & 0xFF, + 0xC1, + "DH: 0x82 >> 1 = 0xC1 (sign extended)" + ); } // ============================================================================ @@ -197,7 +226,11 @@ fn test_sar_ax_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xC321, "AX: 0x8642 >> 1 = 0xC321 (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xC321, + "AX: 0x8642 >> 1 = 0xC321 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF clear"); assert!(emu.flags().f_sf, "SF set"); } @@ -212,7 +245,11 @@ fn test_sar_ax_cl_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xFFFF, "AX: 0x8000 >> 15 = 0xFFFF (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xFFFF, + "AX: 0x8000 >> 15 = 0xFFFF (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF set"); } @@ -238,7 +275,11 @@ fn test_sar_bx_imm8_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0xF923, "BX: 0x9234 >> 4 = 0xF923 (sign extended)"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0xF923, + "BX: 0x9234 >> 4 = 0xF923 (sign extended)" + ); assert!(emu.flags().f_sf, "SF set"); } @@ -264,7 +305,11 @@ fn test_sar_cx_to_ff_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFF, 0xFFFF, "CX: negative >> 16 = 0xFFFF"); + assert_eq!( + emu.regs().rcx & 0xFFFF, + 0xFFFF, + "CX: negative >> 16 = 0xFFFF" + ); assert!(emu.flags().f_sf, "SF set"); } @@ -277,7 +322,11 @@ fn test_sar_si_1_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi & 0xFFFF, 0xC001, "SI: 0x8003 >> 1 = 0xC001 (sign extended)"); + assert_eq!( + emu.regs().rsi & 0xFFFF, + 0xC001, + "SI: 0x8003 >> 1 = 0xC001 (sign extended)" + ); assert!(emu.flags().f_cf, "CF set (LSB was 1)"); } @@ -294,7 +343,11 @@ fn test_sar_eax_1_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x12345678, "EAX: 0x2468ACF0 >> 1 = 0x12345678"); + assert_eq!( + emu.regs().rax, + 0x12345678, + "EAX: 0x2468ACF0 >> 1 = 0x12345678" + ); assert!(!emu.flags().f_cf, "CF clear"); } @@ -307,7 +360,11 @@ fn test_sar_eax_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC0000000, "EAX: 0x80000000 >> 1 = 0xC0000000 (sign extended)"); + assert_eq!( + emu.regs().rax, + 0xC0000000, + "EAX: 0x80000000 >> 1 = 0xC0000000 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF clear"); assert!(emu.flags().f_sf, "SF set"); } @@ -322,7 +379,11 @@ fn test_sar_ebx_cl_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0xFFFFFFFF, "EBX: 0x80000000 >> 31 = 0xFFFFFFFF (sign extended)"); + assert_eq!( + emu.regs().rbx, + 0xFFFFFFFF, + "EBX: 0x80000000 >> 31 = 0xFFFFFFFF (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF set"); } @@ -336,7 +397,11 @@ fn test_sar_ecx_imm8_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0x00123456, "ECX: 0x12345600 >> 8 = 0x00123456"); + assert_eq!( + emu.regs().rcx, + 0x00123456, + "ECX: 0x12345600 >> 8 = 0x00123456" + ); } #[test] @@ -348,7 +413,11 @@ fn test_sar_ecx_imm8_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0xFF923456, "ECX: 0x92345600 >> 8 = 0xFF923456 (sign extended)"); + assert_eq!( + emu.regs().rcx, + 0xFF923456, + "ECX: 0x92345600 >> 8 = 0xFF923456 (sign extended)" + ); assert!(emu.flags().f_sf, "SF set"); } @@ -361,7 +430,11 @@ fn test_sar_esi_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi, 0x00005678, "ESI: 0x56780000 >> 16 = 0x00005678"); + assert_eq!( + emu.regs().rsi, + 0x00005678, + "ESI: 0x56780000 >> 16 = 0x00005678" + ); } #[test] @@ -370,7 +443,7 @@ fn test_sar_edi_to_zero_positive() { let mut emu = emu64(); let code = [ 0xc1, 0xff, 0x1f, // SAR EDI, 31 - 0xd1, 0xff, // SAR EDI, 1 + 0xd1, 0xff, // SAR EDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x12345678; @@ -387,14 +460,18 @@ fn test_sar_edi_to_ff_negative() { let mut emu = emu64(); let code = [ 0xc1, 0xff, 0x1f, // SAR EDI, 31 - 0xd1, 0xff, // SAR EDI, 1 + 0xd1, 0xff, // SAR EDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x92345678; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi, 0xFFFFFFFF, "EDI: negative >> 32 = 0xFFFFFFFF"); + assert_eq!( + emu.regs().rdi, + 0xFFFFFFFF, + "EDI: negative >> 32 = 0xFFFFFFFF" + ); assert!(emu.flags().f_sf, "SF set"); } @@ -424,7 +501,11 @@ fn test_sar_rax_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xC000000000000000, "RAX: >> 1 (sign extended)"); + assert_eq!( + emu.regs().rax, + 0xC000000000000000, + "RAX: >> 1 (sign extended)" + ); assert!(!emu.flags().f_cf, "CF clear"); assert!(emu.flags().f_sf, "SF set"); } @@ -439,7 +520,11 @@ fn test_sar_rbx_cl_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0xFFFFFFFFFFFFFFFF, "RBX: >> 63 = all ones (sign extended)"); + assert_eq!( + emu.regs().rbx, + 0xFFFFFFFFFFFFFFFF, + "RBX: >> 63 = all ones (sign extended)" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF set"); } @@ -465,7 +550,11 @@ fn test_sar_rcx_imm8_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0xFFFF923456789ABC, "RCX: >> 16 (sign extended)"); + assert_eq!( + emu.regs().rcx, + 0xFFFF923456789ABC, + "RCX: >> 16 (sign extended)" + ); assert!(emu.flags().f_sf, "SF set"); } @@ -489,14 +578,18 @@ fn test_sar_rdi_to_zero_positive() { let mut emu = emu64(); let code = [ 0x48, 0xc1, 0xff, 0x3f, // SAR RDI, 63 - 0x48, 0xd1, 0xff, // SAR RDI, 1 + 0x48, 0xd1, 0xff, // SAR RDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x123456789ABCDEF0; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi, 0x0000000000000000, "RDI: positive >> 64 = 0"); + assert_eq!( + emu.regs().rdi, + 0x0000000000000000, + "RDI: positive >> 64 = 0" + ); assert!(emu.flags().f_zf, "ZF set"); } @@ -506,14 +599,18 @@ fn test_sar_rdi_to_ff_negative() { let mut emu = emu64(); let code = [ 0x48, 0xc1, 0xff, 0x3f, // SAR RDI, 63 - 0x48, 0xd1, 0xff, // SAR RDI, 1 + 0x48, 0xd1, 0xff, // SAR RDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x923456789ABCDEF0; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi, 0xFFFFFFFFFFFFFFFF, "RDI: negative >> 64 = all ones"); + assert_eq!( + emu.regs().rdi, + 0xFFFFFFFFFFFFFFFF, + "RDI: negative >> 64 = all ones" + ); assert!(emu.flags().f_sf, "SF set"); } @@ -527,7 +624,11 @@ fn test_sar_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "RAX: 0x08 >> 3 = 0x01 (count masked)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "RAX: 0x08 >> 3 = 0x01 (count masked)" + ); } // ============================================================================ @@ -543,7 +644,11 @@ fn test_sar_r8b_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r8 & 0xFF, 0xC1, "R8B: 0x82 >> 1 = 0xC1 (sign extended)"); + assert_eq!( + emu.regs().r8 & 0xFF, + 0xC1, + "R8B: 0x82 >> 1 = 0xC1 (sign extended)" + ); } #[test] @@ -556,7 +661,11 @@ fn test_sar_r9w_cl_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r9 & 0xFFFF, 0xFFFF, "R9W: 0x8000 >> 15 = 0xFFFF (sign extended)"); + assert_eq!( + emu.regs().r9 & 0xFFFF, + 0xFFFF, + "R9W: 0x8000 >> 15 = 0xFFFF (sign extended)" + ); } #[test] @@ -592,7 +701,11 @@ fn test_sar_r11_1_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r11, 0xC000000000000000, "R11: >> 1 (sign extended)"); + assert_eq!( + emu.regs().r11, + 0xC000000000000000, + "R11: >> 1 (sign extended)" + ); } #[test] @@ -605,7 +718,11 @@ fn test_sar_r12_cl_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r12, 0xFFFFFFFF90000000, "R12: >> 32 (sign extended)"); + assert_eq!( + emu.regs().r12, + 0xFFFFFFFF90000000, + "R12: >> 32 (sign extended)" + ); } #[test] @@ -629,7 +746,11 @@ fn test_sar_r15_imm8_negative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().r15, 0xFFFF923456789ABC, "R15: >> 16 (sign extended)"); + assert_eq!( + emu.regs().r15, + 0xFFFF923456789ABC, + "R15: >> 16 (sign extended)" + ); } // ============================================================================ @@ -734,7 +855,11 @@ fn test_sar_vs_shr_positive() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x07, "AL: 0x7F >> 4 = 0x07 (same as SHR)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x07, + "AL: 0x7F >> 4 = 0x07 (same as SHR)" + ); } #[test] @@ -747,7 +872,11 @@ fn test_sar_vs_shr_negative() { emu.run(None).unwrap(); // SAR: sign extension, SHR would give 0x0F - assert_eq!(emu.regs().rax & 0xFF, 0xFF, "AL: 0xFF >> 4 = 0xFF (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xFF, + "AL: 0xFF >> 4 = 0xFF (sign extended)" + ); } #[test] @@ -763,5 +892,9 @@ fn test_sar_multiple_operations() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xE1, "AL: 0x84 >> 2 = 0xE1 (sign extended)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xE1, + "AL: 0x84 >> 2 = 0xE1 (sign extended)" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shl_sal.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shl_sal.rs index f175504c..5988e147 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shl_sal.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shl_sal.rs @@ -118,7 +118,11 @@ fn test_shl_count_masked_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x88, "AL: 0x11 << 3 = 0x88 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x88, + "AL: 0x11 << 3 = 0x88 (count masked)" + ); } #[test] @@ -127,13 +131,18 @@ fn test_shl_count_zero_preserves_flags() { let mut emu = emu64(); let code = [0xc0, 0xe0, 0x00, 0xf4]; // SHL AL, 0 emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } #[test] @@ -233,7 +242,11 @@ fn test_shl_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x2468ACF0, "EAX: 0x12345678 << 1 = 0x2468ACF0"); + assert_eq!( + emu.regs().rax, + 0x2468ACF0, + "EAX: 0x12345678 << 1 = 0x2468ACF0" + ); assert!(!emu.flags().f_cf, "CF clear"); assert!(!emu.flags().f_of, "OF clear"); } @@ -248,7 +261,11 @@ fn test_shl_ebx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x80000000, "EBX: 0x00000001 << 31 = 0x80000000"); + assert_eq!( + emu.regs().rbx, + 0x80000000, + "EBX: 0x00000001 << 31 = 0x80000000" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF set"); } @@ -262,7 +279,11 @@ fn test_shl_ecx_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0x12345600, "ECX: 0x00123456 << 8 = 0x12345600"); + assert_eq!( + emu.regs().rcx, + 0x12345600, + "ECX: 0x00123456 << 8 = 0x12345600" + ); } #[test] @@ -274,7 +295,11 @@ fn test_shl_esi_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi, 0x56780000, "ESI: 0x12345678 << 16 = 0x56780000"); + assert_eq!( + emu.regs().rsi, + 0x56780000, + "ESI: 0x12345678 << 16 = 0x56780000" + ); } #[test] @@ -283,7 +308,7 @@ fn test_shl_edi_to_zero() { let mut emu = emu64(); let code = [ 0xc1, 0xe7, 0x1f, // SHL EDI, 31 - 0xd1, 0xe7, // SHL EDI, 1 + 0xd1, 0xe7, // SHL EDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x12345678; @@ -322,7 +347,11 @@ fn test_shl_rbx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x8000000000000000, "RBX: 0x01 << 63 = 0x8000...0"); + assert_eq!( + emu.regs().rbx, + 0x8000000000000000, + "RBX: 0x01 << 63 = 0x8000...0" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); assert!(emu.flags().f_sf, "SF set"); } @@ -357,14 +386,18 @@ fn test_shl_rdi_to_zero() { let mut emu = emu64(); let code = [ 0x48, 0xc1, 0xe7, 0x3f, // SHL RDI, 63 - 0x48, 0xd1, 0xe7, // SHL RDI, 1 + 0x48, 0xd1, 0xe7, // SHL RDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x123456789ABCDEF0; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi, 0x0000000000000000, "RDI: all bits shifted out"); + assert_eq!( + emu.regs().rdi, + 0x0000000000000000, + "RDI: all bits shifted out" + ); assert!(emu.flags().f_zf, "ZF set"); } @@ -378,7 +411,11 @@ fn test_shl_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000008, "RAX: 0x01 << 3 = 0x08 (count masked)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000008, + "RAX: 0x01 << 3 = 0x08 (count masked)" + ); } // ============================================================================ diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shr.rs index ba5e6a37..5dc5a773 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/shr.rs @@ -113,7 +113,11 @@ fn test_shr_count_masked_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x11, "AL: 0x88 >> 3 = 0x11 (count masked)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x11, + "AL: 0x88 >> 3 = 0x11 (count masked)" + ); } #[test] @@ -122,13 +126,18 @@ fn test_shr_count_zero_preserves_flags() { let mut emu = emu64(); let code = [0xc0, 0xe8, 0x00, 0xf4]; // SHR AL, 0 emu.regs_mut().rax = 0x42; - emu.flags_mut().load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); + emu.flags_mut() + .load(0x2 | flags::F_CF | flags::F_ZF | flags::F_OF); let initial_flags = emu.flags().dump(); emu.load_code_bytes(&code); emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL unchanged"); - assert_eq!(emu.flags().dump(), initial_flags, "Flags unchanged when count is 0"); + assert_eq!( + emu.flags().dump(), + initial_flags, + "Flags unchanged when count is 0" + ); } #[test] @@ -240,7 +249,11 @@ fn test_shr_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x12345678, "EAX: 0x2468ACF0 >> 1 = 0x12345678"); + assert_eq!( + emu.regs().rax, + 0x12345678, + "EAX: 0x2468ACF0 >> 1 = 0x12345678" + ); assert!(!emu.flags().f_cf, "CF clear"); } @@ -254,7 +267,11 @@ fn test_shr_ebx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x00000001, "EBX: 0x80000000 >> 31 = 0x00000001"); + assert_eq!( + emu.regs().rbx, + 0x00000001, + "EBX: 0x80000000 >> 31 = 0x00000001" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); } @@ -267,7 +284,11 @@ fn test_shr_ecx_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx, 0x00123456, "ECX: 0x12345600 >> 8 = 0x00123456"); + assert_eq!( + emu.regs().rcx, + 0x00123456, + "ECX: 0x12345600 >> 8 = 0x00123456" + ); } #[test] @@ -279,7 +300,11 @@ fn test_shr_esi_with_carry() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi, 0x00005678, "ESI: 0x56780000 >> 16 = 0x00005678"); + assert_eq!( + emu.regs().rsi, + 0x00005678, + "ESI: 0x56780000 >> 16 = 0x00005678" + ); } #[test] @@ -288,7 +313,7 @@ fn test_shr_edi_to_zero() { let mut emu = emu64(); let code = [ 0xc1, 0xef, 0x1f, // SHR EDI, 31 - 0xd1, 0xef, // SHR EDI, 1 + 0xd1, 0xef, // SHR EDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x12345678; @@ -326,7 +351,11 @@ fn test_shr_rbx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x0000000000000001, "RBX: 0x8000...0 >> 63 = 0x01"); + assert_eq!( + emu.regs().rbx, + 0x0000000000000001, + "RBX: 0x8000...0 >> 63 = 0x01" + ); assert!(!emu.flags().f_cf, "CF: last bit shifted out was 0"); } @@ -360,14 +389,18 @@ fn test_shr_rdi_to_zero() { let mut emu = emu64(); let code = [ 0x48, 0xc1, 0xef, 0x3f, // SHR RDI, 63 - 0x48, 0xd1, 0xef, // SHR RDI, 1 + 0x48, 0xd1, 0xef, // SHR RDI, 1 0xf4, ]; emu.regs_mut().rdi = 0x123456789ABCDEF0; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi, 0x0000000000000000, "RDI: all bits shifted out"); + assert_eq!( + emu.regs().rdi, + 0x0000000000000000, + "RDI: all bits shifted out" + ); assert!(emu.flags().f_zf, "ZF set"); } @@ -381,7 +414,11 @@ fn test_shr_count_masked_64bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x0000000000000001, "RAX: 0x08 >> 3 = 0x01 (count masked)"); + assert_eq!( + emu.regs().rax, + 0x0000000000000001, + "RAX: 0x08 >> 3 = 0x01 (count masked)" + ); } // ============================================================================ @@ -530,7 +567,11 @@ fn test_shr_no_sign_extension() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x0F, "AL: 0xFF >> 4 = 0x0F (no sign extension)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0F, + "AL: 0xFF >> 4 = 0x0F (no sign extension)" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/test.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/test.rs index c0c7c849..714c5a00 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/test.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/test.rs @@ -507,7 +507,8 @@ fn test_test_dword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0xf7, 0x05, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, // TEST DWORD PTR [rip+0x0FF6], 0x000000FF + 0xf7, 0x05, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, // TEST DWORD PTR [rip+0x0FF6], 0x000000FF 0xf4, ]; emu.load_code_bytes(&code); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/xor.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/xor.rs index a322fbe6..941fbc04 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/xor.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/logical/xor.rs @@ -51,7 +51,11 @@ fn test_xor_al_imm8_identity() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: 0x42 XOR 0 = 0x42 (identity)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: 0x42 XOR 0 = 0x42 (identity)" + ); } #[test] @@ -63,7 +67,11 @@ fn test_xor_al_imm8_invert() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x55, "AL: 0xAA XOR 0xFF = 0x55 (inverted)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x55, + "AL: 0xAA XOR 0xFF = 0x55 (inverted)" + ); } #[test] @@ -118,7 +126,11 @@ fn test_xor_ax_imm16_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x123B, "AX: 0x1234 XOR 0x000F = 0x123B"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x123B, + "AX: 0x1234 XOR 0x000F = 0x123B" + ); } #[test] @@ -263,7 +275,11 @@ fn test_xor_rm64_r64_rax_rbx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX: all bits different"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX: all bits different" + ); } // ============================================================================ @@ -490,7 +506,8 @@ fn test_xor_word_ptr_imm16() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x66, 0x81, 0x35, 0xf7, 0x0f, 0x00, 0x00, 0xFF, 0xFF, // XOR WORD PTR [rip+0x0FF7], 0xFFFF + 0x66, 0x81, 0x35, 0xf7, 0x0f, 0x00, 0x00, 0xFF, + 0xFF, // XOR WORD PTR [rip+0x0FF7], 0xFFFF 0xf4, ]; emu.load_code_bytes(&code); @@ -507,7 +524,8 @@ fn test_xor_dword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x81, 0x35, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, // XOR DWORD PTR [rip+0x0FF6], 0x0000FFFF + 0x81, 0x35, 0xf6, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0x00, + 0x00, // XOR DWORD PTR [rip+0x0FF6], 0x0000FFFF 0xf4, ]; emu.load_code_bytes(&code); @@ -524,7 +542,8 @@ fn test_xor_qword_ptr_imm32() { let DATA_ADDR = 0x7000; let mut emu = emu64(); let code = [ - 0x48, 0x81, 0x35, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, // XOR QWORD PTR [rip+0x0FF5], 0xFFFFFFFF + 0x48, 0x81, 0x35, 0xf5, 0x0f, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, // XOR QWORD PTR [rip+0x0FF5], 0xFFFFFFFF 0xf4, ]; emu.load_code_bytes(&code); @@ -567,14 +586,22 @@ fn test_xor_toggle_bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x1F, "Toggle bit 4 on: 0x0F ^ 0x10 = 0x1F"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x1F, + "Toggle bit 4 on: 0x0F ^ 0x10 = 0x1F" + ); let code = [0x34, 0x10, 0xf4]; emu.regs_mut().rax = 0x1F; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x0F, "Toggle bit 4 off: 0x1F ^ 0x10 = 0x0F"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x0F, + "Toggle bit 4 off: 0x1F ^ 0x10 = 0x0F" + ); } #[test] @@ -595,7 +622,11 @@ fn test_xor_encryption_basic() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, plaintext, "XOR encryption/decryption"); + assert_eq!( + emu.regs().rax & 0xFF, + plaintext, + "XOR encryption/decryption" + ); } #[test] @@ -616,7 +647,11 @@ fn test_xor_commutative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, emu.regs().rax & 0xFF, "XOR is commutative"); + assert_eq!( + emu.regs().rax & 0xFF, + emu.regs().rax & 0xFF, + "XOR is commutative" + ); } #[test] @@ -638,5 +673,9 @@ fn test_xor_associative() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, emu.regs().rax & 0xFF, "XOR is associative"); + assert_eq!( + emu.regs().rax & 0xFF, + emu.regs().rax & 0xFF, + "XOR is associative" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/mod.rs index ebb0f6c3..3dd92f1e 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/mod.rs @@ -1,8 +1,8 @@ -pub mod rol; -pub mod ror; pub mod rcl; pub mod rcr; -pub mod shld; -pub mod shrd; +pub mod rol; pub mod rol_ror_extended; +pub mod ror; +pub mod shld; pub mod shld_shrd_extended; +pub mod shrd; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcl.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcl.rs index 48758beb..c7396989 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcl.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcl.rs @@ -35,13 +35,13 @@ fn test_rcl_al_1_cf_clear() { // RCL AL, 1 (opcode D0 /2) with CF clear let code = [ 0xd0, 0xd0, // RCL AL, 1 - 0xf4, // HLT + 0xf4, // HLT ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; // 0100_0010 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 0100_0010 << 1, CF(0) -> LSB = 1000_0100 assert_eq!(emu.regs().rax & 0xFF, 0x84, "AL: 0x42 RCL 1 (CF=0) = 0x84"); @@ -57,9 +57,9 @@ fn test_rcl_al_1_cf_set() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; // 0100_0010 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 0100_0010 << 1, CF(1) -> LSB = 1000_0101 assert_eq!(emu.regs().rax & 0xFF, 0x85, "AL: 0x42 RCL 1 (CF=1) = 0x85"); @@ -75,9 +75,9 @@ fn test_rcl_al_1_with_msb() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x81; // 1000_0001 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 1000_0001 << 1, CF(0) -> LSB = 0000_0010 assert_eq!(emu.regs().rax & 0xFF, 0x02, "AL: 0x81 RCL 1 (CF=0) = 0x02"); @@ -93,9 +93,9 @@ fn test_rcl_al_1_msb_and_cf() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x81; // 1000_0001 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 1000_0001 << 1, CF(1) -> LSB = 0000_0011 assert_eq!(emu.regs().rax & 0xFF, 0x03, "AL: 0x81 RCL 1 (CF=1) = 0x03"); @@ -112,9 +112,9 @@ fn test_rcl_al_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x01; // 0000_0001 emu.regs_mut().rcx = 0x04; // Rotate by 4 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // After 4 rotations through carry (9-bit total) // Initial: CF=1, AL=0000_0001 @@ -134,9 +134,9 @@ fn test_rcl_al_imm8() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x11; // 0001_0001 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x88, "AL: 0x11 RCL 3 (CF=0) = 0x88"); } @@ -150,11 +150,15 @@ fn test_rcl_full_rotation_9bit() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: full 9-bit rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: full 9-bit rotation returns to original" + ); assert!(!emu.flags().f_cf, "CF: also returns to original"); } @@ -167,15 +171,18 @@ fn test_rcl_count_zero_preserves_flags() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); + emu.load_code_bytes(&code); + emu.flags_mut() + .load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); let initial_flags = emu.flags().dump(); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: unchanged"); - assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), - initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), - "Flags preserved"); + assert_eq!( + emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), + initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), + "Flags preserved" + ); } #[test] @@ -187,9 +194,9 @@ fn test_rcl_bl() { ]; let mut emu = emu64(); emu.regs_mut().rbx = 0xC5; // 1100_0101 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rbx & 0xFF, 0x8A, "BL: 0xC5 RCL 1 (CF=0) = 0x8A"); assert!(emu.flags().f_cf, "CF: MSB was 1"); @@ -204,9 +211,9 @@ fn test_rcl_cl_reg() { ]; let mut emu = emu64(); emu.regs_mut().rcx = 0x33; // 0011_0011 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 0011_0011, CF=1 // Rot 1: 0110_0111, CF=0 @@ -224,9 +231,9 @@ fn test_rcl_dl() { let mut emu = emu64(); emu.regs_mut().rdx = 0x0F; emu.regs_mut().rcx = 0x04; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdx & 0xFF, 0xF0, "DL: 0x0F RCL 4 (CF=0) = 0xF0"); } @@ -244,11 +251,15 @@ fn test_rcl_ax_1() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x4321; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8642, "AX: 0x4321 RCL 1 (CF=0) = 0x8642"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8642, + "AX: 0x4321 RCL 1 (CF=0) = 0x8642" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -261,11 +272,15 @@ fn test_rcl_ax_1_cf_set() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x4321; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8643, "AX: 0x4321 RCL 1 (CF=1) = 0x8643"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8643, + "AX: 0x4321 RCL 1 (CF=1) = 0x8643" + ); assert!(!emu.flags().f_cf, "CF: MSB was 0"); } @@ -279,11 +294,15 @@ fn test_rcl_ax_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x1234; emu.regs_mut().rcx = 0x04; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x2340, "AX: 0x1234 RCL 4 (CF=0) = 0x2340"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x2340, + "AX: 0x1234 RCL 4 (CF=0) = 0x2340" + ); } #[test] @@ -295,11 +314,15 @@ fn test_rcl_ax_imm8() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x1234; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x3409, "AX: 0x1234 RCL 8 (CF=0) = 0x3409"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x3409, + "AX: 0x1234 RCL 8 (CF=0) = 0x3409" + ); } #[test] @@ -311,11 +334,15 @@ fn test_rcl_ax_full_rotation() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x1234; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full 17-bit rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: full 17-bit rotation returns to original" + ); } #[test] @@ -327,11 +354,15 @@ fn test_rcl_bx() { ]; let mut emu = emu64(); emu.regs_mut().rbx = 0x8000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0x0001, "BX: 0x8000 RCL 1 (CF=1) = 0x0001"); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0x0001, + "BX: 0x8000 RCL 1 (CF=1) = 0x0001" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -344,11 +375,15 @@ fn test_rcl_cx() { ]; let mut emu = emu64(); emu.regs_mut().rcx = 0xABCD; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFF, 0xBCD5, "CX: 0xABCD RCL 4 (CF=0) = 0xBCD5"); + assert_eq!( + emu.regs().rcx & 0xFFFF, + 0xBCD5, + "CX: 0xABCD RCL 4 (CF=0) = 0xBCD5" + ); } #[test] @@ -361,11 +396,15 @@ fn test_rcl_dx_cl() { let mut emu = emu64(); emu.regs_mut().rdx = 0x00FF; emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFF, 0xFF00, "DX: 0x00FF RCL 8 (CF=0) = 0xFF00"); + assert_eq!( + emu.regs().rdx & 0xFFFF, + 0xFF00, + "DX: 0x00FF RCL 8 (CF=0) = 0xFF00" + ); } // ============================================================================ @@ -381,11 +420,15 @@ fn test_rcl_eax_1() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x43218765; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x86430ECA, "EAX: 0x43218765 RCL 1 (CF=0) = 0x86430ECA"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x86430ECA, + "EAX: 0x43218765 RCL 1 (CF=0) = 0x86430ECA" + ); } #[test] @@ -397,11 +440,15 @@ fn test_rcl_eax_1_cf_set() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x43218765; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x86430ECB, "EAX: 0x43218765 RCL 1 (CF=1) = 0x86430ECB"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x86430ECB, + "EAX: 0x43218765 RCL 1 (CF=1) = 0x86430ECB" + ); } #[test] @@ -414,11 +461,15 @@ fn test_rcl_eax_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x34567809, "EAX: 0x12345678 RCL 8 (CF=0) = 0x34567809"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x34567809, + "EAX: 0x12345678 RCL 8 (CF=0) = 0x34567809" + ); } #[test] @@ -430,11 +481,15 @@ fn test_rcl_eax_imm8() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x5678091A, "EAX: 0x12345678 RCL 16 (CF=0) = 0x5678091A"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x5678091A, + "EAX: 0x12345678 RCL 16 (CF=0) = 0x5678091A" + ); } #[test] @@ -446,12 +501,16 @@ fn test_rcl_eax_full_rotation() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 33 & 31 = 1, so effective count is 1 - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2468ACF0, "EAX: RCL 33 (masked to 1) = 0x2468ACF0"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2468ACF0, + "EAX: RCL 33 (masked to 1) = 0x2468ACF0" + ); } #[test] @@ -463,11 +522,15 @@ fn test_rcl_ebx() { ]; let mut emu = emu64(); emu.regs_mut().rbx = 0x80000000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x00000000, "EBX: 0x80000000 RCL 1 (CF=0) = 0x00000000"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x00000000, + "EBX: 0x80000000 RCL 1 (CF=0) = 0x00000000" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -480,11 +543,15 @@ fn test_rcl_ecx() { ]; let mut emu = emu64(); emu.regs_mut().rcx = 0xABCDEF01; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0xBCDEF015, "ECX: 0xABCDEF01 RCL 4 (CF=0) = 0xBCDEF015"); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0xBCDEF015, + "ECX: 0xABCDEF01 RCL 4 (CF=0) = 0xBCDEF015" + ); } #[test] @@ -497,11 +564,15 @@ fn test_rcl_edx_cl() { let mut emu = emu64(); emu.regs_mut().rdx = 0x000000FF; emu.regs_mut().rcx = 0x18; // 24 bits - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0xFF000000, "EDX: 0x000000FF RCL 24 (CF=0) = 0xFF000000"); + assert_eq!( + emu.regs().rdx & 0xFFFFFFFF, + 0xFF000000, + "EDX: 0x000000FF RCL 24 (CF=0) = 0xFF000000" + ); } #[test] @@ -513,11 +584,15 @@ fn test_rcl_esi() { ]; let mut emu = emu64(); emu.regs_mut().rsi = 0x40000000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0x80000001, "ESI: 0x40000000 RCL 1 (CF=1) = 0x80000001"); + assert_eq!( + emu.regs().rsi & 0xFFFFFFFF, + 0x80000001, + "ESI: 0x40000000 RCL 1 (CF=1) = 0x80000001" + ); } #[test] @@ -529,11 +604,15 @@ fn test_rcl_edi() { ]; let mut emu = emu64(); emu.regs_mut().rdi = 0x12345678; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi & 0xFFFFFFFF, 0x45678091, "EDI: 0x12345678 RCL 12 (CF=0) = 0x45678091"); + assert_eq!( + emu.regs().rdi & 0xFFFFFFFF, + 0x45678091, + "EDI: 0x12345678 RCL 12 (CF=0) = 0x45678091" + ); } // ============================================================================ @@ -549,9 +628,9 @@ fn test_rcl_rax_1() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x4321876543218765; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0x86430ECA86430ECA, "RAX: RCL 1 (CF=0)"); } @@ -565,9 +644,9 @@ fn test_rcl_rax_1_cf_set() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x4321876543218765; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0x86430ECA86430ECB, "RAX: RCL 1 (CF=1)"); } @@ -582,11 +661,15 @@ fn test_rcl_rax_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x3456789ABCDEF009, "RAX: 0x123456789ABCDEF0 RCL 8 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x3456789ABCDEF009, + "RAX: 0x123456789ABCDEF0 RCL 8 (CF=0)" + ); } #[test] @@ -598,11 +681,15 @@ fn test_rcl_rax_imm8() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x56789ABCDEF0091A, "RAX: 0x123456789ABCDEF0 RCL 16 (CF=0)"); + assert_eq!( + emu.regs().rax, + 0x56789ABCDEF0091A, + "RAX: 0x123456789ABCDEF0 RCL 16 (CF=0)" + ); } #[test] @@ -614,9 +701,9 @@ fn test_rcl_rax_32bits() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0x9ABCDEF0091A2B3C, "RAX: RCL 32 (CF=0)"); } @@ -630,11 +717,15 @@ fn test_rcl_rbx() { ]; let mut emu = emu64(); emu.regs_mut().rbx = 0x8000000000000000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x0000000000000000, "RBX: 0x8000000000000000 RCL 1 (CF=0) = 0"); + assert_eq!( + emu.regs().rbx, + 0x0000000000000000, + "RBX: 0x8000000000000000 RCL 1 (CF=0) = 0" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -647,9 +738,9 @@ fn test_rcl_rcx() { ]; let mut emu = emu64(); emu.regs_mut().rcx = 0xABCDEF0123456789; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rcx, 0xBCDEF01234567895, "RCX: RCL 4 (CF=0)"); } @@ -664,9 +755,9 @@ fn test_rcl_rdx_cl() { let mut emu = emu64(); emu.regs_mut().rdx = 0x00000000000000FF; emu.regs_mut().rcx = 0x38; // 56 bits - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdx, 0xFF00000000000000, "RDX: RCL 56 (CF=0)"); } @@ -680,9 +771,9 @@ fn test_rcl_rsi() { ]; let mut emu = emu64(); emu.regs_mut().rsi = 0x4000000000000000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rsi, 0x8000000000000001, "RSI: RCL 1 (CF=1)"); } @@ -696,9 +787,9 @@ fn test_rcl_rdi() { ]; let mut emu = emu64(); emu.regs_mut().rdi = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdi, 0x456789ABCDEF0091, "RDI: RCL 12 (CF=0)"); } @@ -712,9 +803,9 @@ fn test_rcl_r8() { ]; let mut emu = emu64(); emu.regs_mut().r8 = 0xFEDCBA9876543210; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r8, 0xFDB97530ECA86420, "R8: RCL 1 (CF=0)"); assert!(emu.flags().f_cf, "CF: MSB was 1"); @@ -730,9 +821,9 @@ fn test_rcl_r9_cl() { let mut emu = emu64(); emu.regs_mut().r9 = 0x0123456789ABCDEF; emu.regs_mut().rcx = 0x10; // 16 bits - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r9, 0x456789ABCDEF0091, "R9: RCL 16 (CF=0)"); } @@ -746,9 +837,9 @@ fn test_rcl_r10_imm8() { ]; let mut emu = emu64(); emu.regs_mut().r10 = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r10, 0x3456789ABCDEF009, "R10: RCL 8 (CF=0)"); } @@ -762,9 +853,9 @@ fn test_rcl_r15() { ]; let mut emu = emu64(); emu.regs_mut().r15 = 0x1111111111111111; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r15, 0x2222222222222223, "R15: RCL 1 (CF=1)"); } @@ -779,7 +870,9 @@ fn test_rcl_mem8() { // RCL byte [DATA_ADDR], 1 let code = [ - 0xd0, 0x14, 0x25, // RCL byte ptr [disp32], 1 + 0xd0, + 0x14, + 0x25, // RCL byte ptr [disp32], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -787,13 +880,24 @@ fn test_rcl_mem8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); - emu.load_code_bytes(&code); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.maps.write_byte(DATA_ADDR, 0x81); + emu.maps.write_byte(DATA_ADDR, 0x81); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 0x02, "Memory: 0x81 RCL 1 (CF=0) = 0x02"); + assert_eq!( + emu.maps.read_byte(DATA_ADDR).unwrap(), + 0x02, + "Memory: 0x81 RCL 1 (CF=0) = 0x02" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -803,7 +907,10 @@ fn test_rcl_mem16() { // RCL word [DATA_ADDR], 4 let code = [ - 0x66, 0xc1, 0x14, 0x25, // RCL word ptr [disp32], imm8 + 0x66, + 0xc1, + 0x14, + 0x25, // RCL word ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -812,13 +919,24 @@ fn test_rcl_mem16() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); - emu.load_code_bytes(&code); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.maps.write_word(DATA_ADDR, 0x1234); + emu.maps.write_word(DATA_ADDR, 0x1234); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0x2340, "Memory: 0x1234 RCL 4 (CF=0) = 0x2340"); + assert_eq!( + emu.maps.read_word(DATA_ADDR).unwrap(), + 0x2340, + "Memory: 0x1234 RCL 4 (CF=0) = 0x2340" + ); } #[test] @@ -827,7 +945,9 @@ fn test_rcl_mem32() { // RCL dword [DATA_ADDR], CL let code = [ - 0xd3, 0x14, 0x25, // RCL dword ptr [disp32], CL + 0xd3, + 0x14, + 0x25, // RCL dword ptr [disp32], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -835,14 +955,25 @@ fn test_rcl_mem32() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.maps.write_dword(DATA_ADDR, 0x12345678); + emu.maps.write_dword(DATA_ADDR, 0x12345678); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0x34567809, "Memory: 0x12345678 RCL 8 (CF=0) = 0x34567809"); + assert_eq!( + emu.maps.read_dword(DATA_ADDR).unwrap(), + 0x34567809, + "Memory: 0x12345678 RCL 8 (CF=0) = 0x34567809" + ); } #[test] @@ -851,7 +982,10 @@ fn test_rcl_mem64() { // RCL qword [DATA_ADDR], 16 let code = [ - 0x48, 0xc1, 0x14, 0x25, // RCL qword ptr [disp32], imm8 + 0x48, + 0xc1, + 0x14, + 0x25, // RCL qword ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -860,11 +994,22 @@ fn test_rcl_mem64() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); - emu.load_code_bytes(&code); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); + emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0x56789ABCDEF0091A, "Memory: RCL 16 (CF=0)"); + assert_eq!( + emu.maps.read_qword(DATA_ADDR).unwrap(), + 0x56789ABCDEF0091A, + "Memory: RCL 16 (CF=0)" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcr.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcr.rs index 7bdfe520..736ad9b2 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcr.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rcr.rs @@ -35,13 +35,13 @@ fn test_rcr_al_1_cf_clear() { // RCR AL, 1 (opcode D0 /3) with CF clear let code = [ 0xd0, 0xd8, // RCR AL, 1 - 0xf4, // HLT + 0xf4, // HLT ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; // 0100_0010 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 0100_0010 >> 1, CF(0) -> MSB = 0010_0001 assert_eq!(emu.regs().rax & 0xFF, 0x21, "AL: 0x42 RCR 1 (CF=0) = 0x21"); @@ -57,9 +57,9 @@ fn test_rcr_al_1_cf_set() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; // 0100_0010 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 0100_0010 >> 1, CF(1) -> MSB = 1010_0001 assert_eq!(emu.regs().rax & 0xFF, 0xA1, "AL: 0x42 RCR 1 (CF=1) = 0xA1"); @@ -75,9 +75,9 @@ fn test_rcr_al_1_with_lsb() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x81; // 1000_0001 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 1000_0001 >> 1, CF(0) -> MSB = 0100_0000 assert_eq!(emu.regs().rax & 0xFF, 0x40, "AL: 0x81 RCR 1 (CF=0) = 0x40"); @@ -93,9 +93,9 @@ fn test_rcr_al_1_lsb_and_cf() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x81; // 1000_0001 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 1000_0001 >> 1, CF(1) -> MSB = 1100_0000 assert_eq!(emu.regs().rax & 0xFF, 0xC0, "AL: 0x81 RCR 1 (CF=1) = 0xC0"); @@ -112,9 +112,9 @@ fn test_rcr_al_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x10; // 0001_0000 emu.regs_mut().rcx = 0x04; // Rotate by 4 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // After 4 rotations right through carry (9-bit total) // Initial: CF=1, AL=0001_0000 @@ -134,9 +134,9 @@ fn test_rcr_al_imm8() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x88; // 1000_1000 - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x11, "AL: 0x88 RCR 3 (CF=0) = 0x11"); } @@ -150,11 +150,15 @@ fn test_rcr_full_rotation_9bit() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: full 9-bit rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: full 9-bit rotation returns to original" + ); assert!(!emu.flags().f_cf, "CF: also returns to original"); } @@ -167,15 +171,18 @@ fn test_rcr_count_zero_preserves_flags() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); + emu.load_code_bytes(&code); + emu.flags_mut() + .load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); let initial_flags = emu.flags().dump(); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: unchanged"); - assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), - initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), - "Flags preserved"); + assert_eq!( + emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), + initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), + "Flags preserved" + ); } #[test] @@ -183,9 +190,9 @@ fn test_rcr_bl() { let code = [0xd0, 0xdb, 0xf4]; // RCR BL, 1 let mut emu = emu64(); emu.regs_mut().rbx = 0xC5; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rbx & 0xFF, 0x62, "BL: 0xC5 RCR 1 (CF=0) = 0x62"); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -195,9 +202,9 @@ fn test_rcr_cl_reg() { let code = [0xc0, 0xd9, 0x02, 0xf4]; // RCR CL, 2 let mut emu = emu64(); emu.regs_mut().rcx = 0xCC; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rcx & 0xFF, 0x73, "CL: 0xCC RCR 2 (CF=1)"); } @@ -207,9 +214,9 @@ fn test_rcr_dl() { let mut emu = emu64(); emu.regs_mut().rdx = 0xF0; emu.regs_mut().rcx = 0x04; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdx & 0xFF, 0x0F, "DL: 0xF0 RCR 4 (CF=0) = 0x0F"); } @@ -222,10 +229,14 @@ fn test_rcr_ax_1() { let code = [0x66, 0xd1, 0xd8, 0xf4]; // RCR AX, 1 let mut emu = emu64(); emu.regs_mut().rax = 0x8642; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x4321, "AX: 0x8642 RCR 1 (CF=0) = 0x4321"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x4321, + "AX: 0x8642 RCR 1 (CF=0) = 0x4321" + ); } #[test] @@ -233,10 +244,14 @@ fn test_rcr_ax_1_cf_set() { let code = [0x66, 0xd1, 0xd8, 0xf4]; // RCR AX, 1 let mut emu = emu64(); emu.regs_mut().rax = 0x8642; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xC321, "AX: 0x8642 RCR 1 (CF=1) = 0xC321"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xC321, + "AX: 0x8642 RCR 1 (CF=1) = 0xC321" + ); } #[test] @@ -245,9 +260,9 @@ fn test_rcr_ax_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x1234; emu.regs_mut().rcx = 0x04; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0x8123, "AX: 0x1234 RCR 4 (CF=0)"); } @@ -256,9 +271,9 @@ fn test_rcr_ax_imm8() { let code = [0x66, 0xc1, 0xd8, 0x08, 0xf4]; // RCR AX, 8 let mut emu = emu64(); emu.regs_mut().rax = 0x1234; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0x6812, "AX: 0x1234 RCR 8 (CF=0)"); } @@ -267,9 +282,9 @@ fn test_rcr_ax_full_rotation() { let code = [0x66, 0xc1, 0xd8, 0x11, 0xf4]; // RCR AX, 17 let mut emu = emu64(); emu.regs_mut().rax = 0x1234; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full 17-bit rotation"); } @@ -278,10 +293,14 @@ fn test_rcr_bx() { let code = [0x66, 0xd1, 0xdb, 0xf4]; // RCR BX, 1 let mut emu = emu64(); emu.regs_mut().rbx = 0x0001; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFF, 0x8000, "BX: 0x0001 RCR 1 (CF=1) = 0x8000"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rbx & 0xFFFF, + 0x8000, + "BX: 0x0001 RCR 1 (CF=1) = 0x8000" + ); } #[test] @@ -289,9 +308,9 @@ fn test_rcr_cx() { let code = [0x66, 0xc1, 0xd9, 0x04, 0xf4]; // RCR CX, 4 let mut emu = emu64(); emu.regs_mut().rcx = 0xABCD; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rcx & 0xFFFF, 0xAABC, "CX: 0xABCD RCR 4 (CF=0)"); } @@ -301,9 +320,9 @@ fn test_rcr_dx_cl() { let mut emu = emu64(); emu.regs_mut().rdx = 0xFF00; emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdx & 0xFFFF, 0x00FF, "DX: 0xFF00 RCR 8 (CF=0)"); } @@ -316,9 +335,9 @@ fn test_rcr_eax_1() { let code = [0xd1, 0xd8, 0xf4]; // RCR EAX, 1 let mut emu = emu64(); emu.regs_mut().rax = 0x86430ECA; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x43218765, "EAX: RCR 1 (CF=0)"); } @@ -327,9 +346,9 @@ fn test_rcr_eax_1_cf_set() { let code = [0xd1, 0xd8, 0xf4]; // RCR EAX, 1 let mut emu = emu64(); emu.regs_mut().rax = 0x86430ECA; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xC3218765, "EAX: RCR 1 (CF=1)"); } @@ -339,9 +358,9 @@ fn test_rcr_eax_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xF0123456, "EAX: RCR 8 (CF=0)"); } @@ -350,10 +369,14 @@ fn test_rcr_eax_imm8() { let code = [0xc1, 0xd8, 0x10, 0xf4]; // RCR EAX, 16 let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xACF01234, "EAX: RCR 16 (CF=0)"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xACF01234, + "EAX: RCR 16 (CF=0)" + ); } #[test] @@ -362,11 +385,15 @@ fn test_rcr_eax_full_rotation() { let code = [0xc1, 0xd8, 0x21, 0xf4]; // RCR EAX, 33 let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); // 33 & 31 = 1, so effective count is 1 - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x091A2B3C, "EAX: RCR 33 (masked to 1)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x091A2B3C, + "EAX: RCR 33 (masked to 1)" + ); } #[test] @@ -374,9 +401,9 @@ fn test_rcr_ebx() { let code = [0xd1, 0xdb, 0xf4]; // RCR EBX, 1 let mut emu = emu64(); emu.regs_mut().rbx = 0x00000001; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x00000000, "EBX: RCR 1 (CF=0)"); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -386,9 +413,9 @@ fn test_rcr_ecx() { let code = [0xc1, 0xd9, 0x04, 0xf4]; // RCR ECX, 4 let mut emu = emu64(); emu.regs_mut().rcx = 0xABCDEF01; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0x2ABCDEF0, "ECX: RCR 4 (CF=0)"); } @@ -398,10 +425,14 @@ fn test_rcr_edx_cl() { let mut emu = emu64(); emu.regs_mut().rdx = 0xFF000000; emu.regs_mut().rcx = 0x18; // 24 bits - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0x000000FF, "EDX: RCR 24 (CF=0)"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rdx & 0xFFFFFFFF, + 0x000000FF, + "EDX: RCR 24 (CF=0)" + ); } #[test] @@ -409,9 +440,9 @@ fn test_rcr_esi() { let code = [0xd1, 0xde, 0xf4]; // RCR ESI, 1 let mut emu = emu64(); emu.regs_mut().rsi = 0x80000000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0xC0000000, "ESI: RCR 1 (CF=1)"); } @@ -420,10 +451,14 @@ fn test_rcr_edi() { let code = [0xc1, 0xdf, 0x0C, 0xf4]; // RCR EDI, 12 let mut emu = emu64(); emu.regs_mut().rdi = 0x12345678; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi & 0xFFFFFFFF, 0xCF012345, "EDI: RCR 12 (CF=0)"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rdi & 0xFFFFFFFF, + 0xCF012345, + "EDI: RCR 12 (CF=0)" + ); } // ============================================================================ @@ -435,9 +470,9 @@ fn test_rcr_rax_1() { let code = [0x48, 0xd1, 0xd8, 0xf4]; // RCR RAX, 1 let mut emu = emu64(); emu.regs_mut().rax = 0x86430ECA86430ECA; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0x4321876543218765, "RAX: RCR 1 (CF=0)"); } @@ -446,9 +481,9 @@ fn test_rcr_rax_1_cf_set() { let code = [0x48, 0xd1, 0xd8, 0xf4]; // RCR RAX, 1 let mut emu = emu64(); emu.regs_mut().rax = 0x86430ECA86430ECA; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0xC321876543218765, "RAX: RCR 1 (CF=1)"); } @@ -458,9 +493,9 @@ fn test_rcr_rax_cl() { let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0xE0123456789ABCDE, "RAX: RCR 8 (CF=0)"); } @@ -469,9 +504,9 @@ fn test_rcr_rax_imm8() { let code = [0x48, 0xc1, 0xd8, 0x10, 0xf4]; // RCR RAX, 16 let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0xBDE0123456789ABC, "RAX: RCR 16 (CF=0)"); } @@ -480,9 +515,9 @@ fn test_rcr_rax_32bits() { let code = [0x48, 0xc1, 0xd8, 0x20, 0xf4]; // RCR RAX, 32 let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0x3579BDE012345678, "RAX: RCR 32 (CF=0)"); } @@ -491,9 +526,9 @@ fn test_rcr_rbx() { let code = [0x48, 0xd1, 0xdb, 0xf4]; // RCR RBX, 1 let mut emu = emu64(); emu.regs_mut().rbx = 0x0000000000000001; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rbx, 0x0000000000000000, "RBX: RCR 1 (CF=0)"); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -503,9 +538,9 @@ fn test_rcr_rcx() { let code = [0x48, 0xc1, 0xd9, 0x04, 0xf4]; // RCR RCX, 4 let mut emu = emu64(); emu.regs_mut().rcx = 0xABCDEF0123456789; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rcx, 0x2ABCDEF012345678, "RCX: RCR 4 (CF=0)"); } @@ -515,9 +550,9 @@ fn test_rcr_rdx_cl() { let mut emu = emu64(); emu.regs_mut().rdx = 0xFF00000000000000; emu.regs_mut().rcx = 0x38; // 56 bits - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdx, 0x00000000000000FF, "RDX: RCR 56 (CF=0)"); } @@ -526,9 +561,9 @@ fn test_rcr_rsi() { let code = [0x48, 0xd1, 0xde, 0xf4]; // RCR RSI, 1 let mut emu = emu64(); emu.regs_mut().rsi = 0x8000000000000000; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rsi, 0xC000000000000000, "RSI: RCR 1 (CF=1)"); } @@ -537,9 +572,9 @@ fn test_rcr_rdi() { let code = [0x48, 0xc1, 0xdf, 0x0C, 0xf4]; // RCR RDI, 12 let mut emu = emu64(); emu.regs_mut().rdi = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rdi, 0xDE0123456789ABCD, "RDI: RCR 12 (CF=0)"); } @@ -548,9 +583,9 @@ fn test_rcr_r8() { let code = [0x49, 0xd1, 0xd8, 0xf4]; // RCR R8, 1 let mut emu = emu64(); emu.regs_mut().r8 = 0xFEDCBA9876543210; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r8, 0x7F6E5D4C3B2A1908, "R8: RCR 1 (CF=0)"); } @@ -560,9 +595,9 @@ fn test_rcr_r9_cl() { let mut emu = emu64(); emu.regs_mut().r9 = 0x0123456789ABCDEF; emu.regs_mut().rcx = 0x10; // 16 bits - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r9, 0x9BDE0123456789AB, "R9: RCR 16 (CF=0)"); } @@ -571,9 +606,9 @@ fn test_rcr_r10_imm8() { let code = [0x49, 0xc1, 0xda, 0x08, 0xf4]; // RCR R10, 8 let mut emu = emu64(); emu.regs_mut().r10 = 0x123456789ABCDEF0; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r10, 0xE0123456789ABCDE, "R10: RCR 8 (CF=0)"); } @@ -582,9 +617,9 @@ fn test_rcr_r15() { let code = [0x49, 0xd1, 0xdf, 0xf4]; // RCR R15, 1 let mut emu = emu64(); emu.regs_mut().r15 = 0x2222222222222222; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().r15, 0x9111111111111111, "R15: RCR 1 (CF=1)"); } @@ -596,7 +631,9 @@ fn test_rcr_r15() { fn test_rcr_mem8() { let DATA_ADDR = 0x7000; let code = [ - 0xd0, 0x1c, 0x25, // RCR byte ptr [disp32], 1 + 0xd0, + 0x1c, + 0x25, // RCR byte ptr [disp32], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -604,12 +641,23 @@ fn test_rcr_mem8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2); - emu.maps.write_byte(DATA_ADDR, 0x81); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); + emu.load_code_bytes(&code); + emu.flags_mut().load(0x2); + emu.maps.write_byte(DATA_ADDR, 0x81); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 0x40, "Memory: 0x81 RCR 1 (CF=0) = 0x40"); + assert_eq!( + emu.maps.read_byte(DATA_ADDR).unwrap(), + 0x40, + "Memory: 0x81 RCR 1 (CF=0) = 0x40" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -617,7 +665,10 @@ fn test_rcr_mem8() { fn test_rcr_mem16() { let DATA_ADDR = 0x7000; let code = [ - 0x66, 0xc1, 0x1c, 0x25, // RCR word ptr [disp32], imm8 + 0x66, + 0xc1, + 0x1c, + 0x25, // RCR word ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -626,19 +677,32 @@ fn test_rcr_mem16() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2); - emu.maps.write_word(DATA_ADDR, 0x1234); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); + emu.load_code_bytes(&code); + emu.flags_mut().load(0x2); + emu.maps.write_word(DATA_ADDR, 0x1234); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0x8123, "Memory: 0x1234 RCR 4 (CF=0)"); + assert_eq!( + emu.maps.read_word(DATA_ADDR).unwrap(), + 0x8123, + "Memory: 0x1234 RCR 4 (CF=0)" + ); } #[test] fn test_rcr_mem32() { let DATA_ADDR = 0x7000; let code = [ - 0xd3, 0x1c, 0x25, // RCR dword ptr [disp32], CL + 0xd3, + 0x1c, + 0x25, // RCR dword ptr [disp32], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -646,20 +710,34 @@ fn test_rcr_mem32() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rcx = 0x08; - emu.load_code_bytes(&code); + emu.load_code_bytes(&code); emu.flags_mut().load(0x2); - emu.maps.write_dword(DATA_ADDR, 0x12345678); + emu.maps.write_dword(DATA_ADDR, 0x12345678); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0xF0123456, "Memory: 0x12345678 RCR 8 (CF=0)"); + assert_eq!( + emu.maps.read_dword(DATA_ADDR).unwrap(), + 0xF0123456, + "Memory: 0x12345678 RCR 8 (CF=0)" + ); } #[test] fn test_rcr_mem64() { let DATA_ADDR = 0x7000; let code = [ - 0x48, 0xc1, 0x1c, 0x25, // RCR qword ptr [disp32], imm8 + 0x48, + 0xc1, + 0x1c, + 0x25, // RCR qword ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -668,11 +746,21 @@ fn test_rcr_mem64() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2); - emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); + emu.load_code_bytes(&code); + emu.flags_mut().load(0x2); + emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0xBDE0123456789ABC, "Memory: RCR 16 (CF=0)"); + assert_eq!( + emu.maps.read_qword(DATA_ADDR).unwrap(), + 0xBDE0123456789ABC, + "Memory: RCR 16 (CF=0)" + ); } - diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol.rs index 4cf2f22b..01c7e3a1 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol.rs @@ -34,7 +34,7 @@ fn test_rol_al_1() { // ROL AL, 1 (opcode D0 /0) let code = [ 0xd0, 0xc0, // ROL AL, 1 - 0xf4, // HLT + 0xf4, // HLT ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; // 0100_0010 @@ -58,7 +58,11 @@ fn test_rol_al_1_with_msb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x03, "AL: 0x81 ROL 1 = 0x03 (MSB rotates to LSB)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x03, + "AL: 0x81 ROL 1 = 0x03 (MSB rotates to LSB)" + ); assert!(emu.flags().f_cf, "CF: receives MSB (was 1)"); } @@ -107,7 +111,11 @@ fn test_rol_full_rotation_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: full rotation returns to original" + ); } #[test] @@ -136,15 +144,18 @@ fn test_rol_count_zero_preserves_flags() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); + emu.load_code_bytes(&code); + emu.flags_mut() + .load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); let initial_flags = emu.flags().dump(); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: unchanged"); - assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), - initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), - "Flags preserved"); + assert_eq!( + emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), + initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), + "Flags preserved" + ); } #[test] @@ -242,7 +253,11 @@ fn test_rol_ax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x3412, "AX: 0x1234 ROL 8 = 0x3412 (byte swap)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x3412, + "AX: 0x1234 ROL 8 = 0x3412 (byte swap)" + ); } #[test] @@ -257,7 +272,11 @@ fn test_rol_ax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: full rotation returns to original" + ); } #[test] @@ -323,7 +342,11 @@ fn test_rol_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x86430ECA, "EAX: 0x43218765 ROL 1 = 0x86430ECA"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x86430ECA, + "EAX: 0x43218765 ROL 1 = 0x86430ECA" + ); } #[test] @@ -339,7 +362,11 @@ fn test_rol_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x34567812, "EAX: 0x12345678 ROL 8 = 0x34567812"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x34567812, + "EAX: 0x12345678 ROL 8 = 0x34567812" + ); } #[test] @@ -354,7 +381,11 @@ fn test_rol_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x56781234, "EAX: 0x12345678 ROL 16 = 0x56781234"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x56781234, + "EAX: 0x12345678 ROL 16 = 0x56781234" + ); } #[test] @@ -369,7 +400,11 @@ fn test_rol_eax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: full rotation returns to original" + ); } #[test] @@ -384,7 +419,11 @@ fn test_rol_ebx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x00000001, "EBX: 0x80000000 ROL 1 = 0x00000001"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x00000001, + "EBX: 0x80000000 ROL 1 = 0x00000001" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -400,7 +439,11 @@ fn test_rol_ecx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0xBCDEF01A, "ECX: 0xABCDEF01 ROL 4 = 0xBCDEF01A"); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0xBCDEF01A, + "ECX: 0xABCDEF01 ROL 4 = 0xBCDEF01A" + ); } #[test] @@ -416,7 +459,11 @@ fn test_rol_edx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0xFF000000, "EDX: 0x000000FF ROL 24 = 0xFF000000"); + assert_eq!( + emu.regs().rdx & 0xFFFFFFFF, + 0xFF000000, + "EDX: 0x000000FF ROL 24 = 0xFF000000" + ); } #[test] @@ -431,7 +478,11 @@ fn test_rol_esi() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0x80000000, "ESI: 0x40000000 ROL 1 = 0x80000000"); + assert_eq!( + emu.regs().rsi & 0xFFFFFFFF, + 0x80000000, + "ESI: 0x40000000 ROL 1 = 0x80000000" + ); } #[test] @@ -446,7 +497,11 @@ fn test_rol_edi() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi & 0xFFFFFFFF, 0x45678123, "EDI: 0x12345678 ROL 12 = 0x45678123"); + assert_eq!( + emu.regs().rdi & 0xFFFFFFFF, + 0x45678123, + "EDI: 0x12345678 ROL 12 = 0x45678123" + ); } // ============================================================================ @@ -481,7 +536,11 @@ fn test_rol_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x3456789ABCDEF012, "RAX: 0x123456789ABCDEF0 ROL 8"); + assert_eq!( + emu.regs().rax, + 0x3456789ABCDEF012, + "RAX: 0x123456789ABCDEF0 ROL 8" + ); } #[test] @@ -496,7 +555,11 @@ fn test_rol_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x56789ABCDEF01234, "RAX: 0x123456789ABCDEF0 ROL 16"); + assert_eq!( + emu.regs().rax, + 0x56789ABCDEF01234, + "RAX: 0x123456789ABCDEF0 ROL 16" + ); } #[test] @@ -511,7 +574,11 @@ fn test_rol_rax_32bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x9ABCDEF012345678, "RAX: ROL 32 swaps high/low dwords"); + assert_eq!( + emu.regs().rax, + 0x9ABCDEF012345678, + "RAX: ROL 32 swaps high/low dwords" + ); } #[test] @@ -526,7 +593,11 @@ fn test_rol_rax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: full rotation returns to original" + ); } #[test] @@ -541,7 +612,11 @@ fn test_rol_rbx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x0000000000000001, "RBX: 0x8000000000000000 ROL 1 = 0x0000000000000001"); + assert_eq!( + emu.regs().rbx, + 0x0000000000000001, + "RBX: 0x8000000000000000 ROL 1 = 0x0000000000000001" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -678,7 +753,9 @@ fn test_rol_mem8() { // ROL byte [DATA_ADDR], 1 let code = [ - 0xd0, 0x04, 0x25, // ROL byte ptr [disp32], 1 + 0xd0, + 0x04, + 0x25, // ROL byte ptr [disp32], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -686,12 +763,23 @@ fn test_rol_mem8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.load_code_bytes(&code); emu.maps.write_byte(DATA_ADDR, 0x81); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 0x03, "Memory: 0x81 ROL 1 = 0x03"); + assert_eq!( + emu.maps.read_byte(DATA_ADDR).unwrap(), + 0x03, + "Memory: 0x81 ROL 1 = 0x03" + ); assert!(emu.flags().f_cf, "CF: MSB was 1"); } @@ -701,7 +789,10 @@ fn test_rol_mem16() { // ROL word [DATA_ADDR], 4 let code = [ - 0x66, 0xc1, 0x04, 0x25, // ROL word ptr [disp32], imm8 + 0x66, + 0xc1, + 0x04, + 0x25, // ROL word ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -710,12 +801,23 @@ fn test_rol_mem16() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, 0x1234); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0x2341, "Memory: 0x1234 ROL 4 = 0x2341"); + assert_eq!( + emu.maps.read_word(DATA_ADDR).unwrap(), + 0x2341, + "Memory: 0x1234 ROL 4 = 0x2341" + ); } #[test] @@ -724,7 +826,9 @@ fn test_rol_mem32() { // ROL dword [DATA_ADDR], CL let code = [ - 0xd3, 0x04, 0x25, // ROL dword ptr [disp32], CL + 0xd3, + 0x04, + 0x25, // ROL dword ptr [disp32], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -732,13 +836,24 @@ fn test_rol_mem32() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rcx = 0x08; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, 0x12345678); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0x34567812, "Memory: 0x12345678 ROL 8 = 0x34567812"); + assert_eq!( + emu.maps.read_dword(DATA_ADDR).unwrap(), + 0x34567812, + "Memory: 0x12345678 ROL 8 = 0x34567812" + ); } #[test] @@ -747,7 +862,10 @@ fn test_rol_mem64() { // ROL qword [DATA_ADDR], 16 let code = [ - 0x48, 0xc1, 0x04, 0x25, // ROL qword ptr [disp32], imm8 + 0x48, + 0xc1, + 0x04, + 0x25, // ROL qword ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -756,10 +874,21 @@ fn test_rol_mem64() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0x56789ABCDEF01234, "Memory: ROL 16"); + assert_eq!( + emu.maps.read_qword(DATA_ADDR).unwrap(), + 0x56789ABCDEF01234, + "Memory: ROL 16" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol_ror_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol_ror_extended.rs index c352016b..623a9188 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol_ror_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/rol_ror_extended.rs @@ -35,7 +35,12 @@ fn test_rol_all_counts_8bit() { 8 => 0xAB, // Back to original _ => unreachable!(), }; - assert_eq!(emu.regs().rax & 0xFF, expected, "ROL AL by {} failed", count); + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "ROL AL by {} failed", + count + ); } } @@ -61,7 +66,12 @@ fn test_ror_all_counts_8bit() { 8 => 0xAB, // Back to original _ => unreachable!(), }; - assert_eq!(emu.regs().rax & 0xFF, expected, "ROR AL by {} failed", count); + assert_eq!( + emu.regs().rax & 0xFF, + expected, + "ROR AL by {} failed", + count + ); } } @@ -150,7 +160,12 @@ fn test_rol_boundary_32bit() { emu.run(None).unwrap(); let expected = ((value << 1) | (value >> 31)) & 0xFFFFFFFF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "ROL 0x{:08X} by 1", value); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "ROL 0x{:08X} by 1", + value + ); } } @@ -165,7 +180,12 @@ fn test_ror_boundary_32bit() { emu.run(None).unwrap(); let expected = ((value >> 1) | (value << 31)) & 0xFFFFFFFF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "ROR 0x{:08X} by 1", value); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "ROR 0x{:08X} by 1", + value + ); } } @@ -270,7 +290,11 @@ fn test_rol_count_masking_32bit() { emu.regs_mut().rax = 0x12345678; emu.run(None).unwrap(); - assert_eq!(rax & 0xFFFFFFFF, emu.regs().rax & 0xFFFFFFFF, "Count masking for 32-bit"); + assert_eq!( + rax & 0xFFFFFFFF, + emu.regs().rax & 0xFFFFFFFF, + "Count masking for 32-bit" + ); } #[test] @@ -289,7 +313,11 @@ fn test_ror_count_masking_32bit() { emu.regs_mut().rax = 0x12345678; emu.run(None).unwrap(); - assert_eq!(rax & 0xFFFFFFFF, emu.regs().rax & 0xFFFFFFFF, "Count masking for 32-bit"); + assert_eq!( + rax & 0xFFFFFFFF, + emu.regs().rax & 0xFFFFFFFF, + "Count masking for 32-bit" + ); } #[test] @@ -323,7 +351,7 @@ fn test_ror_count_masking_64bit() { let code2 = [0x48, 0xc1, 0xc8, 0x08, 0xf4]; let mut emu = emu64(); - emu.load_code_bytes(&code2); + emu.load_code_bytes(&code2); emu.regs_mut().rax = 0x123456789ABCDEF0; emu.run(None).unwrap(); @@ -489,6 +517,11 @@ fn test_rol_power_of_two() { emu.run(None).unwrap(); let expected = ((value << 3) | (value >> 5)) & 0xFF; - assert_eq!(emu.regs().rax & 0xFF, expected as u64, "ROL power of 2 value 0x{:02X}", value); + assert_eq!( + emu.regs().rax & 0xFF, + expected as u64, + "ROL power of 2 value 0x{:02X}", + value + ); } } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/ror.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/ror.rs index ac4d6213..c141a9c3 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/ror.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/ror.rs @@ -34,7 +34,7 @@ fn test_ror_al_1() { // ROR AL, 1 (opcode D0 /1) let code = [ 0xd0, 0xc8, // ROR AL, 1 - 0xf4, // HLT + 0xf4, // HLT ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; // 0100_0010 @@ -58,7 +58,11 @@ fn test_ror_al_1_with_lsb() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0xC0, "AL: 0x81 ROR 1 = 0xC0 (LSB rotates to MSB)"); + assert_eq!( + emu.regs().rax & 0xFF, + 0xC0, + "AL: 0x81 ROR 1 = 0xC0 (LSB rotates to MSB)" + ); assert!(emu.flags().f_cf, "CF: receives LSB (was 1)"); // OF = XOR of two most-significant bits of result: 0xC0 = 1100_0000, MSB=1, MSB-1=1, so 1 XOR 1 = 0 assert!(!emu.flags().f_of, "OF: MSB XOR (MSB-1) = 1 XOR 1 = 0"); @@ -109,7 +113,11 @@ fn test_ror_full_rotation_8bit() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFF, + 0x42, + "AL: full rotation returns to original" + ); } #[test] @@ -138,15 +146,18 @@ fn test_ror_count_zero_preserves_flags() { ]; let mut emu = emu64(); emu.regs_mut().rax = 0x42; - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); + emu.load_code_bytes(&code); + emu.flags_mut() + .load(0x2 | (1 << flags::F_CF) | (1 << flags::F_ZF) | (1 << flags::F_OF)); let initial_flags = emu.flags().dump(); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFF, 0x42, "AL: unchanged"); - assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), - initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), - "Flags preserved"); + assert_eq!( + emu.flags().dump() & (flags::F_CF | flags::F_ZF | flags::F_OF), + initial_flags & (flags::F_CF | flags::F_ZF | flags::F_OF), + "Flags preserved" + ); } #[test] @@ -244,7 +255,11 @@ fn test_ror_ax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x3412, "AX: 0x1234 ROR 8 = 0x3412 (byte swap)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x3412, + "AX: 0x1234 ROR 8 = 0x3412 (byte swap)" + ); } #[test] @@ -259,7 +274,11 @@ fn test_ror_ax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: full rotation returns to original" + ); } #[test] @@ -325,7 +344,11 @@ fn test_ror_eax_1() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x43218765, "EAX: 0x86430ECA ROR 1 = 0x43218765"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x43218765, + "EAX: 0x86430ECA ROR 1 = 0x43218765" + ); } #[test] @@ -341,7 +364,11 @@ fn test_ror_eax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x78123456, "EAX: 0x12345678 ROR 8 = 0x78123456"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x78123456, + "EAX: 0x12345678 ROR 8 = 0x78123456" + ); } #[test] @@ -356,7 +383,11 @@ fn test_ror_eax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x56781234, "EAX: 0x12345678 ROR 16 = 0x56781234"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x56781234, + "EAX: 0x12345678 ROR 16 = 0x56781234" + ); } #[test] @@ -371,7 +402,11 @@ fn test_ror_eax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: full rotation returns to original" + ); } #[test] @@ -386,7 +421,11 @@ fn test_ror_ebx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx & 0xFFFFFFFF, 0x80000000, "EBX: 0x00000001 ROR 1 = 0x80000000"); + assert_eq!( + emu.regs().rbx & 0xFFFFFFFF, + 0x80000000, + "EBX: 0x00000001 ROR 1 = 0x80000000" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -402,7 +441,11 @@ fn test_ror_ecx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFFFFFF, 0x1ABCDEF0, "ECX: 0xABCDEF01 ROR 4 = 0x1ABCDEF0"); + assert_eq!( + emu.regs().rcx & 0xFFFFFFFF, + 0x1ABCDEF0, + "ECX: 0xABCDEF01 ROR 4 = 0x1ABCDEF0" + ); } #[test] @@ -418,7 +461,11 @@ fn test_ror_edx_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFFFFFF, 0x000000FF, "EDX: 0xFF000000 ROR 24 = 0x000000FF"); + assert_eq!( + emu.regs().rdx & 0xFFFFFFFF, + 0x000000FF, + "EDX: 0xFF000000 ROR 24 = 0x000000FF" + ); } #[test] @@ -433,7 +480,11 @@ fn test_ror_esi() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rsi & 0xFFFFFFFF, 0x40000000, "ESI: 0x80000000 ROR 1 = 0x40000000"); + assert_eq!( + emu.regs().rsi & 0xFFFFFFFF, + 0x40000000, + "ESI: 0x80000000 ROR 1 = 0x40000000" + ); } #[test] @@ -448,7 +499,11 @@ fn test_ror_edi() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdi & 0xFFFFFFFF, 0x67812345, "EDI: 0x12345678 ROR 12 = 0x67812345"); + assert_eq!( + emu.regs().rdi & 0xFFFFFFFF, + 0x67812345, + "EDI: 0x12345678 ROR 12 = 0x67812345" + ); } // ============================================================================ @@ -483,7 +538,11 @@ fn test_ror_rax_cl() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xF0123456789ABCDE, "RAX: 0x123456789ABCDEF0 ROR 8"); + assert_eq!( + emu.regs().rax, + 0xF0123456789ABCDE, + "RAX: 0x123456789ABCDEF0 ROR 8" + ); } #[test] @@ -498,7 +557,11 @@ fn test_ror_rax_imm8() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0xDEF0123456789ABC, "RAX: 0x123456789ABCDEF0 ROR 16"); + assert_eq!( + emu.regs().rax, + 0xDEF0123456789ABC, + "RAX: 0x123456789ABCDEF0 ROR 16" + ); } #[test] @@ -513,7 +576,11 @@ fn test_ror_rax_32bits() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x9ABCDEF012345678, "RAX: ROR 32 swaps high/low dwords"); + assert_eq!( + emu.regs().rax, + 0x9ABCDEF012345678, + "RAX: ROR 32 swaps high/low dwords" + ); } #[test] @@ -528,7 +595,11 @@ fn test_ror_rax_full_rotation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: full rotation returns to original"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: full rotation returns to original" + ); } #[test] @@ -543,7 +614,11 @@ fn test_ror_rbx() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rbx, 0x8000000000000000, "RBX: 0x0000000000000001 ROR 1 = 0x8000000000000000"); + assert_eq!( + emu.regs().rbx, + 0x8000000000000000, + "RBX: 0x0000000000000001 ROR 1 = 0x8000000000000000" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -680,7 +755,9 @@ fn test_ror_mem8() { // ROR byte [DATA_ADDR], 1 let code = [ - 0xd0, 0x0c, 0x25, // ROR byte ptr [disp32], 1 + 0xd0, + 0x0c, + 0x25, // ROR byte ptr [disp32], 1 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -688,12 +765,23 @@ fn test_ror_mem8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.load_code_bytes(&code); emu.maps.write_byte(DATA_ADDR, 0x81); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_byte(DATA_ADDR).unwrap(), 0xC0, "Memory: 0x81 ROR 1 = 0xC0"); + assert_eq!( + emu.maps.read_byte(DATA_ADDR).unwrap(), + 0xC0, + "Memory: 0x81 ROR 1 = 0xC0" + ); assert!(emu.flags().f_cf, "CF: LSB was 1"); } @@ -703,7 +791,10 @@ fn test_ror_mem16() { // ROR word [DATA_ADDR], 4 let code = [ - 0x66, 0xc1, 0x0c, 0x25, // ROR word ptr [disp32], imm8 + 0x66, + 0xc1, + 0x0c, + 0x25, // ROR word ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -712,12 +803,23 @@ fn test_ror_mem16() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, 0x1234); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0x4123, "Memory: 0x1234 ROR 4 = 0x4123"); + assert_eq!( + emu.maps.read_word(DATA_ADDR).unwrap(), + 0x4123, + "Memory: 0x1234 ROR 4 = 0x4123" + ); } #[test] @@ -726,7 +828,9 @@ fn test_ror_mem32() { // ROR dword [DATA_ADDR], CL let code = [ - 0xd3, 0x0c, 0x25, // ROR dword ptr [disp32], CL + 0xd3, + 0x0c, + 0x25, // ROR dword ptr [disp32], CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -734,13 +838,24 @@ fn test_ror_mem32() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rcx = 0x08; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, 0x12345678); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0x78123456, "Memory: 0x12345678 ROR 8 = 0x78123456"); + assert_eq!( + emu.maps.read_dword(DATA_ADDR).unwrap(), + 0x78123456, + "Memory: 0x12345678 ROR 8 = 0x78123456" + ); } #[test] @@ -749,7 +864,10 @@ fn test_ror_mem64() { // ROR qword [DATA_ADDR], 16 let code = [ - 0x48, 0xc1, 0x0c, 0x25, // ROR qword ptr [disp32], imm8 + 0x48, + 0xc1, + 0x0c, + 0x25, // ROR qword ptr [disp32], imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -758,10 +876,21 @@ fn test_ror_mem64() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0xDEF0123456789ABC, "Memory: ROR 16"); + assert_eq!( + emu.maps.read_qword(DATA_ADDR).unwrap(), + 0xDEF0123456789ABC, + "Memory: ROR 16" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld.rs index 3f9866d4..0f9f2d9b 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld.rs @@ -38,7 +38,11 @@ fn test_shld_ax_bx_imm8() { // AX: 0001_0010_0011_0100 shifted left by 4 // Bits from BX (1010_1011_1100_1101) fill from right // Result: 0010_0011_0100_1010 - assert_eq!(emu.regs().rax & 0xFFFF, 0x234A, "AX: 0x1234 SHLD 4 from 0xABCD = 0x234A"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x234A, + "AX: 0x1234 SHLD 4 from 0xABCD = 0x234A" + ); assert!(emu.flags().f_cf, "CF: bit shifted out was 1"); } @@ -51,7 +55,11 @@ fn test_shld_ax_bx_cl() { emu.regs_mut().rcx = 0x08; // Shift by 8 emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x34AB, "AX: 0x1234 SHLD 8 from 0xABCD = 0x34AB"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x34AB, + "AX: 0x1234 SHLD 8 from 0xABCD = 0x34AB" + ); } #[test] @@ -62,7 +70,11 @@ fn test_shld_ax_bx_1bit() { emu.regs_mut().rbx = 0x0001; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8000, "AX: 0x4000 SHLD 1 = 0x8000"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8000, + "AX: 0x4000 SHLD 1 = 0x8000" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); assert!(emu.flags().f_of, "OF: sign changed from + to -"); } @@ -75,7 +87,11 @@ fn test_shld_ax_full_replacement() { emu.regs_mut().rbx = 0xABCD; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xABCD, "AX: completely replaced by BX"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xABCD, + "AX: completely replaced by BX" + ); } #[test] @@ -86,7 +102,11 @@ fn test_shld_cx_dx_imm8() { emu.regs_mut().rdx = 0x9ABC; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFF, 0x6789, "CX: 0x5678 SHLD 4 from 0x9ABC"); + assert_eq!( + emu.regs().rcx & 0xFFFF, + 0x6789, + "CX: 0x5678 SHLD 4 from 0x9ABC" + ); } #[test] @@ -98,7 +118,11 @@ fn test_shld_dx_si_cl() { emu.regs_mut().rcx = 0x04; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFF, 0x1112, "DX: 0x1111 SHLD 4 from 0x2222"); + assert_eq!( + emu.regs().rdx & 0xFFFF, + 0x1112, + "DX: 0x1111 SHLD 4 from 0x2222" + ); } #[test] @@ -107,13 +131,21 @@ fn test_shld_ax_zero_count() { let mut emu = emu64(); emu.regs_mut().rax = 0x1234; emu.regs_mut().rbx = 0xABCD; - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_OF)); + emu.load_code_bytes(&code); + emu.flags_mut() + .load(0x2 | (1 << flags::F_CF) | (1 << flags::F_OF)); let initial_flags = emu.flags().dump(); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: unchanged with count 0"); - assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_OF), - initial_flags & (flags::F_CF | flags::F_OF), "Flags preserved"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: unchanged with count 0" + ); + assert_eq!( + emu.flags().dump() & (flags::F_CF | flags::F_OF), + initial_flags & (flags::F_CF | flags::F_OF), + "Flags preserved" + ); } // ============================================================================ @@ -128,7 +160,11 @@ fn test_shld_eax_ebx_imm8() { emu.regs_mut().rbx = 0xABCDEF01; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x2345678A, "EAX: 0x12345678 SHLD 4 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x2345678A, + "EAX: 0x12345678 SHLD 4 from 0xABCDEF01" + ); } #[test] @@ -140,7 +176,11 @@ fn test_shld_eax_ebx_cl() { emu.regs_mut().rcx = 0x08; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x345678AB, "EAX: 0x12345678 SHLD 8 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x345678AB, + "EAX: 0x12345678 SHLD 8 from 0xABCDEF01" + ); } #[test] @@ -165,7 +205,11 @@ fn test_shld_eax_1bit() { emu.regs_mut().rbx = 0x00000001; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000000, "EAX: 0x40000000 SHLD 1"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000000, + "EAX: 0x40000000 SHLD 1" + ); assert!(emu.flags().f_of, "OF: sign changed"); } @@ -178,7 +222,11 @@ fn test_shld_eax_full_replacement() { emu.regs_mut().rbx = 0xABCDEF01; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: count masked to 0, no shift"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: count masked to 0, no shift" + ); } #[test] @@ -233,10 +281,10 @@ fn test_shld_eax_zero_count() { let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; emu.regs_mut().rbx = 0xABCDEF01; - let initial = emu.regs().rax & 0xFFFFFFFF; + let initial = emu.regs().rax & 0xFFFFFFFF; emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, initial, "EAX: unchanged"); } @@ -321,7 +369,11 @@ fn test_shld_rax_full_replacement() { emu.regs_mut().rbx = 0xFEDCBA9876543210; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: count masked to 0, no shift"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: count masked to 0, no shift" + ); } #[test] @@ -422,10 +474,10 @@ fn test_shld_rax_zero_count() { let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; emu.regs_mut().rbx = 0xFEDCBA9876543210; - let initial = emu.regs().rax; + let initial = emu.regs().rax; emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, initial, "RAX: unchanged"); } @@ -437,7 +489,11 @@ fn test_shld_rax_zero_count() { fn test_shld_mem16_imm8() { let DATA_ADDR = 0x7000; let code = [ - 0x66, 0x0f, 0xa4, 0x14, 0x25, // SHLD word ptr [disp32], DX, imm8 + 0x66, + 0x0f, + 0xa4, + 0x14, + 0x25, // SHLD word ptr [disp32], DX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -446,19 +502,33 @@ fn test_shld_mem16_imm8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rdx = 0xABCD; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, 0x1234); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0x234A, "Memory: 0x1234 SHLD 4 from 0xABCD"); + assert_eq!( + emu.maps.read_word(DATA_ADDR).unwrap(), + 0x234A, + "Memory: 0x1234 SHLD 4 from 0xABCD" + ); } #[test] fn test_shld_mem32_cl() { let DATA_ADDR = 0x7000; let code = [ - 0x0f, 0xa5, 0x14, 0x25, // SHLD dword ptr [disp32], EDX, CL + 0x0f, + 0xa5, + 0x14, + 0x25, // SHLD dword ptr [disp32], EDX, CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -466,20 +536,35 @@ fn test_shld_mem32_cl() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rdx = 0xABCDEF01; emu.regs_mut().rcx = 0x08; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, 0x12345678); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0x345678AB, "Memory: SHLD 8"); + assert_eq!( + emu.maps.read_dword(DATA_ADDR).unwrap(), + 0x345678AB, + "Memory: SHLD 8" + ); } #[test] fn test_shld_mem64_imm8() { let DATA_ADDR = 0x7000; let code = [ - 0x48, 0x0f, 0xa4, 0x14, 0x25, // SHLD qword ptr [disp32], RDX, imm8 + 0x48, + 0x0f, + 0xa4, + 0x14, + 0x25, // SHLD qword ptr [disp32], RDX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -488,12 +573,23 @@ fn test_shld_mem64_imm8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rdx = 0xAAAABBBBCCCCDDDD; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0x56789ABCDEF0AAAA, "Memory: SHLD 16"); + assert_eq!( + emu.maps.read_qword(DATA_ADDR).unwrap(), + 0x56789ABCDEF0AAAA, + "Memory: SHLD 16" + ); } // ============================================================================ @@ -560,7 +656,11 @@ fn test_shld_all_ones() { emu.regs_mut().rbx = 0xFFFFFFFF; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "All ones stays all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "All ones stays all ones" + ); } #[test] @@ -573,5 +673,9 @@ fn test_shld_alternating_bits() { emu.regs_mut().rbx = 0x55555555; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x55555554, "Alternating bits shift"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x55555554, + "Alternating bits shift" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld_shrd_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld_shrd_extended.rs index 3c744565..f9921daf 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld_shrd_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shld_shrd_extended.rs @@ -29,7 +29,11 @@ fn test_shld_all_counts_16bit() { // For 16-bit, count is masked to 5 bits: 16 & 0x1F = 16 // Since count (16) == operand size (16), result is undefined per spec // Implementation treats 16 as valid shift, shifting out all original bits - assert_eq!(emu.regs().rax & 0xFFFF, 0x5555, "SHLD AX by 16 (full replacement)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x5555, + "SHLD AX by 16 (full replacement)" + ); } } } @@ -50,7 +54,11 @@ fn test_shrd_all_counts_16bit() { // For 16-bit, count is masked to 5 bits: 16 & 0x1F = 16 // Since count (16) == operand size (16), result is undefined per spec // Implementation treats 16 as valid shift, shifting out all original bits - assert_eq!(emu.regs().rax & 0xFFFF, 0x5555, "SHRD AX by 16 (full replacement)"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x5555, + "SHRD AX by 16 (full replacement)" + ); } } } @@ -69,7 +77,11 @@ fn test_shld_all_counts_32bit() { assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA, "SHLD EAX by 0"); } else if *count == 32 { // Count is masked: 32 MOD 32 = 0, so no shift occurs - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA, "SHLD EAX by 32 (count masked to 0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAAAAAA, + "SHLD EAX by 32 (count masked to 0)" + ); } } } @@ -88,7 +100,11 @@ fn test_shrd_all_counts_32bit() { assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA, "SHRD EAX by 0"); } else if *count == 32 { // Count is masked: 32 MOD 32 = 0, so no shift occurs - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAAAAAA, "SHRD EAX by 32 (count masked to 0)"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAAAAAA, + "SHRD EAX by 32 (count masked to 0)" + ); } } } @@ -107,7 +123,11 @@ fn test_shld_all_counts_64bit() { assert_eq!(emu.regs().rax, 0xAAAAAAAAAAAAAAAA, "SHLD RAX by 0"); } else if *count == 64 { // Count is masked: 64 MOD 64 = 0, so no shift occurs - assert_eq!(emu.regs().rax, 0xAAAAAAAAAAAAAAAA, "SHLD RAX by 64 (count masked to 0)"); + assert_eq!( + emu.regs().rax, + 0xAAAAAAAAAAAAAAAA, + "SHLD RAX by 64 (count masked to 0)" + ); } } } @@ -126,7 +146,11 @@ fn test_shrd_all_counts_64bit() { assert_eq!(emu.regs().rax, 0xAAAAAAAAAAAAAAAA, "SHRD RAX by 0"); } else if *count == 64 { // Count is masked: 64 MOD 64 = 0, so no shift occurs - assert_eq!(emu.regs().rax, 0xAAAAAAAAAAAAAAAA, "SHRD RAX by 64 (count masked to 0)"); + assert_eq!( + emu.regs().rax, + 0xAAAAAAAAAAAAAAAA, + "SHRD RAX by 64 (count masked to 0)" + ); } } } @@ -155,7 +179,13 @@ fn test_shld_boundary_values_32bit() { emu.run(None).unwrap(); let expected = ((*dest << 16) | (*src >> 16)) & 0xFFFFFFFF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "SHLD 0x{:08X} with 0x{:08X}", dest, src); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "SHLD 0x{:08X} with 0x{:08X}", + dest, + src + ); } } @@ -179,7 +209,13 @@ fn test_shrd_boundary_values_32bit() { emu.run(None).unwrap(); let expected = ((*dest >> 16) | (*src << 16)) & 0xFFFFFFFF; - assert_eq!(emu.regs().rax & 0xFFFFFFFF, expected, "SHRD 0x{:08X} with 0x{:08X}", dest, src); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + expected, + "SHRD 0x{:08X} with 0x{:08X}", + dest, + src + ); } } @@ -201,7 +237,13 @@ fn test_shld_boundary_values_64bit() { emu.run(None).unwrap(); let expected = (*dest << 32) | (*src >> 32); - assert_eq!(emu.regs().rax, expected, "SHLD 0x{:016X} with 0x{:016X}", dest, src); + assert_eq!( + emu.regs().rax, + expected, + "SHLD 0x{:016X} with 0x{:016X}", + dest, + src + ); } } @@ -223,7 +265,13 @@ fn test_shrd_boundary_values_64bit() { emu.run(None).unwrap(); let expected = (*dest >> 32) | (*src << 32); - assert_eq!(emu.regs().rax, expected, "SHRD 0x{:016X} with 0x{:016X}", dest, src); + assert_eq!( + emu.regs().rax, + expected, + "SHRD 0x{:016X} with 0x{:016X}", + dest, + src + ); } } @@ -250,7 +298,11 @@ fn test_shld_count_masking_32bit() { emu.regs_mut().rbx = 0xABCDEF01; emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, rax & 0xFFFFFFFF, "Count masking for 32-bit SHLD"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + rax & 0xFFFFFFFF, + "Count masking for 32-bit SHLD" + ); } #[test] @@ -271,7 +323,11 @@ fn test_shrd_count_masking_32bit() { emu.load_code_bytes(&code2); emu.run(None).unwrap(); - assert_eq!(rax & 0xFFFFFFFF, emu.regs().rax & 0xFFFFFFFF, "Count masking for 32-bit SHRD"); + assert_eq!( + rax & 0xFFFFFFFF, + emu.regs().rax & 0xFFFFFFFF, + "Count masking for 32-bit SHRD" + ); } #[test] @@ -338,7 +394,13 @@ fn test_shld_cf_edge_cases() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.flags().f_cf, *expected_cf, "CF for SHLD 0x{:08X} by {}", value, count); + assert_eq!( + emu.flags().f_cf, + *expected_cf, + "CF for SHLD 0x{:08X} by {}", + value, + count + ); } } @@ -359,7 +421,13 @@ fn test_shrd_cf_edge_cases() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.flags().f_cf, *expected_cf, "CF for SHRD 0x{:08X} by {}", value, count); + assert_eq!( + emu.flags().f_cf, + *expected_cf, + "CF for SHRD 0x{:08X} by {}", + value, + count + ); } } @@ -452,7 +520,7 @@ fn test_shld_128bit_simulation() { // Simulate a 128-bit shift left by 16 bits let code = [ 0x48, 0x0f, 0xa4, 0xd0, 0x10, // SHLD RAX, RDX, 16 - 0x48, 0xc1, 0xe2, 0x10, // SHL RDX, 16 + 0x48, 0xc1, 0xe2, 0x10, // SHL RDX, 16 0xf4, ]; let mut emu = emu64(); @@ -461,7 +529,11 @@ fn test_shld_128bit_simulation() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x56789ABCDEF0FEDC, "High 64 bits after SHLD"); + assert_eq!( + emu.regs().rax, + 0x56789ABCDEF0FEDC, + "High 64 bits after SHLD" + ); assert_eq!(emu.regs().rdx, 0xBA98765432100000, "Low 64 bits after SHL"); } @@ -470,7 +542,7 @@ fn test_shrd_128bit_simulation() { // Simulate a 128-bit shift right by 16 bits let code = [ 0x48, 0x0f, 0xac, 0xd0, 0x10, // SHRD RAX, RDX, 16 - 0x48, 0xc1, 0xea, 0x10, // SHR RDX, 16 + 0x48, 0xc1, 0xea, 0x10, // SHR RDX, 16 0xf4, ]; let mut emu = emu64(); @@ -496,7 +568,11 @@ fn test_shld_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xAAAA5555, "Alternating pattern SHLD"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xAAAA5555, + "Alternating pattern SHLD" + ); } #[test] @@ -508,7 +584,11 @@ fn test_shrd_alternating_pattern() { emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x5555AAAA, "Alternating pattern SHRD"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x5555AAAA, + "Alternating pattern SHRD" + ); } #[test] diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shrd.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shrd.rs index a4716409..b908a16d 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shrd.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/rotate/shrd.rs @@ -36,7 +36,11 @@ fn test_shrd_ax_bx_imm8() { // AX: 0001_0010_0011_0100 shifted right by 4 // Bits from BX (1010_1011_1100_1101) fill from left // Result: 1101_0001_0010_0011 - assert_eq!(emu.regs().rax & 0xFFFF, 0xD123, "AX: 0x1234 SHRD 4 from 0xABCD = 0xD123"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xD123, + "AX: 0x1234 SHRD 4 from 0xABCD = 0xD123" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); } @@ -49,7 +53,11 @@ fn test_shrd_ax_bx_cl() { emu.regs_mut().rcx = 0x08; // Shift by 8 emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xCD12, "AX: 0x1234 SHRD 8 from 0xABCD = 0xCD12"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xCD12, + "AX: 0x1234 SHRD 8 from 0xABCD = 0xCD12" + ); } #[test] @@ -60,7 +68,11 @@ fn test_shrd_ax_bx_1bit() { emu.regs_mut().rbx = 0x0001; // Will put 1 in MSB position emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x8001, "AX: 0x0002 SHRD 1 with MSB from source"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x8001, + "AX: 0x0002 SHRD 1 with MSB from source" + ); assert!(!emu.flags().f_cf, "CF: bit shifted out was 0"); assert!(emu.flags().f_of, "OF: sign changed from + to -"); } @@ -73,7 +85,11 @@ fn test_shrd_ax_full_replacement() { emu.regs_mut().rbx = 0xABCD; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0xABCD, "AX: completely replaced by BX"); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0xABCD, + "AX: completely replaced by BX" + ); } #[test] @@ -84,7 +100,11 @@ fn test_shrd_cx_dx_imm8() { emu.regs_mut().rdx = 0x9ABC; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rcx & 0xFFFF, 0xC567, "CX: 0x5678 SHRD 4 from 0x9ABC"); + assert_eq!( + emu.regs().rcx & 0xFFFF, + 0xC567, + "CX: 0x5678 SHRD 4 from 0x9ABC" + ); } #[test] @@ -96,7 +116,11 @@ fn test_shrd_dx_si_cl() { emu.regs_mut().rcx = 0x04; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rdx & 0xFFFF, 0x2111, "DX: 0x1111 SHRD 4 from 0x2222"); + assert_eq!( + emu.regs().rdx & 0xFFFF, + 0x2111, + "DX: 0x1111 SHRD 4 from 0x2222" + ); } #[test] @@ -105,13 +129,21 @@ fn test_shrd_ax_zero_count() { let mut emu = emu64(); emu.regs_mut().rax = 0x1234; emu.regs_mut().rbx = 0xABCD; - emu.load_code_bytes(&code); - emu.flags_mut().load(0x2 | (1 << flags::F_CF) | (1 << flags::F_OF)); + emu.load_code_bytes(&code); + emu.flags_mut() + .load(0x2 | (1 << flags::F_CF) | (1 << flags::F_OF)); let initial_flags = emu.flags().dump(); - emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFF, 0x1234, "AX: unchanged with count 0"); - assert_eq!(emu.flags().dump() & (flags::F_CF | flags::F_OF), - initial_flags & (flags::F_CF | flags::F_OF), "Flags preserved"); + emu.run(None).unwrap(); + assert_eq!( + emu.regs().rax & 0xFFFF, + 0x1234, + "AX: unchanged with count 0" + ); + assert_eq!( + emu.flags().dump() & (flags::F_CF | flags::F_OF), + initial_flags & (flags::F_CF | flags::F_OF), + "Flags preserved" + ); } // ============================================================================ @@ -128,7 +160,11 @@ fn test_shrd_eax_ebx_imm8() { emu.regs_mut().rbx = 0xABCDEF01; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x11234567, "EAX: 0x12345678 SHRD 4 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x11234567, + "EAX: 0x12345678 SHRD 4 from 0xABCDEF01" + ); } #[test] @@ -140,7 +176,11 @@ fn test_shrd_eax_ebx_cl() { emu.regs_mut().rcx = 0x08; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x01123456, "EAX: 0x12345678 SHRD 8 from 0xABCDEF01"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x01123456, + "EAX: 0x12345678 SHRD 8 from 0xABCDEF01" + ); } #[test] @@ -162,7 +202,11 @@ fn test_shrd_eax_1bit() { emu.regs_mut().rbx = 0x00000001; // MSB will be set emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x80000001, "EAX: SHRD 1 with MSB"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x80000001, + "EAX: SHRD 1 with MSB" + ); assert!(emu.flags().f_of, "OF: sign changed"); } @@ -175,7 +219,11 @@ fn test_shrd_eax_full_replacement() { emu.regs_mut().rbx = 0xABCDEF01; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0x12345678, "EAX: count masked to 0, no shift"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0x12345678, + "EAX: count masked to 0, no shift" + ); } #[test] @@ -230,10 +278,10 @@ fn test_shrd_eax_zero_count() { let mut emu = emu64(); emu.regs_mut().rax = 0x12345678; emu.regs_mut().rbx = 0xABCDEF01; - let initial = emu.regs().rax & 0xFFFFFFFF; + let initial = emu.regs().rax & 0xFFFFFFFF; emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax & 0xFFFFFFFF, initial, "EAX: unchanged"); } @@ -318,7 +366,11 @@ fn test_shrd_rax_full_replacement() { emu.regs_mut().rbx = 0xFEDCBA9876543210; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x123456789ABCDEF0, "RAX: count masked to 0, no shift"); + assert_eq!( + emu.regs().rax, + 0x123456789ABCDEF0, + "RAX: count masked to 0, no shift" + ); } #[test] @@ -420,10 +472,10 @@ fn test_shrd_rax_zero_count() { let mut emu = emu64(); emu.regs_mut().rax = 0x123456789ABCDEF0; emu.regs_mut().rbx = 0xFEDCBA9876543210; - let initial = emu.regs().rax; + let initial = emu.regs().rax; emu.load_code_bytes(&code); emu.flags_mut().load(0x2 | (1 << flags::F_CF)); - emu.run(None).unwrap(); + emu.run(None).unwrap(); assert_eq!(emu.regs().rax, initial, "RAX: unchanged"); } @@ -435,7 +487,11 @@ fn test_shrd_rax_zero_count() { fn test_shrd_mem16_imm8() { let DATA_ADDR = 0x7000; let code = [ - 0x66, 0x0f, 0xac, 0x14, 0x25, // SHRD word ptr [disp32], DX, imm8 + 0x66, + 0x0f, + 0xac, + 0x14, + 0x25, // SHRD word ptr [disp32], DX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -444,19 +500,33 @@ fn test_shrd_mem16_imm8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rdx = 0xABCD; emu.load_code_bytes(&code); emu.maps.write_word(DATA_ADDR, 0x1234); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_word(DATA_ADDR).unwrap(), 0xD123, "Memory: 0x1234 SHRD 4 from 0xABCD"); + assert_eq!( + emu.maps.read_word(DATA_ADDR).unwrap(), + 0xD123, + "Memory: 0x1234 SHRD 4 from 0xABCD" + ); } #[test] fn test_shrd_mem32_cl() { let DATA_ADDR = 0x7000; let code = [ - 0x0f, 0xad, 0x14, 0x25, // SHRD dword ptr [disp32], EDX, CL + 0x0f, + 0xad, + 0x14, + 0x25, // SHRD dword ptr [disp32], EDX, CL (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -464,20 +534,35 @@ fn test_shrd_mem32_cl() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rdx = 0xABCDEF01; emu.regs_mut().rcx = 0x08; emu.load_code_bytes(&code); emu.maps.write_dword(DATA_ADDR, 0x12345678); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_dword(DATA_ADDR).unwrap(), 0x01123456, "Memory: SHRD 8"); + assert_eq!( + emu.maps.read_dword(DATA_ADDR).unwrap(), + 0x01123456, + "Memory: SHRD 8" + ); } #[test] fn test_shrd_mem64_imm8() { let DATA_ADDR = 0x7000; let code = [ - 0x48, 0x0f, 0xac, 0x14, 0x25, // SHRD qword ptr [disp32], RDX, imm8 + 0x48, + 0x0f, + 0xac, + 0x14, + 0x25, // SHRD qword ptr [disp32], RDX, imm8 (DATA_ADDR & 0xFF) as u8, ((DATA_ADDR >> 8) & 0xFF) as u8, ((DATA_ADDR >> 16) & 0xFF) as u8, @@ -486,12 +571,23 @@ fn test_shrd_mem64_imm8() { 0xf4, ]; let mut emu = emu64(); - emu.maps.create_map("test_data", 0x7000, 0x1000, crate::maps::mem64::Permission::READ_WRITE).expect("failed to map test_data"); + emu.maps + .create_map( + "test_data", + 0x7000, + 0x1000, + crate::maps::mem64::Permission::READ_WRITE, + ) + .expect("failed to map test_data"); emu.regs_mut().rdx = 0xAAAABBBBCCCCDDDD; emu.load_code_bytes(&code); emu.maps.write_qword(DATA_ADDR, 0x123456789ABCDEF0); emu.run(None).unwrap(); - assert_eq!(emu.maps.read_qword(DATA_ADDR).unwrap(), 0xDDDD123456789ABC, "Memory: SHRD 16"); + assert_eq!( + emu.maps.read_qword(DATA_ADDR).unwrap(), + 0xDDDD123456789ABC, + "Memory: SHRD 16" + ); } // ============================================================================ @@ -559,7 +655,11 @@ fn test_shrd_all_ones() { emu.regs_mut().rbx = 0xFFFFFFFF; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xFFFFFFFF, "All ones stays all ones"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xFFFFFFFF, + "All ones stays all ones" + ); } #[test] @@ -572,5 +672,9 @@ fn test_shrd_alternating_bits() { emu.regs_mut().rbx = 0x55555555; emu.load_code_bytes(&code); emu.run(None).unwrap(); - assert_eq!(emu.regs().rax & 0xFFFFFFFF, 0xD5555555, "Alternating bits shift"); + assert_eq!( + emu.regs().rax & 0xFFFFFFFF, + 0xD5555555, + "Alternating bits shift" + ); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/enter_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/enter_extended.rs index d47a1455..1fce09ae 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/enter_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/enter_extended.rs @@ -29,13 +29,24 @@ fn test_enter_basic_no_nesting() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); // ENTER 0,0 should: PUSH RBP, MOV RBP, RSP - assert_eq!(emu.regs().rsp, 0x1000 - 8, "RSP decremented by 8 (pushed RBP)"); + assert_eq!( + emu.regs().rsp, + 0x1000 - 8, + "RSP decremented by 8 (pushed RBP)" + ); assert_eq!(emu.regs().rbp, 0x1000 - 8, "RBP = RSP after PUSH"); let saved_rbp = emu.maps.read_qword(0x1000 - 8).unwrap(); @@ -50,13 +61,24 @@ fn test_enter_allocate_8_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); assert_eq!(emu.regs().rbp, 0x1000 - 8, "RBP set after pushing"); - assert_eq!(emu.regs().rsp, 0x1000 - 16, "RSP = RBP - 8 (allocated space)"); + assert_eq!( + emu.regs().rsp, + 0x1000 - 16, + "RSP = RBP - 8 (allocated space)" + ); let saved_rbp = emu.maps.read_qword(0x1000 - 8).unwrap(); assert_eq!(saved_rbp, 0x2000, "Old RBP saved"); @@ -70,7 +92,14 @@ fn test_enter_allocate_16_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -90,7 +119,14 @@ fn test_enter_allocate_32_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -107,7 +143,14 @@ fn test_enter_allocate_64_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -124,7 +167,14 @@ fn test_enter_allocate_128_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -141,7 +191,14 @@ fn test_enter_allocate_256_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -158,7 +215,14 @@ fn test_enter_allocate_1024_bytes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -175,7 +239,14 @@ fn test_enter_allocate_max_16bit() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x20000-(0x20000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x20000 - (0x20000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x20000; emu.regs_mut().rbp = 0x30000; emu.run(None).unwrap(); @@ -196,7 +267,14 @@ fn test_enter_nesting_level_1_no_alloc() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -221,7 +299,14 @@ fn test_enter_nesting_level_1_with_alloc() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -244,7 +329,14 @@ fn test_enter_nesting_level_2() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; @@ -263,7 +355,14 @@ fn test_enter_nesting_level_3() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; @@ -283,7 +382,14 @@ fn test_enter_nesting_level_4_with_alloc() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -299,7 +405,14 @@ fn test_enter_nesting_level_5() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; emu.regs_mut().rbp = 0x4000; emu.run(None).unwrap(); @@ -322,7 +435,14 @@ fn test_enter_preserves_other_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -340,7 +460,14 @@ fn test_enter_preserves_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -360,7 +487,14 @@ fn test_enter_leave_roundtrip() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -382,13 +516,28 @@ fn test_enter_leave_nested() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x1000, "RSP restored after nested ENTER/LEAVE"); - assert_eq!(emu.regs().rbp, 0x2000, "RBP restored after nested ENTER/LEAVE"); + assert_eq!( + emu.regs().rsp, + 0x1000, + "RSP restored after nested ENTER/LEAVE" + ); + assert_eq!( + emu.regs().rbp, + 0x2000, + "RBP restored after nested ENTER/LEAVE" + ); } // ============================================================================ @@ -403,7 +552,14 @@ fn test_enter_high_stack_address() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x100000-(0x100000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x100000 - (0x100000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x100000; emu.regs_mut().rbp = 0x200000; emu.run(None).unwrap(); @@ -423,7 +579,14 @@ fn test_enter_low_stack_address() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x100-(0x100 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x100 - (0x100 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x100; emu.regs_mut().rbp = 0x200; emu.run(None).unwrap(); @@ -452,7 +615,14 @@ fn test_enter_multiple_calls() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -468,7 +638,14 @@ fn test_enter_with_odd_allocation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -485,7 +662,14 @@ fn test_enter_allocation_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -511,7 +695,14 @@ fn test_enter_frame_pointer_chain() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -538,7 +729,14 @@ fn test_enter_small_local_vars() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -555,7 +753,14 @@ fn test_enter_large_local_array() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -572,7 +777,14 @@ fn test_enter_no_locals() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -595,7 +807,14 @@ fn test_enter_then_push() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -616,7 +835,14 @@ fn test_enter_then_mov_to_local() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -638,7 +864,14 @@ fn test_enter_with_parameter_access() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -658,7 +891,14 @@ fn test_enter_nesting_level_10() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; emu.regs_mut().rbp = 0x4000; emu.run(None).unwrap(); @@ -674,7 +914,14 @@ fn test_enter_nesting_level_16() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x4000-(0x4000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x4000 - (0x4000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x4000; emu.regs_mut().rbp = 0x5000; emu.run(None).unwrap(); @@ -690,12 +937,23 @@ fn test_enter_nesting_level_31() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x5000-(0x5000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x5000 - (0x5000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x5000; emu.regs_mut().rbp = 0x6000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x5000 - 256, "RSP with max nesting level 31"); + assert_eq!( + emu.regs().rsp, + 0x5000 - 256, + "RSP with max nesting level 31" + ); } // ============================================================================ @@ -710,7 +968,14 @@ fn test_enter_zero_allocation_zero_nesting() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -727,7 +992,14 @@ fn test_enter_with_same_rbp_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x1000; // RBP == RSP emu.run(None).unwrap(); @@ -748,7 +1020,14 @@ fn test_enter_consecutive_same_size() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -767,7 +1046,14 @@ fn test_enter_mixed_sizes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; emu.regs_mut().rbp = 0x4000; emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/leave_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/leave_extended.rs index a275bc59..82919380 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/leave_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/leave_extended.rs @@ -24,7 +24,14 @@ fn test_leave_basic() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2FF8-(0x2FF8 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2FF8 - (0x2FF8 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2FF8; // Stack pointer below frame pointer emu.regs_mut().rbp = 0x3000; // Frame pointer @@ -45,7 +52,14 @@ fn test_leave_after_enter() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -65,12 +79,23 @@ fn test_leave_with_local_variables() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x1000, "RSP restored despite local var usage"); + assert_eq!( + emu.regs().rsp, + 0x1000, + "RSP restored despite local var usage" + ); assert_eq!(emu.regs().rbp, 0x2000, "RBP restored"); } @@ -83,7 +108,14 @@ fn test_leave_small_frame() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -101,12 +133,23 @@ fn test_leave_large_frame() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x2000, "RSP restored after large allocation"); + assert_eq!( + emu.regs().rsp, + 0x2000, + "RSP restored after large allocation" + ); assert_eq!(emu.regs().rbp, 0x3000, "RBP restored"); } @@ -127,13 +170,28 @@ fn test_leave_nested_functions() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x1000, "RSP fully restored after nested calls"); - assert_eq!(emu.regs().rbp, 0x2000, "RBP fully restored after nested calls"); + assert_eq!( + emu.regs().rsp, + 0x1000, + "RSP fully restored after nested calls" + ); + assert_eq!( + emu.regs().rbp, + 0x2000, + "RBP fully restored after nested calls" + ); } #[test] @@ -149,7 +207,14 @@ fn test_leave_triple_nested() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -175,7 +240,14 @@ fn test_leave_deep_nesting() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; emu.regs_mut().rbp = 0x4000; emu.run(None).unwrap(); @@ -200,7 +272,14 @@ fn test_leave_preserves_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -219,7 +298,14 @@ fn test_leave_preserves_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -243,7 +329,14 @@ fn test_leave_manual_frame() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -266,7 +359,14 @@ fn test_leave_with_push_pop_in_function() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.regs_mut().rax = 0xAAAA; @@ -291,7 +391,14 @@ fn test_leave_standalone() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2FF8-(0x2FF8 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2FF8 - (0x2FF8 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2FF8; emu.regs_mut().rbp = 0x3000; @@ -314,7 +421,14 @@ fn test_leave_with_modified_stack() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -337,7 +451,14 @@ fn test_leave_high_stack_address() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x100000-(0x100000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x100000 - (0x100000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x100000; emu.regs_mut().rbp = 0x200000; emu.run(None).unwrap(); @@ -355,7 +476,14 @@ fn test_leave_low_stack_address() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x100-(0x100 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x100 - (0x100 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x100; emu.regs_mut().rbp = 0x200; emu.run(None).unwrap(); @@ -377,7 +505,14 @@ fn test_leave_zero_sized_frame() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -403,7 +538,14 @@ fn test_leave_typical_epilogue() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -431,7 +573,14 @@ fn test_leave_with_saved_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.regs_mut().rax = 0xAAAA; @@ -458,7 +607,14 @@ fn test_leave_sequence() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -486,7 +642,14 @@ fn test_leave_frame_chain() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -508,7 +671,14 @@ fn test_leave_with_varying_frames() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -529,7 +699,14 @@ fn test_leave_rbp_equals_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; emu.regs_mut().rbp = 0x3000; // RBP == RSP @@ -550,7 +727,14 @@ fn test_leave_with_zero_saved_rbp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x0000; // RBP is zero emu.run(None).unwrap(); @@ -567,7 +751,14 @@ fn test_leave_stack_grows_correctly() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.run(None).unwrap(); @@ -591,12 +782,23 @@ fn test_leave_after_stack_arithmetic() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x1000, "LEAVE restores correctly despite SUB/ADD"); + assert_eq!( + emu.regs().rsp, + 0x1000, + "LEAVE restores correctly despite SUB/ADD" + ); } #[test] @@ -610,7 +812,14 @@ fn test_leave_after_many_pushes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -639,7 +848,14 @@ fn test_leave_recursive_function_simulation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; emu.regs_mut().rbp = 0x4000; emu.run(None).unwrap(); @@ -666,7 +882,14 @@ fn test_leave_with_mixed_operations() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.regs_mut().rax = 0x1111; @@ -690,7 +913,14 @@ fn test_leave_exception_handler_pattern() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -709,7 +939,14 @@ fn test_leave_tail_call_preparation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -731,7 +968,14 @@ fn test_leave_coroutine_switch_pattern() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.regs_mut().rbp = 0x3000; emu.regs_mut().rax = 0xAA; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/mod.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/mod.rs index d23ea8c9..4cb5666c 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/mod.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/mod.rs @@ -1,11 +1,11 @@ -mod push; -mod pop; -mod pusha_popa; -mod pushf_popf_extended; mod enter_extended; mod leave_extended; +mod pop; +mod pop_mem; +mod push; mod push_imm; mod push_mem; -mod pop_mem; -mod stack_alignment; +mod pusha_popa; +mod pushf_popf_extended; mod rsp_operations; +mod stack_alignment; diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pop/pop.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pop/pop.rs index 91f9c739..34259469 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pop/pop.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pop/pop.rs @@ -1,4 +1,3 @@ - use crate::*; const DATA_ADDR: u64 = 0x7000; @@ -16,11 +15,22 @@ fn test_pop_rax() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = 0x1234567890ABCDEF; emu.run(None).unwrap(); - assert_eq!(emu.regs().rax, 0x1234567890ABCDEF, "RAX restored from stack"); + assert_eq!( + emu.regs().rax, + 0x1234567890ABCDEF, + "RAX restored from stack" + ); assert_eq!(emu.regs().rsp, 0x1000, "RSP back to original"); } @@ -36,7 +46,14 @@ fn test_pop_rbx() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rbx, 0x44332211, "RBX restored"); @@ -47,7 +64,14 @@ fn test_pop_rcx() { let code = [0x51, 0x59, 0xf4]; // PUSH RCX, POP RCX, HLT let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rcx = 0xAAAAAAAABBBBBBBB; emu.run(None).unwrap(); @@ -64,7 +88,14 @@ fn test_pop_all_gp_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = 0x1111111111111111; emu.regs_mut().rbx = 0x2222222222222222; @@ -96,7 +127,14 @@ fn test_pop_r8() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().r8 = 0xCCCCCCCCCCCCCCCC; emu.run(None).unwrap(); @@ -112,7 +150,14 @@ fn test_pop_r15() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().r15 = 0xDDDDDDDDDDDDDDDD; emu.run(None).unwrap(); @@ -129,10 +174,21 @@ fn test_pop_increments_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x1000, "RSP back to original after PUSH/POP"); + assert_eq!( + emu.regs().rsp, + 0x1000, + "RSP back to original after PUSH/POP" + ); assert_eq!(emu.regs().rax, 0x42, "Value popped"); } @@ -150,7 +206,14 @@ fn test_multiple_pop() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0x33, "Last pushed, first popped"); @@ -171,7 +234,14 @@ fn test_pop_preserves_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert!(emu.flags().dump() & 0x40 != 0, "ZF should still be set"); @@ -187,7 +257,14 @@ fn test_pop_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rsp, 0x1000, "RSP restored from stack"); @@ -206,7 +283,14 @@ fn test_lifo_behavior() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rdx, 3, "RDX gets last pushed (RCX=3)"); @@ -225,7 +309,14 @@ fn test_pop_zero() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0, "RAX should be 0"); @@ -243,11 +334,22 @@ fn test_pop_max_value() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // MOV r64, imm32 sign-extends: 0xFFFFFFFF becomes 0xFFFFFFFFFFFFFFFF - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFFFF, "RAX should be sign-extended max"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFFFF, + "RAX should be sign-extended max" + ); } // Practical use case: function epilogue @@ -268,7 +370,14 @@ fn test_pop_practical_function_epilogue() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.regs_mut().rax = 0x1111; @@ -293,7 +402,14 @@ fn test_pop_after_stack_manipulation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 2, "Skipped top value, got second"); @@ -311,7 +427,14 @@ fn test_pop_all_extended_regs() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().r8 = 0x08; emu.regs_mut().r9 = 0x09; @@ -350,7 +473,14 @@ fn test_push_pop_chain() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rbx, 0x33); @@ -368,7 +498,14 @@ fn test_stack_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = 0x42; emu.run(None).unwrap(); @@ -389,7 +526,14 @@ fn test_pop_same_register_multiple() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 1, "RAX has last popped value"); @@ -408,7 +552,14 @@ fn test_pop_with_mov() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rax, 0xAA, "RAX restored from stack"); @@ -419,15 +570,20 @@ fn test_pop_with_mov() { #[test] fn test_deep_stack() { let code = [ - 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0x6a, 0x04, 0x6a, 0x05, - 0x6a, 0x06, 0x6a, 0x07, 0x6a, 0x08, 0x6a, 0x09, 0x6a, 0x0a, - // Pop all back - 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, - 0xf4, // HLT + 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0x6a, 0x04, 0x6a, 0x05, 0x6a, 0x06, 0x6a, 0x07, 0x6a, + 0x08, 0x6a, 0x09, 0x6a, 0x0a, // Pop all back + 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xf4, // HLT ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rsp, 0x1000, "Deep stack balanced"); @@ -446,11 +602,22 @@ fn test_pop_preserves_other_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // PUSH imm8 sign-extends: 0x99 (bit 7 set) -> 0xFFFFFFFFFFFFFF99 - assert_eq!(emu.regs().rax, 0xFFFFFFFFFFFFFF99, "RAX popped (sign-extended)"); + assert_eq!( + emu.regs().rax, + 0xFFFFFFFFFFFFFF99, + "RAX popped (sign-extended)" + ); assert_eq!(emu.regs().rbx, 0x33, "RBX unchanged"); assert_eq!(emu.regs().rcx, 0x44, "RCX unchanged"); } diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/push_imm.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/push_imm.rs index a472a028..9f511b87 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/push_imm.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/push_imm.rs @@ -20,7 +20,14 @@ fn test_push_imm8_zero() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -37,7 +44,14 @@ fn test_push_imm8_positive_small() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -53,7 +67,14 @@ fn test_push_imm8_positive_medium() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -69,7 +90,14 @@ fn test_push_imm8_max_positive() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -85,7 +113,14 @@ fn test_push_imm8_negative_one() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -101,7 +136,14 @@ fn test_push_imm8_negative_small() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -117,7 +159,14 @@ fn test_push_imm8_negative_medium() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -133,7 +182,14 @@ fn test_push_imm8_min_negative() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -152,7 +208,14 @@ fn test_push_imm8_boundary_values() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -183,7 +246,14 @@ fn test_push_imm32_zero() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -200,7 +270,14 @@ fn test_push_imm32_small_positive() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -216,7 +293,14 @@ fn test_push_imm32_medium_positive() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -232,7 +316,14 @@ fn test_push_imm32_large_positive() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -248,7 +339,14 @@ fn test_push_imm32_negative_one() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -264,7 +362,14 @@ fn test_push_imm32_negative_small() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -280,7 +385,14 @@ fn test_push_imm32_negative_large() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -296,7 +408,14 @@ fn test_push_imm32_pattern_deadbeef() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -312,7 +431,14 @@ fn test_push_imm32_pattern_cafebabe() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -336,7 +462,14 @@ fn test_push_imm8_sequence() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -362,7 +495,14 @@ fn test_push_imm32_sequence() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -383,7 +523,14 @@ fn test_push_imm_mixed_sizes() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -407,7 +554,14 @@ fn test_push_imm8_pop_roundtrip() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -424,7 +578,14 @@ fn test_push_imm32_pop_roundtrip() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -441,7 +602,14 @@ fn test_push_imm_negative_pop() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -462,7 +630,14 @@ fn test_push_imm_preserves_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -479,7 +654,14 @@ fn test_push_imm_preserves_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -504,7 +686,14 @@ fn test_push_imm_function_params() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -521,7 +710,14 @@ fn test_push_imm_large_params() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.run(None).unwrap(); @@ -542,7 +738,14 @@ fn test_push_imm8_all_ones() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -558,7 +761,14 @@ fn test_push_imm32_all_ones() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -574,7 +784,14 @@ fn test_push_imm_at_low_stack() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x10-(0x10 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x10 - (0x10 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x10; emu.run(None).unwrap(); @@ -592,7 +809,14 @@ fn test_push_imm_rapid_sequence() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x2000-(0x2000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x2000 - (0x2000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x2000; emu.run(None).unwrap(); @@ -615,7 +839,14 @@ fn test_push_imm32_alternating_bits() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -631,7 +862,14 @@ fn test_push_imm32_inverse_alternating() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -650,7 +888,14 @@ fn test_push_imm32_high_bit_set() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -666,7 +911,14 @@ fn test_push_imm32_high_bit_clear() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -692,7 +944,14 @@ fn test_push_imm_powers_of_two() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -715,7 +974,14 @@ fn test_push_imm_ascii_values() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -741,7 +1007,14 @@ fn test_push_imm_boolean_values() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -763,7 +1036,14 @@ fn test_push_imm_then_add() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -782,7 +1062,14 @@ fn test_push_imm_multiple_ops() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -805,7 +1092,14 @@ fn test_push_imm_stack_based_calc() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pushf_popf_extended.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pushf_popf_extended.rs index c1777c1d..d26217cf 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pushf_popf_extended.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/pushf_popf_extended.rs @@ -24,14 +24,25 @@ fn test_pushfq_basic() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rsp, 0x0FF8, "RSP decremented by 8"); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags, 0, "Flags should be pushed"); } @@ -45,12 +56,23 @@ fn test_pushfq_with_carry_set() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x01, 0, "CF should be set in pushed flags"); } @@ -64,12 +86,23 @@ fn test_pushfq_with_zero_set() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x40, 0, "ZF should be set in pushed flags"); } @@ -84,12 +117,23 @@ fn test_pushfq_with_sign_set() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x80, 0, "SF should be set in pushed flags"); } @@ -105,12 +149,23 @@ fn test_pushfq_multiple_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x01, 0, "CF should be set"); assert_ne!(pushed_flags & 0x40, 0, "ZF should be set"); @@ -126,7 +181,14 @@ fn test_pushfq_preserves_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -145,16 +207,31 @@ fn test_pushfq_multiple_times() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); assert_eq!(emu.regs().rsp, 0x1000 - 16, "RSP decremented twice"); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let first_flags = u64::from_le_bytes(stack_val); - stack_val = emu.maps.read_bytes(0x0FF0, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF0, stack_val.len()) + .try_into() + .unwrap(); let second_flags = u64::from_le_bytes(stack_val); assert_ne!(first_flags & 0x01, 0, "First PUSHFQ has CF set"); @@ -175,7 +252,14 @@ fn test_popfq_basic() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -193,7 +277,14 @@ fn test_popfq_restore_carry() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -212,7 +303,14 @@ fn test_popfq_restore_zero() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -231,7 +329,14 @@ fn test_popfq_restore_sign() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -253,7 +358,14 @@ fn test_popfq_restore_all_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -272,7 +384,14 @@ fn test_popfq_preserves_registers() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -295,7 +414,14 @@ fn test_pushfq_popfq_roundtrip() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -316,7 +442,14 @@ fn test_pushfq_popfq_nested() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -338,7 +471,14 @@ fn test_pushfq_popfq_with_arithmetic() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -359,11 +499,21 @@ fn test_pushfq_modify_on_stack() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be set from modified stack value"); + assert!( + emu.flags().f_cf, + "CF should be set from modified stack value" + ); } #[test] @@ -380,7 +530,14 @@ fn test_multiple_pushfq_popfq() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -400,7 +557,14 @@ fn test_pushf_16bit() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -416,7 +580,14 @@ fn test_popf_16bit() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -435,7 +606,14 @@ fn test_pushfq_at_stack_boundary() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x08-(0x08 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x08 - (0x08 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x08; // Near bottom of memory emu.run(None).unwrap(); @@ -450,7 +628,14 @@ fn test_popfq_from_prepared_stack() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x3000-(0x3000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x3000 - (0x3000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x3000; let flags_with_cf = 0x0001u64; @@ -471,12 +656,23 @@ fn test_pushfq_popfq_preserves_reserved_bits() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(emu.regs().rsp, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(emu.regs().rsp, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x02, 0, "Reserved bit 1 should be set"); @@ -494,12 +690,23 @@ fn test_pushfq_with_overflow() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x800, 0, "OF should be set in pushed flags"); } @@ -517,7 +724,14 @@ fn test_popfq_restore_overflow() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -533,12 +747,23 @@ fn test_pushfq_with_direction_flag() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x400, 0, "DF should be set in pushed flags"); } @@ -554,7 +779,14 @@ fn test_popfq_restore_direction_flag() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -582,7 +814,14 @@ fn test_pushfq_popfq_with_all_status_flags() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -602,16 +841,31 @@ fn test_pushfq_after_comparison() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_eq!(pushed_flags & 0x01, 0, "CF should be clear (10 >= 5)"); assert_eq!(pushed_flags & 0x40, 0, "ZF should be clear (10 != 5)"); - assert_eq!(pushed_flags & 0x80, 0, "SF should be clear (positive result)"); + assert_eq!( + pushed_flags & 0x80, + 0, + "SF should be clear (positive result)" + ); } #[test] @@ -629,11 +883,21 @@ fn test_popfq_after_comparison() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be restored from first comparison"); + assert!( + emu.flags().f_cf, + "CF should be restored from first comparison" + ); } #[test] @@ -657,11 +921,21 @@ fn test_pushfq_popfq_in_loop_simulation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert!(emu.flags().f_cf, "CF should be preserved through multiple save/restore"); + assert!( + emu.flags().f_cf, + "CF should be preserved through multiple save/restore" + ); assert_eq!(emu.regs().rsp, 0x1000, "Stack should be balanced"); } @@ -675,12 +949,23 @@ fn test_pushfq_with_parity_flag() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x04, 0, "PF should be set in pushed flags"); } @@ -698,7 +983,14 @@ fn test_popfq_restore_parity() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -715,12 +1007,23 @@ fn test_pushfq_with_auxiliary_carry() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); let mut stack_val = [0u8; 8]; - stack_val = emu.maps.read_bytes(0x0FF8, stack_val.len()).try_into().unwrap(); + stack_val = emu + .maps + .read_bytes(0x0FF8, stack_val.len()) + .try_into() + .unwrap(); let pushed_flags = u64::from_le_bytes(stack_val); assert_ne!(pushed_flags & 0x10, 0, "AF should be set in pushed flags"); } @@ -737,7 +1040,14 @@ fn test_popfq_restore_auxiliary_carry() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/rsp_operations.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/rsp_operations.rs index 2f03f873..ea1a6245 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/rsp_operations.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/rsp_operations.rs @@ -22,7 +22,14 @@ fn test_add_rsp_8() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -37,7 +44,14 @@ fn test_add_rsp_16() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -52,7 +66,14 @@ fn test_add_rsp_32() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -67,7 +88,14 @@ fn test_add_rsp_large() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -84,11 +112,22 @@ fn test_add_rsp_cleanup_params() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x1000, "Stack cleaned up after parameter push"); + assert_eq!( + emu.regs().rsp, + 0x1000, + "Stack cleaned up after parameter push" + ); } // ============================================================================ @@ -103,7 +142,14 @@ fn test_sub_rsp_8() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -118,7 +164,14 @@ fn test_sub_rsp_16() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -133,7 +186,14 @@ fn test_sub_rsp_32() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -148,7 +208,14 @@ fn test_sub_rsp_large_frame() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x10000-(0x10000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x10000 - (0x10000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x10000; emu.run(None).unwrap(); @@ -165,7 +232,14 @@ fn test_sub_rsp_for_locals() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -184,7 +258,14 @@ fn test_mov_rsp_rax() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = 0x2000; emu.run(None).unwrap(); @@ -200,7 +281,14 @@ fn test_mov_rsp_rbx() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbx = 0x3000; emu.run(None).unwrap(); @@ -216,12 +304,23 @@ fn test_mov_rsp_rbp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0x2000, "RSP set from RBP (like LEAVE part 1)"); + assert_eq!( + emu.regs().rsp, + 0x2000, + "RSP set from RBP (like LEAVE part 1)" + ); } #[test] @@ -232,7 +331,14 @@ fn test_mov_rsp_r8() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().r8 = 0x4000; emu.run(None).unwrap(); @@ -252,7 +358,14 @@ fn test_mov_rax_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -268,7 +381,14 @@ fn test_mov_rbx_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -283,11 +403,22 @@ fn test_mov_rbp_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rbp, 0x1000, "RBP gets RSP value (prologue pattern)"); + assert_eq!( + emu.regs().rbp, + 0x1000, + "RBP gets RSP value (prologue pattern)" + ); } #[test] @@ -300,7 +431,14 @@ fn test_save_restore_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -319,7 +457,14 @@ fn test_lea_rsp_rsp_plus_8() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -334,7 +479,14 @@ fn test_lea_rsp_rsp_minus_8() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -349,7 +501,14 @@ fn test_lea_rsp_rsp_plus_16() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -364,7 +523,14 @@ fn test_lea_rsp_rbp_minus_offset() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbp = 0x2000; emu.run(None).unwrap(); @@ -384,7 +550,14 @@ fn test_inc_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -399,7 +572,14 @@ fn test_dec_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -417,7 +597,14 @@ fn test_multiple_inc_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -436,7 +623,14 @@ fn test_xchg_rsp_rax() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = 0x2000; emu.run(None).unwrap(); @@ -453,7 +647,14 @@ fn test_xchg_rsp_rbx() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbx = 0x3000; emu.run(None).unwrap(); @@ -475,7 +676,14 @@ fn test_rsp_alloc_dealloc_cycle() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -493,7 +701,14 @@ fn test_rsp_save_alloc_restore() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -510,7 +725,14 @@ fn test_rsp_with_stack_operations() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -528,7 +750,14 @@ fn test_rsp_lea_cleanup() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -547,7 +776,14 @@ fn test_add_rsp_rax() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = 0x100; emu.run(None).unwrap(); @@ -563,7 +799,14 @@ fn test_sub_rsp_rbx() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rbx = 0x50; emu.run(None).unwrap(); @@ -579,7 +822,14 @@ fn test_and_rsp_align() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1008-(0x1008 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1008 - (0x1008 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1008; emu.run(None).unwrap(); @@ -598,7 +848,14 @@ fn test_mov_rsp_from_memory() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.regs_mut().rax = DATA_ADDR; @@ -617,7 +874,14 @@ fn test_mov_memory_from_rsp() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1234-(0x1234 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1234 - (0x1234 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1234; emu.regs_mut().rax = DATA_ADDR; emu.run(None).unwrap(); @@ -638,7 +902,14 @@ fn test_rsp_zero() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -653,11 +924,22 @@ fn test_rsp_max_value() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp, 0xFFFFFFFFFFFFFFFF, "RSP can be set to max value"); + assert_eq!( + emu.regs().rsp, + 0xFFFFFFFFFFFFFFFF, + "RSP can be set to max value" + ); } #[test] @@ -668,7 +950,14 @@ fn test_rsp_wraparound_add() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0xFFFFFFFFFFFFFFF0-(0xFFFFFFFFFFFFFFF0 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0xFFFFFFFFFFFFFFF0 - (0xFFFFFFFFFFFFFFF0 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0xFFFFFFFFFFFFFFF0; emu.run(None).unwrap(); @@ -686,7 +975,14 @@ fn test_rsp_complex_calculation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -708,7 +1004,14 @@ fn test_rsp_in_loop_simulation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); diff --git a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/stack_alignment.rs b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/stack_alignment.rs index 25f44c36..765fed7a 100644 --- a/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/stack_alignment.rs +++ b/crates/libmwemu/src/tests/isa/x86/rax_x86_tests/stack_operations/stack_alignment.rs @@ -18,7 +18,14 @@ fn test_stack_alignment_16_byte() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; // 16-byte aligned emu.run(None).unwrap(); @@ -32,7 +39,14 @@ fn test_stack_misalignment_8_byte() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1008-(0x1008 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1008 - (0x1008 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1008; // 8-byte aligned, not 16-byte aligned emu.run(None).unwrap(); @@ -48,11 +62,22 @@ fn test_single_push_breaks_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; // 16-byte aligned emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp & 0x0F, 8, "RSP offset by 8 from 16-byte boundary"); + assert_eq!( + emu.regs().rsp & 0x0F, + 8, + "RSP offset by 8 from 16-byte boundary" + ); } #[test] @@ -64,11 +89,22 @@ fn test_two_pushes_restore_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; // 16-byte aligned emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp & 0x0F, 0, "RSP is 16-byte aligned after two pushes"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "RSP is 16-byte aligned after two pushes" + ); } #[test] @@ -79,7 +115,14 @@ fn test_odd_pushes_misalign() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -94,7 +137,14 @@ fn test_four_pushes_aligned() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -113,11 +163,22 @@ fn test_enter_maintains_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp & 0x0F, 8, "ENTER pushes RBP (8 bytes), misaligning"); + assert_eq!( + emu.regs().rsp & 0x0F, + 8, + "ENTER pushes RBP (8 bytes), misaligning" + ); } #[test] @@ -128,12 +189,23 @@ fn test_enter_with_even_allocation() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // PUSH RBP (8) + SUB RSP, 16 = 24 bytes total, misaligned - assert_eq!(emu.regs().rsp & 0x0F, 8, "ENTER 16,0 results in misalignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 8, + "ENTER 16,0 results in misalignment" + ); } #[test] @@ -144,7 +216,14 @@ fn test_enter_with_alignment_padding() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -161,11 +240,22 @@ fn test_enter_leave_alignment_roundtrip() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp & 0x0F, 0, "ENTER/LEAVE roundtrip preserves alignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "ENTER/LEAVE roundtrip preserves alignment" + ); } // ============================================================================ @@ -180,7 +270,14 @@ fn test_push_imm_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -190,13 +287,19 @@ fn test_push_imm_alignment() { #[test] fn test_multiple_push_imm_pattern() { let code = [ - 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0x6a, 0x04, - 0x6a, 0x05, 0x6a, 0x06, 0x6a, 0x07, 0x6a, 0x08, - 0xf4, // HLT + 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0x6a, 0x04, 0x6a, 0x05, 0x6a, 0x06, 0x6a, 0x07, 0x6a, + 0x08, 0xf4, // HLT ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -216,7 +319,14 @@ fn test_sub_rsp_16_aligned() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -231,7 +341,14 @@ fn test_sub_rsp_8_misaligned() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -246,7 +363,14 @@ fn test_sub_rsp_32_aligned() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -261,7 +385,14 @@ fn test_sub_rsp_48_aligned() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -276,7 +407,14 @@ fn test_sub_rsp_odd_value() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -295,7 +433,14 @@ fn test_align_stack_with_and() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1008-(0x1008 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1008 - (0x1008 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1008; // Misaligned emu.run(None).unwrap(); @@ -311,7 +456,14 @@ fn test_align_already_aligned_stack() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; // Already aligned emu.run(None).unwrap(); @@ -332,12 +484,23 @@ fn test_function_prologue_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // PUSH RBP (8) + SUB 16 = 24 bytes, misaligned - assert_eq!(emu.regs().rsp & 0x0F, 8, "Standard prologue results in misalignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 8, + "Standard prologue results in misalignment" + ); } #[test] @@ -351,12 +514,23 @@ fn test_function_prologue_with_saved_regs() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // PUSH RBP (8) + PUSH RBX (8) + SUB 8 = 24 bytes, misaligned - assert_eq!(emu.regs().rsp & 0x0F, 8, "Prologue with saved reg misaligned"); + assert_eq!( + emu.regs().rsp & 0x0F, + 8, + "Prologue with saved reg misaligned" + ); } #[test] @@ -369,12 +543,23 @@ fn test_function_prologue_aligned_locals() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // PUSH RBP (8) + SUB 8 = 16 bytes, aligned - assert_eq!(emu.regs().rsp & 0x0F, 0, "Aligned prologue with 8-byte adjust"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "Aligned prologue with 8-byte adjust" + ); } // ============================================================================ @@ -390,7 +575,14 @@ fn test_push_pop_alignment_restoration() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -406,7 +598,14 @@ fn test_sub_add_alignment_restoration() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -432,41 +631,67 @@ fn test_nested_function_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp & 0x0F, 0, "Nested functions maintain alignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "Nested functions maintain alignment" + ); } #[test] fn test_alignment_with_parameter_passing() { let code = [ // Push 6 parameters (odd number) - 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, - 0x6a, 0x04, 0x6a, 0x05, 0x6a, 0x06, - 0xf4, // HLT + 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0x6a, 0x04, 0x6a, 0x05, 0x6a, 0x06, 0xf4, // HLT ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // 6 * 8 = 48 bytes, maintains alignment - assert_eq!(emu.regs().rsp & 0x0F, 0, "Six parameters maintain alignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "Six parameters maintain alignment" + ); } #[test] fn test_alignment_with_odd_parameters() { let code = [ // Push 3 parameters (odd number) - 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, - 0xf4, // HLT + 0x6a, 0x01, 0x6a, 0x02, 0x6a, 0x03, 0xf4, // HLT ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -489,7 +714,14 @@ fn test_check_multiple_alignment_points() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -503,11 +735,23 @@ fn test_alignment_at_various_addresses() { emu.load_code_bytes(&code); for addr in [0x1000, 0x2000, 0x3000, 0x4000, 0x10000, 0x100000].iter() { - emu.maps.create_map("stack_test", *addr-(*addr / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); - emu.regs_mut().rsp = *addr; - emu.run(None).unwrap(); - - assert_eq!(emu.regs().rsp & 0x0F, 0, "Address 0x{:x} is 16-byte aligned", addr); + emu.maps + .create_map( + "stack_test", + *addr - (*addr / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); + emu.regs_mut().rsp = *addr; + emu.run(None).unwrap(); + + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "Address 0x{:x} is 16-byte aligned", + addr + ); } } @@ -520,7 +764,14 @@ fn test_pushfq_popfq_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); @@ -535,11 +786,22 @@ fn test_large_stack_frame_alignment() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x10000-(0x10000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x10000 - (0x10000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x10000; emu.run(None).unwrap(); - assert_eq!(emu.regs().rsp & 0x0F, 0, "Large allocation maintains alignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "Large allocation maintains alignment" + ); assert_eq!(emu.regs().rsp, 0xF000, "4KB frame allocated"); } @@ -554,10 +816,21 @@ fn test_alignment_after_mixed_operations() { ]; let mut emu = emu64(); emu.load_code_bytes(&code); - emu.maps.create_map("stack_test", 0x1000-(0x1000 / 2), 0x1000, crate::maps::mem64::Permission::READ_WRITE_EXECUTE).unwrap(); + emu.maps + .create_map( + "stack_test", + 0x1000 - (0x1000 / 2), + 0x1000, + crate::maps::mem64::Permission::READ_WRITE_EXECUTE, + ) + .unwrap(); emu.regs_mut().rsp = 0x1000; emu.run(None).unwrap(); // PUSH(8) + SUB(8) + PUSH(8) + SUB(8) = 32 bytes, aligned - assert_eq!(emu.regs().rsp & 0x0F, 0, "Mixed operations maintain alignment"); + assert_eq!( + emu.regs().rsp & 0x0F, + 0, + "Mixed operations maintain alignment" + ); } diff --git a/crates/libmwemu/src/tests/loaders/elf64/elf64lin_dynamic_hello.rs b/crates/libmwemu/src/tests/loaders/elf64/elf64lin_dynamic_hello.rs new file mode 100644 index 00000000..0561c793 --- /dev/null +++ b/crates/libmwemu/src/tests/loaders/elf64/elf64lin_dynamic_hello.rs @@ -0,0 +1,83 @@ +use std::sync::atomic::Ordering; + +use crate::tests::helpers; +use crate::*; + +/// Dynamic Linux x86_64 hello world using `puts`, built from +/// `fixtures/elf64_x86_64_linux_hello.c`. +const ELF64_LINUX_X64_HELLO: &[u8] = include_bytes!("../../fixtures/elf64_x86_64_linux_hello.bin"); + +#[test] +fn elf64lin_dynamic_hello_puts_bridge() { + helpers::setup(); + + let tmp = std::env::temp_dir().join("mwemu_test_elf64_x86_64_linux_hello.bin"); + std::fs::write(&tmp, ELF64_LINUX_X64_HELLO).unwrap(); + + let mut emu = emu64(); + emu.load_code(tmp.to_str().unwrap()); + + assert!(emu.cfg.arch.is_x64()); + assert!(emu.os.is_linux(), "expected Linux loader path"); + assert!(emu.elf64.is_some(), "ELF metadata should be loaded"); + + let elf = emu.elf64.as_ref().unwrap(); + assert!( + elf.needed_libs.iter().any(|lib| lib.contains("libc.so.6")), + "expected libc.so.6 in DT_NEEDED, got {:?}", + elf.needed_libs + ); + + let start_main_addr = *elf + .sym_to_addr + .get("__libc_start_main") + .expect("expected __libc_start_main to resolve into the linux stub libc"); + let puts_addr = *elf + .sym_to_addr + .get("puts") + .expect("expected puts to resolve into the linux stub libc"); + + let start_main_map = emu + .maps + .get_addr_name(start_main_addr) + .unwrap_or("unmapped"); + let puts_map = emu.maps.get_addr_name(puts_addr).unwrap_or("unmapped"); + assert!( + start_main_map.contains("libc.so.6"), + "__libc_start_main should map into libc.so.6, got '{}'", + start_main_map + ); + assert!( + puts_map.contains("libc.so.6"), + "puts should map into libc.so.6, got '{}'", + puts_map + ); + + let mut saw_unix_api_break = false; + for i in 0..32 { + let rip_before = emu.regs().rip; + let ok = emu.step(); + assert!(ok, "step {} failed at rip=0x{:x}", i, rip_before); + assert_ne!(emu.regs().rip, 0, "rip should never fall to 0"); + + if emu.force_break { + saw_unix_api_break = true; + break; + } + } + + assert!( + saw_unix_api_break, + "expected to intercept the Linux x86_64 startup/libc path" + ); + assert_eq!( + emu.is_running.load(Ordering::Relaxed), + 0, + "the process should be stopped after __libc_start_main drives main -> exit" + ); + assert_eq!( + emu.regs().rdi, + 7, + "main return value should be forwarded into exit(status)" + ); +} diff --git a/crates/libmwemu/src/tests/loaders/elf64/mod.rs b/crates/libmwemu/src/tests/loaders/elf64/mod.rs index 6486157b..d8028d1b 100644 --- a/crates/libmwemu/src/tests/loaders/elf64/mod.rs +++ b/crates/libmwemu/src/tests/loaders/elf64/mod.rs @@ -1,4 +1,5 @@ mod elf64_aarch64_basic; +mod elf64lin_dynamic_hello; mod elf64lin_cpu_arithmetics; mod elf64lin_flags; mod elf64lin_fpu; diff --git a/crates/libmwemu/src/tests/loaders/macho/macho64_hello.rs b/crates/libmwemu/src/tests/loaders/macho/macho64_hello.rs index d3eb1607..28a3928f 100644 --- a/crates/libmwemu/src/tests/loaders/macho/macho64_hello.rs +++ b/crates/libmwemu/src/tests/loaders/macho/macho64_hello.rs @@ -31,10 +31,8 @@ fn macho64_hello_raw_syscall() { for i in 0..20 { let pc_before = emu.regs_aarch64().pc; let ok = emu.step(); - if !ok { - eprintln!("step {} failed at pc=0x{:x}", i, pc_before); - break; - } + assert!(ok, "step {} failed at pc=0x{:x}", i, pc_before); + assert_ne!(emu.regs_aarch64().pc, 0, "pc should never fall to 0"); // After executing SVC for write (x16=4), check x0/x1/x2 // After executing SVC for exit (x16=1), stop if emu.regs_aarch64().x[16] == 1 { @@ -58,22 +56,42 @@ fn macho64_hello_libc_load() { assert!(emu.cfg.arch.is_aarch64()); let pc = emu.regs_aarch64().pc; assert!(pc >= 0x100000000, "entry 0x{:x} should be in __TEXT", pc); + assert!(emu.macho64.is_some(), "Mach-O metadata should be loaded"); + + let macho = emu.macho64.as_ref().unwrap(); + let printf_addr = macho + .addr_to_symbol + .iter() + .find(|(_, sym)| sym.trim_start_matches('_').contains("printf")) + .map(|(addr, sym)| (*addr, sym.clone())) + .expect("expected a resolved printf symbol in the loaded dylib map"); - // Try to run and see what fails - this needs dylib support + let printf_map = emu.maps.get_addr_name(printf_addr.0).unwrap_or("unmapped"); + assert!( + printf_map.contains("libSystem.B"), + "printf should resolve into libSystem.B, got map '{}' at 0x{:x} ({})", + printf_map, + printf_addr.0, + printf_addr.1 + ); + + // Step until the first intercepted API call. Success means we reach a + // library call, break cleanly, and never fall off into pc=0x0. + let mut saw_api_break = false; let mut last_pc = pc; - let mut steps = 0; - for i in 0..50 { + for i in 0..100 { + let pc_before = emu.regs_aarch64().pc; let ok = emu.step(); - if !ok { - eprintln!( - "step {} failed at pc=0x{:x} (instruction not implemented or bad memory access)", - i, - emu.regs_aarch64().pc - ); + assert!(ok, "step {} failed at pc=0x{:x}", i, pc_before); + last_pc = emu.regs_aarch64().pc; + assert_ne!(last_pc, 0, "pc should never fall to 0"); + + if emu.force_break { + saw_api_break = true; break; } - last_pc = emu.regs_aarch64().pc; - steps = i + 1; } - eprintln!("executed {} steps, last_pc=0x{:x}", steps, last_pc); + + assert!(saw_api_break, "expected to intercept a libSystem API call"); + assert_ne!(last_pc, 0, "final pc should be a valid return address"); } diff --git a/crates/libmwemu/src/tests/loaders/macho/macho64_x64_hello.rs b/crates/libmwemu/src/tests/loaders/macho/macho64_x64_hello.rs new file mode 100644 index 00000000..85b7a759 --- /dev/null +++ b/crates/libmwemu/src/tests/loaders/macho/macho64_x64_hello.rs @@ -0,0 +1,100 @@ +use crate::tests::helpers; +use crate::*; + +/// Raw macOS x86_64 syscall hello world (no libc, no dylibs). +/// Built from `fixtures/macho64_x86_64_hello_raw.s`. +const HELLO_RAW_X64: &[u8] = include_bytes!("../../fixtures/macho64_x86_64_hello_raw.bin"); + +/// macOS x86_64 libc-linked hello world using `puts`. +/// Built from `fixtures/macho64_x86_64_hello.c`. +const HELLO_LIBC_X64: &[u8] = include_bytes!("../../fixtures/macho64_x86_64_hello.bin"); + +#[test] +fn macho64_x64_hello_raw_syscall() { + helpers::setup(); + + let tmp = std::env::temp_dir().join("mwemu_test_macho64_x64_hello_raw.bin"); + std::fs::write(&tmp, HELLO_RAW_X64).unwrap(); + + let mut emu = emu64(); + emu.load_code(tmp.to_str().unwrap()); + + assert!(emu.cfg.arch.is_x64()); + assert!(emu.os.is_macos(), "expected macOS loader path"); + + let entry = emu.regs().rip; + assert!( + entry >= 0x100000000, + "entry 0x{:x} should be in __TEXT", + entry + ); + + let stopped_at = emu + .run(None) + .expect("raw macOS x86_64 syscall hello should exit cleanly"); + + assert_ne!(stopped_at, 0, "run() should not stop at pc=0"); + assert!( + emu.pos > 0, + "emulation should execute at least one instruction" + ); + assert_eq!(emu.regs().rax, 0x2000001, "final syscall should be exit"); + assert_eq!(emu.regs().rdi, 0, "exit status should be zero"); +} + +#[test] +fn macho64_x64_hello_libc_intercepts_puts() { + helpers::setup(); + + let tmp = std::env::temp_dir().join("mwemu_test_macho64_x64_hello_libc.bin"); + std::fs::write(&tmp, HELLO_LIBC_X64).unwrap(); + + let mut emu = emu64(); + emu.load_code(tmp.to_str().unwrap()); + + assert!(emu.cfg.arch.is_x64()); + assert!(emu.os.is_macos(), "expected macOS loader path"); + assert!(emu.macho64.is_some(), "Mach-O metadata should be loaded"); + + let macho = emu.macho64.as_ref().unwrap(); + let puts_addr = macho + .addr_to_symbol + .iter() + .find(|(_, sym)| sym.trim_start_matches('_') == "puts") + .map(|(addr, sym)| (*addr, sym.clone())) + .expect("expected a resolved puts symbol in the loaded dylib map"); + + let puts_map = emu.maps.get_addr_name(puts_addr.0).unwrap_or("unmapped"); + assert!( + puts_map.contains("libSystem.B"), + "puts should resolve into libSystem.B, got map '{}' at 0x{:x} ({})", + puts_map, + puts_addr.0, + puts_addr.1 + ); + + let mut saw_api_break = false; + for i in 0..128 { + let rip_before = emu.regs().rip; + let ok = emu.step(); + assert!(ok, "step {} failed at rip=0x{:x}", i, rip_before); + assert_ne!(emu.regs().rip, 0, "rip should never fall to 0"); + + if emu.force_break { + saw_api_break = true; + break; + } + } + + assert!(saw_api_break, "expected to intercept a libSystem API call"); + assert_eq!( + emu.regs().rax, + 0, + "puts should return 0 through the API shim" + ); + assert_ne!( + emu.regs().rip, + 0, + "final rip should be a valid return address" + ); +} diff --git a/crates/libmwemu/src/tests/loaders/macho/mod.rs b/crates/libmwemu/src/tests/loaders/macho/mod.rs index bfe28bfe..9197efaf 100644 --- a/crates/libmwemu/src/tests/loaders/macho/mod.rs +++ b/crates/libmwemu/src/tests/loaders/macho/mod.rs @@ -1,2 +1,3 @@ mod macho64_basic; mod macho64_hello; +mod macho64_x64_hello; diff --git a/crates/libmwemu/src/tests/loaders/pe/exe64win_enigma.rs b/crates/libmwemu/src/tests/loaders/pe/exe64win_enigma.rs index 3eadc7d1..a813bdfc 100644 --- a/crates/libmwemu/src/tests/loaders/pe/exe64win_enigma.rs +++ b/crates/libmwemu/src/tests/loaders/pe/exe64win_enigma.rs @@ -15,9 +15,8 @@ pub fn exe64win_enigma() { emu.run_to(5_000_000 + 5); assert!(emu.pos >= 5_000_000); /* - too slow for a test: + too slow for a test: emu.run_to(102072786); assert!(emu.pos > 102072780); */ - } diff --git a/crates/libmwemu/src/tests/loaders/pe/mingw_tests.rs b/crates/libmwemu/src/tests/loaders/pe/mingw_tests.rs index fbffc28d..c9bee44b 100644 --- a/crates/libmwemu/src/tests/loaders/pe/mingw_tests.rs +++ b/crates/libmwemu/src/tests/loaders/pe/mingw_tests.rs @@ -11,7 +11,8 @@ fn test_mingw32() { let sample = "../../test/exe32win_mingw.bin"; emu.load_code(sample); // Keep this test aligned with the CLI check window where execution reaches ~119. - emu.run_to(119).expect("mingw32 should reach the early execution window"); + emu.run_to(119) + .expect("mingw32 should reach the early execution window"); assert!(emu.pos >= 119); } @@ -25,4 +26,4 @@ fn test_mingw64() { let sample = "../../test/exe64win_mingw.bin"; emu.load_code(sample); emu.run_to(100); -} \ No newline at end of file +} diff --git a/crates/libmwemu/src/tests/loaders/pe/pe64_loader_tests.rs b/crates/libmwemu/src/tests/loaders/pe/pe64_loader_tests.rs index 98ff8df5..556b9fa8 100644 --- a/crates/libmwemu/src/tests/loaders/pe/pe64_loader_tests.rs +++ b/crates/libmwemu/src/tests/loaders/pe/pe64_loader_tests.rs @@ -10,7 +10,10 @@ fn pe64_loader_sets_entrypoint_and_maps_main_image() { emu.load_code("../../test/exe64win_msgbox.bin"); assert!(emu.pe64.is_some(), "PE64 metadata should be loaded"); - assert!(emu.maps.is_mapped(emu.regs().rip), "RIP should point to mapped memory"); + assert!( + emu.maps.is_mapped(emu.regs().rip), + "RIP should point to mapped memory" + ); let map_name = emu.maps.get_addr_name(emu.regs().rip).unwrap_or("unknown"); assert!( @@ -61,4 +64,3 @@ fn pe64_loader_normalizes_api_set_dependencies() { deps ); } - diff --git a/crates/libmwemu/src/tests/loaders/pe/peb_teb_ldr_structures_test.rs b/crates/libmwemu/src/tests/loaders/pe/peb_teb_ldr_structures_test.rs index ba3b0aec..a1ac9674 100644 --- a/crates/libmwemu/src/tests/loaders/pe/peb_teb_ldr_structures_test.rs +++ b/crates/libmwemu/src/tests/loaders/pe/peb_teb_ldr_structures_test.rs @@ -1,5 +1,5 @@ -use crate::{tests::helpers, *}; use crate::windows::structures; +use crate::{tests::helpers, *}; #[test] // peb/teb/ldr basic tests diff --git a/crates/libmwemu/src/tests/os/ssdt_win64_tests.rs b/crates/libmwemu/src/tests/os/ssdt_win64_tests.rs index c759433d..0aea68e1 100644 --- a/crates/libmwemu/src/tests/os/ssdt_win64_tests.rs +++ b/crates/libmwemu/src/tests/os/ssdt_win64_tests.rs @@ -66,11 +66,12 @@ fn exe64win_msgbox_ssdt_hits_first_windows_syscall() { let hit = Rc::new(RefCell::new(false)); let hit_flag = Rc::clone(&hit); - emu.hooks.on_post_instruction(move |emu, _rip, ins, _sz, _ok| { - if emu.os.is_windows() && ins.is_x86() && ins.as_x86().mnemonic() == Mnemonic::Syscall { - *hit_flag.borrow_mut() = true; - } - }); + emu.hooks + .on_post_instruction(move |emu, _rip, ins, _sz, _ok| { + if emu.os.is_windows() && ins.is_x86() && ins.as_x86().mnemonic() == Mnemonic::Syscall { + *hit_flag.borrow_mut() = true; + } + }); emu.load_code(&sample); diff --git a/crates/libmwemu/src/tests/os/syscall64_ssdt_tests.rs b/crates/libmwemu/src/tests/os/syscall64_ssdt_tests.rs index 5a282b18..17d1ef0c 100644 --- a/crates/libmwemu/src/tests/os/syscall64_ssdt_tests.rs +++ b/crates/libmwemu/src/tests/os/syscall64_ssdt_tests.rs @@ -1,9 +1,9 @@ use std::sync::atomic::Ordering; -use crate::windows::constants::*; use crate::maps::mem64::Permission; use crate::syscall::windows::syscall64; use crate::tests::helpers; +use crate::windows::constants::*; use crate::*; fn setup_emu64_syscall() -> emu::Emu { @@ -31,10 +31,11 @@ fn nt_query_virtual_memory_success_writes_output() { emu.regs_mut().rdx = 0x400100; emu.regs_mut().r8 = MEMORY_INFORMATION_CLASS_MEMORY_BASIC_INFORMATION; emu.regs_mut().r9 = 0x500100; // MEMORY_BASIC_INFORMATION output - emu.maps - .write_qword(emu.regs().rsp + 0x28, crate::windows::structures::MemoryBasicInformation64::SIZE); // out length - emu.maps - .write_qword(emu.regs().rsp + 0x30, 0x500080); // return length ptr + emu.maps.write_qword( + emu.regs().rsp + 0x28, + crate::windows::structures::MemoryBasicInformation64::SIZE, + ); // out length + emu.maps.write_qword(emu.regs().rsp + 0x30, 0x500080); // return length ptr syscall64::gateway(&mut emu); @@ -99,7 +100,10 @@ fn nt_write_then_read_virtual_memory_roundtrip() { emu.maps.write_qword(emu.regs().rsp + 0x28, 0x550080); // bytes written ptr syscall64::gateway(&mut emu); assert_eq!(emu.regs().rax, STATUS_SUCCESS); - assert_eq!(emu.maps.read_qword(0x550080).unwrap_or(0), payload.len() as u64); + assert_eq!( + emu.maps.read_qword(0x550080).unwrap_or(0), + payload.len() as u64 + ); emu.regs_mut().rax = WIN64_NTREADVIRTUALMEMORY; emu.regs_mut().rcx = !0; @@ -109,7 +113,10 @@ fn nt_write_then_read_virtual_memory_roundtrip() { emu.maps.write_qword(emu.regs().rsp + 0x28, 0x550088); // bytes read ptr syscall64::gateway(&mut emu); assert_eq!(emu.regs().rax, STATUS_SUCCESS); - assert_eq!(emu.maps.read_qword(0x550088).unwrap_or(0), payload.len() as u64); + assert_eq!( + emu.maps.read_qword(0x550088).unwrap_or(0), + payload.len() as u64 + ); assert_eq!(emu.maps.read_bytes(0x550100, payload.len()), payload); } diff --git a/crates/libmwemu/src/tests/shellcode/sc32lin_rshell.rs b/crates/libmwemu/src/tests/shellcode/sc32lin_rshell.rs index d033e01d..e2fab20f 100644 --- a/crates/libmwemu/src/tests/shellcode/sc32lin_rshell.rs +++ b/crates/libmwemu/src/tests/shellcode/sc32lin_rshell.rs @@ -14,9 +14,7 @@ pub fn sc32lin_rshell() { let sockaddr = emu.maps.read_bytes(emu.regs().get_ecx(), 9); assert_eq!( sockaddr, - &[ - 0x02, 0x00, 0x05, 0x39, 0x01, 0x03, 0x03, 0x07, 0x01 - ][..] + &[0x02, 0x00, 0x05, 0x39, 0x01, 0x03, 0x03, 0x07, 0x01][..] ); emu.run_to(42); diff --git a/crates/libmwemu/src/tests/unit/emulation_perf.rs b/crates/libmwemu/src/tests/unit/emulation_perf.rs index 671449e6..f597f014 100644 --- a/crates/libmwemu/src/tests/unit/emulation_perf.rs +++ b/crates/libmwemu/src/tests/unit/emulation_perf.rs @@ -109,7 +109,11 @@ fn benchmark32win_donut() { emu.disable_ctrlc(); let sample = helpers::test_data_path("sc32win_donut.bin"); - assert!(std::path::Path::new(&sample).is_file(), "missing {}", sample); + assert!( + std::path::Path::new(&sample).is_file(), + "missing {}", + sample + ); emu.load_code(&sample); // `-vv` → verbose level 2 (assembly tracing). @@ -166,7 +170,11 @@ fn benchmark64with_enigma() { emu.disable_ctrlc(); let sample = helpers::test_data_path("exe64win_enigma.bin"); - assert!(std::path::Path::new(&sample).is_file(), "missing {}", sample); + assert!( + std::path::Path::new(&sample).is_file(), + "missing {}", + sample + ); emu.load_code(&sample); // Keep the cost profile comparable to `-vv`. diff --git a/maps/maps_linux/libc.so.6 b/maps/maps_linux/libc.so.6 new file mode 100755 index 00000000..283b9188 Binary files /dev/null and b/maps/maps_linux/libc.so.6 differ diff --git a/maps/maps_linux/libc_stub.c b/maps/maps_linux/libc_stub.c new file mode 100644 index 00000000..b0ca3f03 --- /dev/null +++ b/maps/maps_linux/libc_stub.c @@ -0,0 +1,77 @@ +int __libc_start_main( + int (*main_fn)(int, char **, char **), + int argc, + char **argv, + void (*init)(void), + void (*fini)(void), + void (*rtld_fini)(void), + void *stack_end +) { + (void)main_fn; + (void)argc; + (void)argv; + (void)init; + (void)fini; + (void)rtld_fini; + (void)stack_end; + return 0; +} + +int puts(const char *s) { + (void)s; + return 0; +} + +int printf(const char *fmt, ...) { + (void)fmt; + return 0; +} + +int __cxa_finalize(void *dso_handle) { + (void)dso_handle; + return 0; +} + +int __cxa_atexit(void (*func)(void *), void *arg, void *dso_handle) { + (void)func; + (void)arg; + (void)dso_handle; + return 0; +} + +void *__gmon_start__(void) { + return 0; +} + +void exit(int status) { + (void)status; + for (;;) { + } +} + +void _exit(int status) { + (void)status; + for (;;) { + } +} + +void *malloc(unsigned long size) { + (void)size; + return 0; +} + +void free(void *ptr) { + (void)ptr; +} + +void *memcpy(void *dst, const void *src, unsigned long len) { + (void)src; + (void)len; + return dst; +} + +void *memset(void *dst, int value, unsigned long len) { + (void)value; + (void)len; + return dst; +}