mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-21 19:30:52 +00:00
Refactored mc68681 to make a common port struct and fixed a bug in DIV
This commit is contained in:
parent
f0637e81f1
commit
fbb5153121
Binary file not shown.
@ -261,8 +261,11 @@ impl MC68010 {
|
||||
let value = self.get_target_value(system, src, size)?;
|
||||
let existing = self.get_target_value(system, dest, Size::Long)?;
|
||||
let result = match sign {
|
||||
Sign::Signed => ((existing as i16 % value as i16) as u32) << 16 | (0xFFFF & (existing as i16 / value as i16) as u32),
|
||||
Sign::Unsigned => ((existing as u16 % value as u16) as u32) << 16 | (0xFFFF & (existing as u16 / value as u16) as u32),
|
||||
Sign::Signed => {
|
||||
let value = sign_extend_to_long(value, size) as u32;
|
||||
((existing % value) << 16) | (0xFFFF & (existing / value))
|
||||
},
|
||||
Sign::Unsigned => ((existing % value) << 16) | (0xFFFF & (existing / value)),
|
||||
};
|
||||
self.set_target_value(system, dest, result, Size::Long)?;
|
||||
},
|
||||
|
39
src/main.rs
39
src/main.rs
@ -34,7 +34,8 @@ fn main() {
|
||||
system.add_addressable_device(0x00600000, wrap_addressable(ata)).unwrap();
|
||||
|
||||
let mut serial = MC68681::new();
|
||||
serial.open().unwrap();
|
||||
launch_terminal_emulator(serial.port_a.open().unwrap());
|
||||
launch_slip_connection(serial.port_b.open().unwrap());
|
||||
system.add_addressable_device(0x00700000, wrap_addressable(serial)).unwrap();
|
||||
|
||||
|
||||
@ -44,6 +45,7 @@ fn main() {
|
||||
//cpu.add_breakpoint(0x10781a);
|
||||
//cpu.add_breakpoint(0x10bc9c);
|
||||
//cpu.add_breakpoint(0x106a94);
|
||||
//cpu.add_breakpoint(0x10d0c6);
|
||||
|
||||
system.add_interruptable_device(wrap_interruptable(cpu)).unwrap();
|
||||
loop {
|
||||
@ -72,3 +74,38 @@ fn main() {
|
||||
*/
|
||||
}
|
||||
|
||||
pub fn launch_terminal_emulator(name: String) {
|
||||
use nix::unistd::sleep;
|
||||
use std::process::Command;
|
||||
|
||||
Command::new("x-terminal-emulator").arg("-e").arg(&format!("pyserial-miniterm {}", name)).spawn().unwrap();
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
pub fn launch_slip_connection(name: String) {
|
||||
use nix::unistd::sleep;
|
||||
use std::process::Command;
|
||||
|
||||
//Command::new("x-terminal-emulator").arg("-e").arg(&format!("pyserial-miniterm {}", name)).spawn().unwrap();
|
||||
|
||||
Command::new("sudo").args(["slattach", "-s", "38400", "-p", "slip", &name]).spawn().unwrap();
|
||||
Command::new("sudo").args(["ifconfig", "sl0", "192.168.1.2", "pointopoint", "192.168.1.200", "up"]).status().unwrap();
|
||||
Command::new("sudo").args(["arp", "-Ds", "192.168.1.200", "enp4s0", "pub"]).status().unwrap();
|
||||
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-i", "sl0", "-j", "ACCEPT"]).status().unwrap();
|
||||
Command::new("sudo").args(["iptables", "-A", "FORWARD", "-o", "sl0", "-j", "ACCEPT"]).status().unwrap();
|
||||
Command::new("sudo").args(["sh", "-c", "echo 1 > /proc/sys/net/ipv4/ip_forward"]).status().unwrap();
|
||||
/*
|
||||
*/
|
||||
/*
|
||||
sudo slattach -s 38400 -p slip /dev/ttyUSB1
|
||||
sudo ifconfig sl0 192.168.1.2 pointopoint 192.168.1.200 up
|
||||
// (this is automatically added on my machine) >> sudo route add -host 192.168.1.200 sl0
|
||||
sudo arp -Ds 192.168.1.200 enp3s0 pub
|
||||
sudo iptables -A FORWARD -i sl0 -j ACCEPT
|
||||
sudo iptables -A FORWARD -o sl0 -j ACCEPT
|
||||
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
|
||||
*/
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
|
||||
use std::process::Command;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
use nix::fcntl::OFlag;
|
||||
use nix::unistd::sleep;
|
||||
use nix::pty::{self, PtyMaster};
|
||||
use nix::fcntl::{fcntl, FcntlArg};
|
||||
|
||||
@ -21,12 +19,12 @@ const REG_CRA_WR: Address = 0x05;
|
||||
const REG_TBA_WR: Address = 0x07;
|
||||
const REG_RBA_RD: Address = 0x07;
|
||||
|
||||
const REG_MR1B_MR2B: Address = 0x700011;
|
||||
const REG_SRB_RD: Address = 0x700013;
|
||||
const REG_CSRB_WR: Address = 0x700013;
|
||||
const REG_CRB_WR: Address = 0x700015;
|
||||
const REG_TBB_WR: Address = 0x700017;
|
||||
const REG_RBB_RD: Address = 0x700017;
|
||||
const REG_MR1B_MR2B: Address = 0x11;
|
||||
const REG_SRB_RD: Address = 0x13;
|
||||
const REG_CSRB_WR: Address = 0x13;
|
||||
const REG_CRB_WR: Address = 0x15;
|
||||
const REG_TBB_WR: Address = 0x17;
|
||||
const REG_RBB_RD: Address = 0x17;
|
||||
|
||||
const REG_ACR_WR: Address = 0x09;
|
||||
|
||||
@ -70,21 +68,95 @@ const ISR_CH_A_TX_READY: u8 = 0x01;
|
||||
|
||||
const DEV_NAME: &'static str = "mc68681";
|
||||
|
||||
pub struct MC68681 {
|
||||
pub struct MC68681Port {
|
||||
pub tty: Option<PtyMaster>,
|
||||
pub status: u8,
|
||||
pub input: u8,
|
||||
pub tx_enabled: bool,
|
||||
pub rx_enabled: bool,
|
||||
}
|
||||
|
||||
impl MC68681Port {
|
||||
pub fn new() -> MC68681Port {
|
||||
MC68681Port {
|
||||
tty: None,
|
||||
status: 0,
|
||||
input: 0,
|
||||
tx_enabled: false,
|
||||
rx_enabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&mut self) -> Result<String, Error> {
|
||||
let master = pty::posix_openpt(OFlag::O_RDWR).and_then(|master| {
|
||||
pty::grantpt(&master)?;
|
||||
pty::unlockpt(&master)?;
|
||||
fcntl(master.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK))?;
|
||||
Ok(master)
|
||||
}).map_err(|_| Error::new("Error opening new pseudoterminal"))?;
|
||||
|
||||
let name = unsafe { pty::ptsname(&master).map_err(|_| Error::new("Unable to get pty name"))? };
|
||||
println!("{}: opening pts {}", DEV_NAME, name);
|
||||
self.tty = Some(master);
|
||||
Ok(name)
|
||||
}
|
||||
|
||||
pub fn rx_ready(&self) -> bool {
|
||||
(self.status & SR_RX_READY) != 0
|
||||
}
|
||||
|
||||
pub fn check_read(&mut self) -> Result<bool, Error> {
|
||||
if self.rx_enabled && !self.rx_ready() && self.tty.is_some() {
|
||||
let mut buf = [0; 1];
|
||||
let tty = self.tty.as_mut().unwrap();
|
||||
match tty.read(&mut buf) {
|
||||
Ok(count) => {
|
||||
println!("READ {:?}", count);
|
||||
self.input = buf[0];
|
||||
self.status |= SR_RX_READY;
|
||||
return Ok(true);
|
||||
},
|
||||
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
|
||||
Err(err) => {
|
||||
println!("ERROR: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn handle_command(&mut self, data: u8) -> Option<bool> {
|
||||
let rx_cmd = data& 0x03;
|
||||
if rx_cmd == 0b01 {
|
||||
self.rx_enabled = true;
|
||||
} else if rx_cmd == 0b10 {
|
||||
self.rx_enabled = false;
|
||||
}
|
||||
|
||||
let tx_cmd = (data & 0x0C) >> 2;
|
||||
if tx_cmd == 0b01 {
|
||||
self.tx_enabled = true;
|
||||
self.status |= SR_TX_READY | SR_TX_EMPTY;
|
||||
return Some(true);
|
||||
} else if tx_cmd == 0b10 {
|
||||
self.tx_enabled = false;
|
||||
self.status &= !(SR_TX_READY | SR_TX_EMPTY);
|
||||
return Some(false);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MC68681 {
|
||||
pub acr: u8,
|
||||
pub status_a: u8,
|
||||
pub input_a: u8,
|
||||
pub tx_a_enabled: bool,
|
||||
pub rx_a_enabled: bool,
|
||||
pub status_b: u8,
|
||||
pub input_b: u8,
|
||||
pub tx_b_enabled: bool,
|
||||
pub rx_b_enabled: bool,
|
||||
pub port_a: MC68681Port,
|
||||
pub port_b: MC68681Port,
|
||||
|
||||
pub int_mask: u8,
|
||||
pub int_status: u8,
|
||||
pub int_vector: u8,
|
||||
pub is_interrupt: bool,
|
||||
|
||||
pub timer_preload: u16,
|
||||
pub timer_count: u16,
|
||||
pub is_timing: bool,
|
||||
@ -93,22 +165,13 @@ pub struct MC68681 {
|
||||
impl MC68681 {
|
||||
pub fn new() -> Self {
|
||||
MC68681 {
|
||||
tty: None,
|
||||
acr: 0,
|
||||
|
||||
status_a: 0,
|
||||
input_a: 0,
|
||||
tx_a_enabled: false,
|
||||
rx_a_enabled: false,
|
||||
status_b: 0,
|
||||
input_b: 0,
|
||||
tx_b_enabled: false,
|
||||
rx_b_enabled: false,
|
||||
port_a: MC68681Port::new(),
|
||||
port_b: MC68681Port::new(),
|
||||
|
||||
int_mask: 0,
|
||||
int_status: 0,
|
||||
int_vector: 0,
|
||||
is_interrupt: false,
|
||||
|
||||
timer_preload: 0,
|
||||
timer_count: 0,
|
||||
@ -116,46 +179,13 @@ impl MC68681 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(&mut self) -> Result<(), Error> {
|
||||
let result = pty::posix_openpt(OFlag::O_RDWR).and_then(|master| {
|
||||
pty::grantpt(&master).and_then(|_| pty::unlockpt(&master)).and_then(|_| Ok(master))
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(master) => {
|
||||
let name = unsafe { pty::ptsname(&master).map_err(|_| Error::new("Unable to get pty name"))? };
|
||||
println!("Open {}", name);
|
||||
fcntl(master.as_raw_fd(), FcntlArg::F_SETFL(OFlag::O_NONBLOCK)).unwrap();
|
||||
self.tty = Some(master);
|
||||
|
||||
Command::new("x-terminal-emulator").arg("-e").arg(&format!("pyserial-miniterm {}", name)).spawn().unwrap();
|
||||
sleep(1);
|
||||
Ok(())
|
||||
},
|
||||
Err(_) => Err(Error::new("Error opening new pseudoterminal")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rx_ready(&self) -> bool {
|
||||
(self.status_a & SR_RX_READY) != 0
|
||||
}
|
||||
|
||||
pub fn step_internal(&mut self, system: &System) -> Result<(), Error> {
|
||||
if self.rx_a_enabled && !self.rx_ready() && self.tty.is_some() {
|
||||
let mut buf = [0; 1];
|
||||
let tty = self.tty.as_mut().unwrap();
|
||||
match tty.read(&mut buf) {
|
||||
Ok(count) => {
|
||||
println!("READ {:?}", count);
|
||||
self.input_a = buf[0];
|
||||
self.status_a |= SR_RX_READY;
|
||||
self.int_status |= ISR_CH_A_RX_READY_FULL;
|
||||
},
|
||||
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { },
|
||||
Err(err) => {
|
||||
println!("ERROR: {:?}", err);
|
||||
}
|
||||
}
|
||||
if self.port_a.check_read()? {
|
||||
self.int_status |= ISR_CH_A_RX_READY_FULL;
|
||||
}
|
||||
|
||||
if self.port_b.check_read()? {
|
||||
self.int_status |= ISR_CH_B_RX_READY_FULL;
|
||||
}
|
||||
|
||||
if self.is_timing {
|
||||
@ -176,6 +206,10 @@ impl MC68681 {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_interrupt_flag(&mut self, flag: u8, value: bool) {
|
||||
self.int_status = (self.int_status & !flag) | (if value { flag } else { 0 });
|
||||
}
|
||||
|
||||
fn check_interrupt_state(&mut self, system: &System) -> Result<(), Error> {
|
||||
system.get_interrupt_controller().set((self.int_status & self.int_mask) != 0, 4, self.int_vector)
|
||||
}
|
||||
@ -195,19 +229,19 @@ impl Addressable for MC68681 {
|
||||
|
||||
match addr {
|
||||
REG_SRA_RD => {
|
||||
data[0] = self.status_a
|
||||
data[0] = self.port_a.status
|
||||
},
|
||||
REG_RBA_RD => {
|
||||
data[0] = self.input_a;
|
||||
self.status_a &= !SR_RX_READY;
|
||||
data[0] = self.port_a.input;
|
||||
self.port_a.status &= !SR_RX_READY;
|
||||
self.int_status &= !ISR_CH_A_RX_READY_FULL;
|
||||
},
|
||||
REG_SRB_RD => {
|
||||
data[0] = self.status_b
|
||||
data[0] = self.port_b.status
|
||||
},
|
||||
REG_RBB_RD => {
|
||||
data[0] = self.input_b;
|
||||
self.status_b &= !SR_RX_READY;
|
||||
data[0] = self.port_b.input;
|
||||
self.port_b.status &= !SR_RX_READY;
|
||||
self.int_status &= !ISR_CH_B_RX_READY_FULL;
|
||||
},
|
||||
REG_ISR_RD => {
|
||||
@ -245,47 +279,22 @@ impl Addressable for MC68681 {
|
||||
}
|
||||
REG_TBA_WR => {
|
||||
println!("{}a: write {}", DEV_NAME, data[0] as char);
|
||||
self.tty.as_mut().map(|tty| tty.write_all(&[data[0]]));
|
||||
self.port_a.tty.as_mut().map(|tty| tty.write_all(&[data[0]]));
|
||||
},
|
||||
REG_CRA_WR => {
|
||||
let rx_cmd = (data[0] & 0x03);
|
||||
if rx_cmd == 0b01 {
|
||||
self.rx_a_enabled = true;
|
||||
} else if rx_cmd == 0b10 {
|
||||
self.rx_a_enabled = false;
|
||||
}
|
||||
|
||||
let tx_cmd = ((data[0] & 0x0C) >> 2);
|
||||
if tx_cmd == 0b01 {
|
||||
self.tx_a_enabled = true;
|
||||
self.status_a |= SR_TX_READY | SR_TX_EMPTY;
|
||||
self.int_status |= ISR_CH_A_TX_READY;
|
||||
} else if tx_cmd == 0b10 {
|
||||
self.tx_a_enabled = false;
|
||||
self.status_a &= !(SR_TX_READY | SR_TX_EMPTY);
|
||||
self.int_status &= !ISR_CH_A_TX_READY;
|
||||
match self.port_a.handle_command(data[0]) {
|
||||
Some(value) => self.set_interrupt_flag(ISR_CH_A_TX_READY, value),
|
||||
None => { },
|
||||
}
|
||||
},
|
||||
REG_TBB_WR => {
|
||||
println!("{}b: write {:x}", DEV_NAME, data[0]);
|
||||
self.port_b.tty.as_mut().map(|tty| tty.write_all(&[data[0]]));
|
||||
},
|
||||
REG_CRB_WR => {
|
||||
let rx_cmd = (data[0] & 0x03);
|
||||
if rx_cmd == 0b01 {
|
||||
self.rx_b_enabled = true;
|
||||
} else if rx_cmd == 0b10 {
|
||||
self.rx_b_enabled = false;
|
||||
}
|
||||
|
||||
let tx_cmd = ((data[0] & 0x0C) >> 2);
|
||||
if tx_cmd == 0b01 {
|
||||
self.tx_b_enabled = true;
|
||||
self.status_b |= SR_TX_READY | SR_TX_EMPTY;
|
||||
self.int_status |= ISR_CH_B_TX_READY;
|
||||
} else if tx_cmd == 0b10 {
|
||||
self.tx_b_enabled = false;
|
||||
self.status_b &= !(SR_TX_READY | SR_TX_EMPTY);
|
||||
self.int_status &= !ISR_CH_B_TX_READY;
|
||||
match self.port_b.handle_command(data[0]) {
|
||||
Some(value) => self.set_interrupt_flag(ISR_CH_B_TX_READY, value),
|
||||
None => { },
|
||||
}
|
||||
},
|
||||
REG_CTUR_WR => {
|
||||
|
@ -1,11 +1,10 @@
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::interrupts::InterruptController;
|
||||
use crate::memory::{Address, Addressable, Bus};
|
||||
use crate::devices::{Device, Steppable, AddressableDeviceBox, InterruptableDeviceBox, Clock};
|
||||
use crate::memory::{Address, Bus};
|
||||
use crate::devices::{Device, AddressableDeviceBox, InterruptableDeviceBox, Clock};
|
||||
|
||||
|
||||
pub struct System {
|
||||
@ -42,7 +41,7 @@ impl System {
|
||||
}
|
||||
|
||||
pub fn add_interruptable_device(&mut self, device: InterruptableDeviceBox) -> Result<(), Error> {
|
||||
self.interrupt_controller.borrow_mut().set_target(device.clone());
|
||||
self.interrupt_controller.borrow_mut().set_target(device.clone())?;
|
||||
self.devices.push(Device::Interruptable(device));
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user