This repository has been archived on 2026-08-27. You can view files and clone it, but cannot push or open issues or pull requests.
gopher64-netplay/src/device/fpu_instructions.rs
Logan McNaughton 2e4a23c315 Initial Commit
2023-10-04 14:33:17 -06:00

701 lines
26 KiB
Rust

use crate::device;
pub fn fs(opcode: u32) -> u32 {
return (opcode >> 11) & 0x1F;
}
pub fn ft(opcode: u32) -> u32 {
return (opcode >> 16) & 0x1F;
}
pub fn fd(opcode: u32) -> u32 {
return (opcode >> 6) & 0x1F;
}
pub fn bc1f(device: &mut device::Device, opcode: u32) {
if device.cpu.cop1.fcr31 & device::cop1::FCR31_CMP_BIT == 0 {
device::cpu_instructions::check_relative_idle_loop(device, opcode);
device.cpu.branch_state.state = device::cpu::State::Take;
device.cpu.branch_state.pc = device.cpu.pc.wrapping_add(device::cpu_instructions::se16(
device::cpu_instructions::imm(opcode << 2) as i16,
)) + 4;
} else {
device.cpu.branch_state.state = device::cpu::State::NotTaken;
}
}
pub fn bc1t(device: &mut device::Device, opcode: u32) {
if device.cpu.cop1.fcr31 & device::cop1::FCR31_CMP_BIT != 0 {
device::cpu_instructions::check_relative_idle_loop(device, opcode);
device.cpu.branch_state.state = device::cpu::State::Take;
device.cpu.branch_state.pc = device.cpu.pc.wrapping_add(device::cpu_instructions::se16(
device::cpu_instructions::imm(opcode << 2) as i16,
)) + 4;
} else {
device.cpu.branch_state.state = device::cpu::State::NotTaken;
}
}
pub fn bc1fl(device: &mut device::Device, opcode: u32) {
if device.cpu.cop1.fcr31 & device::cop1::FCR31_CMP_BIT == 0 {
device::cpu_instructions::check_relative_idle_loop(device, opcode);
device.cpu.branch_state.state = device::cpu::State::Take;
device.cpu.branch_state.pc = device.cpu.pc.wrapping_add(device::cpu_instructions::se16(
device::cpu_instructions::imm(opcode << 2) as i16,
)) + 4;
} else {
device.cpu.branch_state.state = device::cpu::State::Discard;
}
}
pub fn bc1tl(device: &mut device::Device, opcode: u32) {
if device.cpu.cop1.fcr31 & device::cop1::FCR31_CMP_BIT != 0 {
device::cpu_instructions::check_relative_idle_loop(device, opcode);
device.cpu.branch_state.state = device::cpu::State::Take;
device.cpu.branch_state.pc = device.cpu.pc.wrapping_add(device::cpu_instructions::se16(
device::cpu_instructions::imm(opcode << 2) as i16,
)) + 4;
} else {
device.cpu.branch_state.state = device::cpu::State::Discard;
}
}
pub fn add_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs + ft, true);
device::cop0::add_cycles(device, 2)
}
pub fn sub_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs - ft, true);
device::cop0::add_cycles(device, 2)
}
pub fn mul_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs * ft, true);
device::cop0::add_cycles(device, 4)
}
pub fn div_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs / ft, true);
device::cop0::add_cycles(device, 28)
}
pub fn sqrt_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs.sqrt(), true);
device::cop0::add_cycles(device, 28)
}
pub fn abs_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs.abs(), true);
device::cop0::add_cycles(device, 2)
}
pub fn mov_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs);
}
pub fn neg_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, -fs, true);
}
pub fn round_l_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.round_ties_even() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn trunc_l_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.trunc() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn ceil_l_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.ceil() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn floor_l_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.floor() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn round_w_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.round_ties_even() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn trunc_w_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.trunc() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn ceil_w_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.ceil() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn floor_w_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.floor() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_d_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs as f64);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_w_s(device: &mut device::Device, opcode: u32) {
match device.cpu.cop1.fcr31 & 3 {
0 => round_w_s(device, opcode),
1 => trunc_w_s(device, opcode),
2 => ceil_w_s(device, opcode),
3 => floor_w_s(device, opcode),
_ => panic!("unknown cvt_w_s"),
}
}
pub fn cvt_l_s(device: &mut device::Device, opcode: u32) {
match device.cpu.cop1.fcr31 & 3 {
0 => round_l_s(device, opcode),
1 => trunc_l_s(device, opcode),
2 => ceil_l_s(device, opcode),
3 => floor_l_s(device, opcode),
_ => panic!("unknown cvt_l_s"),
}
}
pub fn c_f_s(device: &mut device::Device, _opcode: u32) {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT
}
pub fn c_un_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_eq_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
return;
}
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ueq_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
return;
}
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_olt_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
return;
}
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ult_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
return;
}
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ole_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
return;
}
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ule_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
return;
}
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_sf_s(device: &mut device::Device, _opcode: u32) {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
pub fn c_ngle_s(device: &mut device::Device, _opcode: u32) {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
pub fn c_seq_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ngl_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_lt_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_nge_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_le_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ngt_s(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_single(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_single(device, ft(opcode) as usize);
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn add_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs + ft);
device::cop0::add_cycles(device, 2)
}
pub fn sub_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs - ft);
device::cop0::add_cycles(device, 2)
}
pub fn mul_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs * ft);
device::cop0::add_cycles(device, 7)
}
pub fn div_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs / ft);
device::cop0::add_cycles(device, 57)
}
pub fn sqrt_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs.sqrt());
device::cop0::add_cycles(device, 57)
}
pub fn abs_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs.abs());
device::cop0::add_cycles(device, 2)
}
pub fn mov_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs);
}
pub fn neg_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
device::cop1::set_fpr_double(device, fd(opcode) as usize, -fs);
}
pub fn round_l_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.round_ties_even() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn trunc_l_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.trunc() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn ceil_l_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.ceil() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn floor_l_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f64::from_ne_bytes((fs.floor() as i64).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, value);
device::cop0::add_cycles(device, 4)
}
pub fn round_w_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.round_ties_even() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn trunc_w_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.trunc() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn ceil_w_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.ceil() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn floor_w_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let value = f32::from_ne_bytes((fs.floor() as i32).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, value, true);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_s_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs as f32, true);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_w_d(device: &mut device::Device, opcode: u32) {
match device.cpu.cop1.fcr31 & 3 {
0 => round_w_d(device, opcode),
1 => trunc_w_d(device, opcode),
2 => ceil_w_d(device, opcode),
3 => floor_w_d(device, opcode),
_ => panic!("unknown cvt_w_d"),
}
}
pub fn cvt_l_d(device: &mut device::Device, opcode: u32) {
match device.cpu.cop1.fcr31 & 3 {
0 => round_l_d(device, opcode),
1 => trunc_l_d(device, opcode),
2 => ceil_l_d(device, opcode),
3 => floor_l_d(device, opcode),
_ => panic!("unknown cvt_l_d"),
}
}
pub fn c_f_d(device: &mut device::Device, _opcode: u32) {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
pub fn c_un_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_eq_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
return;
}
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ueq_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
return;
}
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_olt_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
return;
}
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ult_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
return;
}
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ole_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
return;
}
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ule_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs.is_nan() || ft.is_nan() {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
return;
}
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_sf_d(device: &mut device::Device, _opcode: u32) {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
pub fn c_ngle_d(device: &mut device::Device, _opcode: u32) {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
pub fn c_seq_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ngl_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs == ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_lt_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_nge_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs < ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_le_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn c_ngt_d(device: &mut device::Device, opcode: u32) {
let fs = device::cop1::get_fpr_double(device, fs(opcode) as usize);
let ft = device::cop1::get_fpr_double(device, ft(opcode) as usize);
if fs <= ft {
device.cpu.cop1.fcr31 |= device::cop1::FCR31_CMP_BIT;
} else {
device.cpu.cop1.fcr31 &= !device::cop1::FCR31_CMP_BIT;
}
}
pub fn cvt_s_l(device: &mut device::Device, opcode: u32) {
let fs =
i64::from_ne_bytes(device::cop1::get_fpr_double(device, fs(opcode) as usize).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs as f32, true);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_d_l(device: &mut device::Device, opcode: u32) {
let fs =
i64::from_ne_bytes(device::cop1::get_fpr_double(device, fs(opcode) as usize).to_ne_bytes());
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs as f64);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_s_w(device: &mut device::Device, opcode: u32) {
let fs =
i32::from_ne_bytes(device::cop1::get_fpr_single(device, fs(opcode) as usize).to_ne_bytes());
device::cop1::set_fpr_single(device, fd(opcode) as usize, fs as f32, true);
device::cop0::add_cycles(device, 4)
}
pub fn cvt_d_w(device: &mut device::Device, opcode: u32) {
let fs = i32::from_ne_bytes(
device::cop1::get_fpr_double(device, fs(opcode) as usize).to_ne_bytes()[0..4]
.try_into()
.unwrap(),
);
device::cop1::set_fpr_double(device, fd(opcode) as usize, fs as f64);
device::cop0::add_cycles(device, 4)
}