mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 01:25:20 +02:00
@@ -21,4 +21,3 @@ cc = { version = "1.0", features = ["parallel"] }
|
||||
[profile.release]
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
debug = 1
|
||||
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
RUSTFLAGS='-C target-cpu=x86-64-v3' cargo build
|
||||
+6
-2
@@ -134,9 +134,13 @@ impl Device {
|
||||
instrs: [cop0::reserved; 64],
|
||||
special_instrs: [cop0::reserved; 64],
|
||||
regimm_instrs: [cop0::reserved; 32],
|
||||
events: vec![],
|
||||
events: [events::Event {
|
||||
enabled: false,
|
||||
count: u64::MAX,
|
||||
handler: events::dummy_event,
|
||||
}; events::EventType::EventTypeCount as usize],
|
||||
next_event_count: u64::MAX,
|
||||
next_event: None,
|
||||
next_event: 0,
|
||||
},
|
||||
pif: pif::Pif {
|
||||
rom: [0; 1984],
|
||||
|
||||
+3
-3
@@ -202,7 +202,7 @@ pub fn set_control_registers(device: &mut device::Device, index: u32, mut data:
|
||||
event_time += !0 as u32 as u64
|
||||
}
|
||||
let compare_event: &mut device::events::Event =
|
||||
device::events::get_event(device, device::events::EventType::COMPARE).unwrap();
|
||||
device::events::get_event(device, device::events::EventType::Compare).unwrap();
|
||||
compare_event.count = event_time; // reschedule the next compare interrupt event
|
||||
device::events::set_next_event(device);
|
||||
device.cpu.cop0.regs[COP0_CAUSE_REG as usize] &= !COP0_CAUSE_IP7;
|
||||
@@ -228,7 +228,7 @@ pub fn compare_event(device: &mut device::Device) {
|
||||
|
||||
device::events::create_event(
|
||||
device,
|
||||
device::events::EventType::COMPARE,
|
||||
device::events::EventType::Compare,
|
||||
device.cpu.next_event_count + (!0 as u32 as u64),
|
||||
compare_event,
|
||||
);
|
||||
@@ -364,7 +364,7 @@ pub fn init(device: &mut device::Device) {
|
||||
|
||||
device::events::create_event(
|
||||
device,
|
||||
device::events::EventType::COMPARE,
|
||||
device::events::EventType::Compare,
|
||||
!0 as u32 as u64,
|
||||
compare_event,
|
||||
)
|
||||
|
||||
+2
-2
@@ -30,9 +30,9 @@ pub struct Cpu {
|
||||
pub instrs: [fn(&mut device::Device, u32); 64],
|
||||
pub special_instrs: [fn(&mut device::Device, u32); 64],
|
||||
pub regimm_instrs: [fn(&mut device::Device, u32); 32],
|
||||
pub events: Vec<device::events::Event>,
|
||||
pub events: [device::events::Event; device::events::EventType::EventTypeCount as usize],
|
||||
pub next_event_count: u64,
|
||||
pub next_event: Option<device::events::Event>,
|
||||
pub next_event: usize,
|
||||
}
|
||||
|
||||
pub fn decode_opcode(device: &mut device::Device, opcode: u32) -> fn(&mut device::Device, u32) {
|
||||
|
||||
+18
-30
@@ -9,12 +9,13 @@ pub enum EventType {
|
||||
DP,
|
||||
SP,
|
||||
SPDma,
|
||||
COMPARE,
|
||||
Compare,
|
||||
EventTypeCount,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub struct Event {
|
||||
pub name: EventType,
|
||||
pub enabled: bool,
|
||||
pub count: u64,
|
||||
pub handler: fn(&mut device::Device),
|
||||
}
|
||||
@@ -25,57 +26,40 @@ pub fn create_event(
|
||||
when: u64,
|
||||
handler: fn(&mut device::Device),
|
||||
) {
|
||||
let event = Event {
|
||||
name: name,
|
||||
device.cpu.events[name as usize] = Event {
|
||||
enabled: true,
|
||||
count: when,
|
||||
handler: handler,
|
||||
};
|
||||
if get_event(device, name) != None {
|
||||
panic! {"duplicate event {}", name as usize}
|
||||
}
|
||||
device.cpu.events.push(event);
|
||||
set_next_event(device);
|
||||
}
|
||||
|
||||
pub fn get_event(device: &mut device::Device, name: EventType) -> Option<&mut Event> {
|
||||
for i in device.cpu.events.iter_mut() {
|
||||
if i.name == name {
|
||||
return Some(i);
|
||||
}
|
||||
if device.cpu.events[name as usize].enabled {
|
||||
return Some(&mut device.cpu.events[name as usize]);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
|
||||
pub fn remove_event(device: &mut device::Device, name: EventType) {
|
||||
let mut remove_index: usize = 0;
|
||||
let mut found = false;
|
||||
for (pos, i) in device.cpu.events.iter_mut().enumerate() {
|
||||
if i.name == name {
|
||||
found = true;
|
||||
remove_index = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if found {
|
||||
device.cpu.events.remove(remove_index);
|
||||
}
|
||||
device.cpu.events[name as usize].enabled = false;
|
||||
}
|
||||
|
||||
pub fn trigger_event(device: &mut device::Device) {
|
||||
let next_event_name = device.cpu.next_event.unwrap().name;
|
||||
remove_event(device, next_event_name);
|
||||
let next_event_name = device.cpu.next_event;
|
||||
device.cpu.events[next_event_name].enabled = false;
|
||||
|
||||
let handler = device.cpu.next_event.unwrap().handler;
|
||||
let handler = device.cpu.events[next_event_name].handler;
|
||||
handler(device);
|
||||
set_next_event(device);
|
||||
}
|
||||
|
||||
pub fn set_next_event(device: &mut device::Device) {
|
||||
device.cpu.next_event_count = u64::MAX;
|
||||
for i in device.cpu.events.iter() {
|
||||
if i.count < device.cpu.next_event_count {
|
||||
for (pos, i) in device.cpu.events.iter().enumerate() {
|
||||
if i.enabled && i.count < device.cpu.next_event_count {
|
||||
device.cpu.next_event_count = i.count;
|
||||
device.cpu.next_event = Some(*i);
|
||||
device.cpu.next_event = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,3 +70,7 @@ pub fn translate_events(device: &mut device::Device, old_count: u64, new_count:
|
||||
}
|
||||
set_next_event(device);
|
||||
}
|
||||
|
||||
pub fn dummy_event(_device: &mut device::Device) {
|
||||
panic!("dummy event")
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ pub fn in_delay_slot_taken(device: &mut device::Device) -> bool {
|
||||
pub fn run(device: &mut device::Device) -> u64 {
|
||||
device.rsp.cpu.broken = false;
|
||||
let mut cycle_counter = 0;
|
||||
while !device.rsp.cpu.halted && !device.rsp.cpu.sync_point {
|
||||
while !device.rsp.cpu.sync_point {
|
||||
device.rsp.cpu.instruction_type = InstructionType::Su;
|
||||
device.rsp.cpu.gpr[0] = 0; // gpr 0 is read only
|
||||
let offset = 0x1000 + device.rsp.regs2[device::rsp_interface::SP_PC_REG as usize] as usize;
|
||||
@@ -66,7 +66,10 @@ pub fn run(device: &mut device::Device) -> u64 {
|
||||
execute_opcode(device, opcode)(device, opcode);
|
||||
match device.rsp.cpu.branch_state.state {
|
||||
device::cpu::State::Step => {
|
||||
device.rsp.regs2[device::rsp_interface::SP_PC_REG as usize] += 4
|
||||
device.rsp.regs2[device::rsp_interface::SP_PC_REG as usize] += 4;
|
||||
if device.rsp.cpu.broken {
|
||||
break;
|
||||
}
|
||||
}
|
||||
device::cpu::State::Take => {
|
||||
device.rsp.regs2[device::rsp_interface::SP_PC_REG as usize] += 4;
|
||||
@@ -107,10 +110,6 @@ pub fn run(device: &mut device::Device) -> u64 {
|
||||
device.rsp.cpu.pipeline_full = true;
|
||||
}
|
||||
}
|
||||
|
||||
if device.rsp.cpu.broken && device.rsp.cpu.branch_state.state == device::cpu::State::Step {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (cycle_counter as f64 * 1.5) as u64; // converting RCP clock to CPU clock
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user