mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 01:25:20 +02:00
@@ -43,6 +43,7 @@ pub const COP0_STATUS_CU1: u64 = 1 << 29;
|
||||
pub const COP0_STATUS_CU2: u64 = 1 << 30;
|
||||
|
||||
//pub const COP0_CAUSE_EXCCODE_INTR: u64 = 0 << 2;
|
||||
pub const COP0_CAUSE_EXCCODE_MOD: u64 = 1 << 2;
|
||||
pub const COP0_CAUSE_EXCCODE_TLBL: u64 = 2 << 2;
|
||||
pub const COP0_CAUSE_EXCCODE_TLBS: u64 = 3 << 2;
|
||||
//pub const COP0_CAUSE_EXCCODE_ADEL: u64 = 4 << 2;
|
||||
|
||||
@@ -246,11 +246,12 @@ pub fn ldl(device: &mut device::Device, opcode: u32) {
|
||||
let shift = 8 * n;
|
||||
let mask = bits_below_mask(8 * n);
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !7, device::memory::AccessType::Read);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Read);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !7;
|
||||
|
||||
let mut w = [0; 2];
|
||||
w[0] = device::memory::data_read(
|
||||
@@ -280,11 +281,12 @@ pub fn ldr(device: &mut device::Device, opcode: u32) {
|
||||
mask = bits_above_mask(8 * (n + 1))
|
||||
}
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !7, device::memory::AccessType::Read);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Read);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !7;
|
||||
|
||||
let mut w = [0; 2];
|
||||
w[0] = device::memory::data_read(
|
||||
@@ -349,11 +351,12 @@ pub fn lwl(device: &mut device::Device, opcode: u32) {
|
||||
let shift = 8 * n;
|
||||
let mask = bits_below_mask(8 * n) as u32;
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !3, device::memory::AccessType::Read);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Read);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !3;
|
||||
|
||||
device.cpu.gpr[rt(opcode) as usize] = se32(
|
||||
((device.cpu.gpr[rt(opcode) as usize] as u32) & mask
|
||||
@@ -433,11 +436,12 @@ pub fn lwr(device: &mut device::Device, opcode: u32) {
|
||||
mask = bits_above_mask(8 * (n + 1))
|
||||
}
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !3, device::memory::AccessType::Read);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Read);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !3;
|
||||
|
||||
device.cpu.gpr[rt(opcode) as usize] = se32(
|
||||
((device.cpu.gpr[rt(opcode) as usize] as u32) & (mask as u32)
|
||||
@@ -522,11 +526,13 @@ pub fn swl(device: &mut device::Device, opcode: u32) {
|
||||
mask = bits_below_mask(8 * (4 - n)) as u32
|
||||
}
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !3, device::memory::AccessType::Write);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Write);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !3;
|
||||
|
||||
device::memory::data_write(
|
||||
device,
|
||||
phys_address,
|
||||
@@ -567,11 +573,12 @@ pub fn sdl(device: &mut device::Device, opcode: u32) {
|
||||
mask = bits_below_mask(8 * (8 - n))
|
||||
}
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !7, device::memory::AccessType::Write);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Write);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !7;
|
||||
|
||||
let value = device.cpu.gpr[rt(opcode) as usize] >> shift;
|
||||
device::memory::data_write(
|
||||
@@ -591,11 +598,12 @@ pub fn sdr(device: &mut device::Device, opcode: u32) {
|
||||
|
||||
let mask = bits_above_mask(8 * (7 - n));
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !7, device::memory::AccessType::Write);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Write);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !7;
|
||||
|
||||
let value = device.cpu.gpr[rt(opcode) as usize] << shift;
|
||||
device::memory::data_write(
|
||||
@@ -615,11 +623,13 @@ pub fn swr(device: &mut device::Device, opcode: u32) {
|
||||
|
||||
let mask = bits_above_mask(8 * (3 - n)) as u32;
|
||||
|
||||
let (phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr & !3, device::memory::AccessType::Write);
|
||||
let (mut phys_address, cached, err) =
|
||||
device::memory::translate_address(device, addr, device::memory::AccessType::Write);
|
||||
if err {
|
||||
return;
|
||||
}
|
||||
phys_address &= !3;
|
||||
|
||||
device::memory::data_write(
|
||||
device,
|
||||
phys_address,
|
||||
|
||||
+39
-11
@@ -20,49 +20,49 @@ pub fn check_pending_interrupts(device: &mut device::Device) {
|
||||
return;
|
||||
}
|
||||
|
||||
exception_general(device);
|
||||
exception_general(device, 0x180);
|
||||
}
|
||||
|
||||
pub fn floating_point_exception(device: &mut device::Device) {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_FPE;
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, 0x180)
|
||||
}
|
||||
|
||||
pub fn trap_exception(device: &mut device::Device) {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_TR;
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, 0x180)
|
||||
}
|
||||
|
||||
pub fn syscall_exception(device: &mut device::Device) {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_SYS;
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, 0x180)
|
||||
}
|
||||
|
||||
pub fn break_exception(device: &mut device::Device) {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_BP;
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, 0x180)
|
||||
}
|
||||
|
||||
pub fn reserved_exception(device: &mut device::Device, cop: u64) {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_RI | cop;
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, 0x180)
|
||||
}
|
||||
|
||||
pub fn cop_unusable_exception(device: &mut device::Device, cop: u64) {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_CPU | cop;
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, 0x180)
|
||||
}
|
||||
|
||||
pub fn tlb_miss_exception(
|
||||
@@ -94,17 +94,46 @@ pub fn tlb_miss_exception(
|
||||
address >> 31,
|
||||
device::cop0::COP0_XCONTEXT_REGION_MASK,
|
||||
);
|
||||
device::memory::masked_write_64(
|
||||
&mut device.cpu.cop0.regs[device::cop0::COP0_ENTRYHI_REG as usize],
|
||||
address,
|
||||
0xFFFFE000,
|
||||
);
|
||||
|
||||
let mut vector_offset = 0x180;
|
||||
let mut valid = true;
|
||||
for i in device.cpu.cop0.tlb_entries {
|
||||
if address & !3 >= i.start_even && address & !3 <= i.end_even {
|
||||
valid = i.v_even != 0;
|
||||
if valid && access_type == device::memory::AccessType::Write && i.d_even == 0 {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_MOD;
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if address & !3 >= i.start_odd && address & !3 <= i.start_odd {
|
||||
valid = i.v_odd != 0;
|
||||
if valid && access_type == device::memory::AccessType::Write && i.d_odd == 0 {
|
||||
device.cpu.cop0.regs[device::cop0::COP0_CAUSE_REG as usize] =
|
||||
device::cop0::COP0_CAUSE_EXCCODE_MOD;
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if device.cpu.cop0.regs[device::cop0::COP0_STATUS_REG as usize] & device::cop0::COP0_STATUS_EXL
|
||||
== 0
|
||||
&& valid
|
||||
{
|
||||
device.cpu.pc -= 0x180
|
||||
vector_offset = 0;
|
||||
}
|
||||
|
||||
exception_general(device)
|
||||
exception_general(device, vector_offset)
|
||||
}
|
||||
|
||||
pub fn exception_general(device: &mut device::Device) {
|
||||
pub fn exception_general(device: &mut device::Device, vector_offset: u32) {
|
||||
if device.cpu.cop0.regs[device::cop0::COP0_STATUS_REG as usize] & device::cop0::COP0_STATUS_EXL
|
||||
== 0
|
||||
{
|
||||
@@ -121,7 +150,6 @@ pub fn exception_general(device: &mut device::Device) {
|
||||
|
||||
device.cpu.cop0.regs[device::cop0::COP0_STATUS_REG as usize] |= device::cop0::COP0_STATUS_EXL;
|
||||
|
||||
let vector_offset: u32 = 0x180;
|
||||
if device.cpu.cop0.regs[device::cop0::COP0_STATUS_REG as usize] & device::cop0::COP0_STATUS_BEV
|
||||
== 0
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user