Fixed all clippy warnings

This commit is contained in:
transistor 2023-03-05 20:19:49 -08:00
parent 0ac3f48b64
commit 7bdd63bc76
50 changed files with 377 additions and 566 deletions

1
.clippy.toml Normal file
View File

@ -0,0 +1 @@
msrv = "1.60.0"

View File

@ -6,6 +6,7 @@ use crate::system::System;
use crate::devices::{Address, Addressable, Debuggable, TransmutableBox};
#[derive(Default)]
pub struct Debugger {
last_command: Option<String>,
repeat: u32,
@ -14,14 +15,6 @@ pub struct Debugger {
impl Debugger {
pub fn new() -> Self {
Self {
last_command: None,
repeat: 0,
trace_only: false,
}
}
pub fn breakpoint_occurred(&mut self) {
self.trace_only = false;
}
@ -60,7 +53,7 @@ impl Debugger {
}
pub fn run_debugger_command(&mut self, system: &System, debug_obj: &mut dyn Debuggable, args: &[&str]) -> Result<bool, Error> {
if args.len() == 0 {
if args.is_empty() {
// The Default Command
return Ok(true);
}
@ -202,7 +195,7 @@ impl Debugger {
fn check_repeat_arg(&mut self, args: &[&str]) -> Result<(), Error> {
if args.len() > 1 {
self.repeat = u32::from_str_radix(args[1], 10).map_err(|_| Error::new("Unable to parse repeat number"))?;
self.repeat = args[1].parse::<u32>().map_err(|_| Error::new("Unable to parse repeat number"))?;
self.last_command = Some(args[0].to_string());
}
Ok(())

View File

@ -32,6 +32,7 @@ pub trait Interruptable {
}
/// A device that can be addressed to read data from or write data to the device.
#[allow(clippy::len_without_is_empty)]
pub trait Addressable {
fn len(&self) -> usize;
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error>;

View File

@ -1,5 +1,5 @@
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ErrorType {
Assertion,
Emulator,

View File

@ -1,5 +1,5 @@
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControllerDevice {
A,
B,
@ -7,7 +7,7 @@ pub enum ControllerDevice {
D,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControllerEvent {
DpadUp(bool),
DpadDown(bool),

View File

@ -7,7 +7,7 @@ use crate::Error;
pub const MASK_COLOUR: u32 = 0xFFFFFFFF;
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Frame {
pub width: u32,
pub height: u32,
@ -131,7 +131,7 @@ impl FrameQueue {
pub fn new(width: u32, height: u32) -> Self {
Self {
max_size: (width, height),
queue: ClockedQueue::new(),
queue: Default::default(),
}
}

View File

@ -1,5 +1,5 @@
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Key {
A,
B,

View File

@ -106,14 +106,10 @@ impl<T: Copy> HostData<T> {
}
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct ClockedQueue<T>(Arc<Mutex<VecDeque<(Clock, T)>>>);
impl<T: Clone> ClockedQueue<T> {
pub fn new() -> Self {
Self(Arc::new(Mutex::new(VecDeque::new())))
}
pub fn push(&self, clock: Clock, data: T) {
self.0.lock().unwrap().push_back((clock, data));
}

View File

@ -9,15 +9,17 @@ pub struct InterruptController {
highest: u8,
}
impl InterruptController {
pub fn new() -> InterruptController {
impl Default for InterruptController {
fn default() -> InterruptController {
InterruptController {
target: None,
interrupts: vec![(false, 0); 7],
highest: 0,
}
}
}
impl InterruptController {
pub fn set_target(&mut self, dev: TransmutableBox) -> Result<(), Error> {
if self.target.is_some() {
return Err(Error::new("Interruptable device already set, and interrupt controller only supports one receiver"));

View File

@ -2,6 +2,7 @@
use std::fs;
use std::rc::Rc;
use std::cell::RefCell;
use std::fmt::Write;
use crate::info;
use crate::error::Error;
@ -31,9 +32,7 @@ impl MemoryBlock {
pub fn load_at(&mut self, addr: Address, filename: &str) -> Result<(), Error> {
match fs::read(filename) {
Ok(contents) => {
for i in 0..contents.len() {
self.contents[(addr as usize) + i] = contents[i];
}
self.contents[(addr as usize)..(addr as usize) + contents.len()].copy_from_slice(&contents);
Ok(())
},
Err(_) => Err(Error::new(&format!("Error reading contents of {}", filename))),
@ -55,9 +54,7 @@ impl Addressable for MemoryBlock {
}
fn read(&mut self, addr: Address, data: &mut [u8]) -> Result<(), Error> {
for i in 0..data.len() {
data[i] = self.contents[(addr as usize) + i];
}
data.copy_from_slice(&self.contents[(addr as usize)..(addr as usize) + data.len()]);
Ok(())
}
@ -66,9 +63,7 @@ impl Addressable for MemoryBlock {
return Err(Error::breakpoint(&format!("Attempt to write to read-only memory at {:x} with data {:?}", addr, data)));
}
for i in 0..data.len() {
self.contents[(addr as usize) + i] = data[i];
}
self.contents[(addr as usize) .. (addr as usize) + data.len()].copy_from_slice(data);
Ok(())
}
}
@ -160,7 +155,7 @@ pub struct Block {
pub dev: TransmutableBox,
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Bus {
blocks: Vec<Block>,
ignore_unmapped: bool,
@ -169,15 +164,6 @@ pub struct Bus {
}
impl Bus {
pub fn new() -> Bus {
Bus {
ignore_unmapped: false,
blocks: vec!(),
watchers: vec!(),
watcher_modified: false,
}
}
pub fn set_ignore_unmapped(&mut self, ignore_unmapped: bool) {
self.ignore_unmapped = ignore_unmapped;
}
@ -204,7 +190,7 @@ impl Bus {
}
}
}
return Err(Error::new(&format!("No segment found at {:#010x}", addr)));
Err(Error::new(&format!("No segment found at {:#010x}", addr)))
}
pub fn dump_memory(&mut self, mut addr: Address, mut count: Address) {
@ -218,7 +204,7 @@ impl Bus {
println!("{}", line);
return;
}
line += &format!("{:#06x} ", word.unwrap());
write!(line, "{:#06x} ", word.unwrap()).unwrap();
addr += 2;
count -= 2;
}
@ -264,7 +250,7 @@ impl Addressable for Bus {
}
fn write(&mut self, addr: Address, data: &[u8]) -> Result<(), Error> {
if let Some(_) = self.watchers.iter().position(|a| *a == addr) {
if self.watchers.iter().any(|a| *a == addr) {
println!("watch: writing to address {:#06x} with {:?}", addr, data);
self.watcher_modified = true;
}
@ -352,7 +338,7 @@ pub fn dump_slice(data: &[u8], mut count: usize) {
let to = if count < 16 { count / 2 } else { 8 };
for _ in 0..to {
let word = read_beu16(&data[addr..]);
line += &format!("{:#06x} ", word);
write!(line, "{:#06x} ", word).unwrap();
addr += 2;
count -= 2;
}

View File

@ -62,7 +62,7 @@ impl<'input> AssemblyParser<'input> {
let list = self.parse_list_of_words()?;
AssemblyLine::Directive(name, list)
},
word if word.chars().nth(0).map(|ch| is_word(ch)).unwrap_or(false) => {
word if word.chars().next().map(is_word).unwrap_or(false) => {
let next = self.lexer.peek();
if next.is_some() && next.as_ref().unwrap() == ":" {
self.lexer.expect_next()?;
@ -152,7 +152,7 @@ impl<'input> AssemblyParser<'input> {
Ok(AssemblyOperand::Immediate(number))
},
_ => {
if is_digit(token.chars().nth(0).unwrap()) {
if is_digit(token.chars().next().unwrap()) {
let number = parse_any_number(self.lexer.lineno(), &token)?;
Ok(AssemblyOperand::Immediate(number))
} else {
@ -164,12 +164,12 @@ impl<'input> AssemblyParser<'input> {
}
fn parse_any_number(lineno: usize, string: &str) -> Result<usize, Error> {
let (radix, numeric) = if string.starts_with("0x") {
(16, &string[2..])
} else if string.starts_with("0b") {
(2, &string[2..])
} else if string.starts_with("0o") {
(8, &string[2..])
let (radix, numeric) = if let Some(s) = string.strip_prefix("0x") {
(16, s)
} else if let Some(s) = string.strip_prefix("0b") {
(2, s)
} else if let Some(s) = string.strip_prefix("0o") {
(8, s)
} else {
(10, string)
};

View File

@ -37,11 +37,13 @@ impl<T: Copy> Signal<T> {
#[derive(Clone, Debug)]
pub struct EdgeSignal(Signal<bool>);
impl EdgeSignal {
pub fn new() -> Self {
impl Default for EdgeSignal {
fn default() -> Self {
EdgeSignal(Signal::new(false))
}
}
impl EdgeSignal {
pub fn signal(&mut self) {
self.0.set(true);
}
@ -53,8 +55,10 @@ impl EdgeSignal {
}
}
type ObservableCallback<T> = Box<dyn Fn(&T)>;
#[derive(Clone)]
pub struct ObservableSignal<T>(Rc<RefCell<(T, Option<Box<dyn Fn(&T)>>)>>);
pub struct ObservableSignal<T>(Rc<RefCell<(T, Option<ObservableCallback<T>>)>>);
impl<T> ObservableSignal<T> {
pub fn new(init: T) -> ObservableSignal<T> {
@ -84,11 +88,13 @@ impl<T> Observable<T> for ObservableSignal<T> {
pub struct ObservableEdgeSignal(ObservableSignal<bool>);
impl ObservableEdgeSignal {
pub fn new() -> Self {
impl Default for ObservableEdgeSignal {
fn default() -> Self {
ObservableEdgeSignal(ObservableSignal::new(false))
}
}
impl ObservableEdgeSignal {
pub fn set(&mut self) {
*self.0.borrow_mut() = true;
self.0.notify();

View File

@ -25,23 +25,25 @@ pub struct System {
pub break_signal: Option<EdgeSignal>,
}
impl System {
pub fn new() -> System {
System {
impl Default for System {
fn default() -> Self {
Self {
clock: 0,
devices: HashMap::new(),
event_queue: vec![],
debug_enabled: Cell::new(false),
debugger: RefCell::new(Debugger::new()),
debugger: RefCell::new(Debugger::default()),
bus: Rc::new(RefCell::new(Bus::new())),
interrupt_controller: RefCell::new(InterruptController::new()),
bus: Rc::new(RefCell::new(Bus::default())),
interrupt_controller: RefCell::new(InterruptController::default()),
break_signal: None,
}
}
}
impl System {
pub fn get_bus(&self) -> RefMut<'_, Bus> {
self.bus.borrow_mut()
}
@ -91,7 +93,7 @@ impl System {
fn process_one_event(&mut self) -> Result<(), Error> {
let mut event_device = self.event_queue.pop().unwrap();
self.clock = event_device.next_clock;
let result = match event_device.device.borrow_mut().as_steppable().unwrap().step(&self) {
let result = match event_device.device.borrow_mut().as_steppable().unwrap().step(self) {
Ok(diff) => {
event_device.next_clock = self.clock + diff;
Ok(())
@ -152,7 +154,7 @@ impl System {
pub fn exit_error(&mut self) {
for (_, dev) in self.devices.iter() {
match dev.borrow_mut().as_steppable() {
Some(dev) => dev.on_error(&self),
Some(dev) => dev.on_error(self),
None => { },
}
}
@ -162,7 +164,7 @@ impl System {
if self.debug_enabled.get() {
let top = self.event_queue[self.event_queue.len() - 1].device.clone();
if top.borrow_mut().as_debuggable().map(|debug| debug.debugging_enabled()).unwrap_or(false) {
if let Err(err) = self.debugger.borrow_mut().run_debugger(&self, top.clone()) {
if let Err(err) = self.debugger.borrow_mut().run_debugger(self, top.clone()) {
println!("Error: {:?}", err);
}
}

View File

@ -11,8 +11,8 @@ pub struct AverageTimer {
pub start: Option<Instant>,
}
impl AverageTimer {
pub fn new() -> AverageTimer {
impl Default for AverageTimer {
fn default() -> AverageTimer {
AverageTimer {
high: 0,
average: 0.0,
@ -21,7 +21,9 @@ impl AverageTimer {
start: None,
}
}
}
impl AverageTimer {
pub fn start(&mut self) {
//self.start = Some(Instant::now())
}
@ -47,28 +49,18 @@ impl fmt::Display for AverageTimer {
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct CpuTimer {
pub decode: AverageTimer,
pub execute: AverageTimer,
pub cycle: AverageTimer,
}
impl CpuTimer {
pub fn new() -> CpuTimer {
CpuTimer {
decode: AverageTimer::new(),
execute: AverageTimer::new(),
cycle: AverageTimer::new(),
}
}
}
impl fmt::Display for CpuTimer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Decode: {}\n", self.decode)?;
write!(f, "Execute: {}\n", self.execute)?;
write!(f, "Cycle: {}\n", self.cycle)?;
writeln!(f, "Decode: {}", self.decode)?;
writeln!(f, "Execute: {}", self.execute)?;
writeln!(f, "Cycle: {}", self.cycle)?;
Ok(())
}
}

View File

@ -141,7 +141,7 @@ impl M68kAssembler {
self.labels.insert(label.clone(), self.output.len() - 1);
},
AssemblyLine::Instruction(name, list) => {
self.convert_instruction(lineno, &name, &list)?;
self.convert_instruction(lineno, name, list)?;
},
}
Ok(())
@ -255,7 +255,7 @@ impl M68kAssembler {
let (effective_address_left, additional_words_left) = convert_target(lineno, &args[0], operation_size, Disallow::None)?;
let (effective_address_right, additional_words_right) = convert_target(lineno, &args[1], operation_size, Disallow::None)?;
let effective_address_left = (effective_address_left >> 3) | (effective_address_left << 3);
self.output.push(0x0000 | encode_size_for_move(operation_size) | effective_address_left | effective_address_right);
self.output.push(encode_size_for_move(operation_size) | effective_address_left | effective_address_right);
self.output.extend(additional_words_left);
self.output.extend(additional_words_right);
},
@ -371,23 +371,23 @@ impl M68kAssembler {
};
match &args {
&[AssemblyOperand::Immediate(_), AssemblyOperand::Register(_)] => {
[AssemblyOperand::Immediate(_), AssemblyOperand::Register(_)] => {
let mut immediate = parser::expect_immediate(lineno, &args[0])?;
if immediate < 1 || immediate > 8 {
if !(1..=8).contains(&immediate) {
return Err(Error::new(&format!("error at line {}: immediate value must be between 1 and 8, found {:?}", lineno, args)));
} else if immediate == 8 {
immediate = 0;
}
let reg = expect_data_register(lineno, &args[1])?;
self.output.push(opcode | ((immediate as u16) << 9) | direction | encode_size(operation_size) | (0b0 << 5) | reg);
self.output.push(opcode | ((immediate as u16) << 9) | direction | encode_size(operation_size) /*(0b0 << 5)*/ | reg);
},
&[AssemblyOperand::Register(_), AssemblyOperand::Register(_)] => {
[AssemblyOperand::Register(_), AssemblyOperand::Register(_)] => {
let bit_reg = expect_data_register(lineno, &args[0])?;
let reg = expect_data_register(lineno, &args[1])?;
self.output.push(opcode | ((bit_reg as u16) << 9) | direction | encode_size(operation_size) | (0b1 << 5) | reg);
},
//&[_] => {
//[_] => {
// let (effective_address, additional_words) = convert_target(lineno, &args[0], Size::Word, Disallow::NoRegsImmediateOrPC)?;
// self.output.push(opcode | effective_address);
// self.output.extend(additional_words);
@ -414,7 +414,7 @@ fn convert_target(lineno: usize, operand: &AssemblyOperand, size: Size, disallow
disallow.check(lineno, Disallow::NoIndirectPost)?;
if args.len() == 1 && operator == "+" {
if let AssemblyOperand::Register(name) = &args[0] {
if name.starts_with("a") {
if name.starts_with('a') {
let reg = expect_reg_num(lineno, name)?;
return Ok(((0b011 << 3) | reg, vec![]));
}
@ -426,7 +426,7 @@ fn convert_target(lineno: usize, operand: &AssemblyOperand, size: Size, disallow
disallow.check(lineno, Disallow::NoIndirectPre)?;
if args.len() == 1 && operator == "-" {
if let AssemblyOperand::Register(name) = &args[0] {
if name.starts_with("a") {
if name.starts_with('a') {
let reg = expect_reg_num(lineno, name)?;
return Ok(((0b100 << 3) | reg, vec![]));
} else if name == "sp" {
@ -442,12 +442,12 @@ fn convert_target(lineno: usize, operand: &AssemblyOperand, size: Size, disallow
fn convert_register(lineno: usize, name: &str, disallow: Disallow) -> Result<(u16, Vec<u16>), Error> {
match name {
name if name.starts_with("d") => {
name if name.starts_with('d') => {
disallow.check(lineno, Disallow::NoDReg)?;
let reg = expect_reg_num(lineno, name)?;
Ok(((0b000 << 3) | reg, vec![]))
Ok((/*(0b000 << 3)*/ reg, vec![]))
},
name if name.starts_with("a") => {
name if name.starts_with('a') => {
disallow.check(lineno, Disallow::NoAReg)?;
let reg = expect_reg_num(lineno, name)?;
Ok(((0b001 << 3) | reg, vec![]))
@ -462,12 +462,12 @@ fn convert_register(lineno: usize, name: &str, disallow: Disallow) -> Result<(u1
fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow) -> Result<(u16, Vec<u16>), Error> {
match &args {
&[AssemblyOperand::Register(name)] => {
[AssemblyOperand::Register(name)] => {
disallow.check(lineno, Disallow::NoIndirect)?;
let reg = expect_address_reg_num(lineno, name)?;
Ok(((0b010 << 3) | reg, vec![]))
},
&[AssemblyOperand::Immediate(address)] => {
[AssemblyOperand::Immediate(address)] => {
disallow.check(lineno, Disallow::NoIndirectImmediate)?;
if *address < u16::MAX as usize {
Ok((0b111000, convert_immediate(lineno, *address, Size::Word)?))
@ -475,7 +475,7 @@ fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow)
Ok((0b111001, convert_immediate(lineno, *address, Size::Long)?))
}
},
&[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name)] => {
[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name)] => {
if name == "pc" {
disallow.check(lineno, Disallow::NoPCRelative)?;
Ok((0b111010, convert_immediate(lineno, *offset, Size::Word)?))
@ -485,9 +485,9 @@ fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow)
Ok(((0b101 << 3) | reg, convert_immediate(lineno, *offset, Size::Word)?))
}
},
&[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name), AssemblyOperand::Register(index)] => {
[AssemblyOperand::Immediate(offset), AssemblyOperand::Register(name), AssemblyOperand::Register(index)] => {
let index_reg = expect_reg_num(lineno, index)?;
let da_select = if index.starts_with("a") { 1 << 15 } else { 0 };
let da_select = if index.starts_with('a') { 1 << 15 } else { 0 };
if name == "pc" {
disallow.check(lineno, Disallow::NoPCRelativeIndex)?;
Ok((0b111011, vec![da_select | (index_reg << 12) | ((*offset as u16) & 0xff)]))
@ -504,13 +504,13 @@ fn convert_indirect(lineno: usize, args: &[AssemblyOperand], disallow: Disallow)
}
}
fn convert_reg_and_other<'a>(lineno: usize, args: &'a [AssemblyOperand], _disallow: Disallow) -> Result<(u16, u16, &'a AssemblyOperand), Error> {
fn convert_reg_and_other(lineno: usize, args: &[AssemblyOperand], _disallow: Disallow) -> Result<(u16, u16, &AssemblyOperand), Error> {
match &args {
&[AssemblyOperand::Register(reg), effective_address] => {
Ok(((0b1 << 8), expect_reg_num(lineno, &reg)?, effective_address))
[AssemblyOperand::Register(reg), effective_address] => {
Ok(((0b1 << 8), expect_reg_num(lineno, reg)?, effective_address))
},
&[effective_address, AssemblyOperand::Register(reg)] => {
Ok(((0b0 << 8), expect_reg_num(lineno, &reg)?, effective_address))
[effective_address, AssemblyOperand::Register(reg)] => {
Ok(((0b0 << 8), expect_reg_num(lineno, reg)?, effective_address))
},
_ => {
Err(Error::new(&format!("error at line {}: expected register and effective address, but found {:?}", lineno, args)))
@ -540,7 +540,7 @@ fn convert_immediate(lineno: usize, value: usize, size: Size) -> Result<Vec<u16>
fn expect_data_register(lineno: usize, operand: &AssemblyOperand) -> Result<u16, Error> {
if let AssemblyOperand::Register(name) = operand {
if name.starts_with("d") {
if name.starts_with('d') {
return expect_reg_num(lineno, name);
}
}
@ -549,7 +549,7 @@ fn expect_data_register(lineno: usize, operand: &AssemblyOperand) -> Result<u16,
fn expect_address_register(lineno: usize, operand: &AssemblyOperand) -> Result<u16, Error> {
if let AssemblyOperand::Register(name) = operand {
if name.starts_with("d") {
if name.starts_with('d') {
return expect_reg_num(lineno, name);
}
}
@ -557,7 +557,7 @@ fn expect_address_register(lineno: usize, operand: &AssemblyOperand) -> Result<u
}
fn expect_address_reg_num(lineno: usize, name: &str) -> Result<u16, Error> {
if name.starts_with("a") {
if name.starts_with('a') {
return expect_reg_num(lineno, name);
}
Err(Error::new(&format!("error at line {}: expected an address register, but found {:?}", lineno, name)))

View File

@ -4,18 +4,12 @@ use moa_core::{System, Error, Address, Addressable, Debuggable};
use super::state::M68k;
use super::decode::M68kDecoder;
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct StackTracer {
pub calls: Vec<u32>,
}
impl StackTracer {
pub fn new() -> StackTracer {
StackTracer {
calls: vec![],
}
}
pub fn push_return(&mut self, addr: u32) {
self.calls.push(addr);
}
@ -26,7 +20,7 @@ impl StackTracer {
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct M68kDebugger {
pub enabled: bool,
pub breakpoints: Vec<u32>,
@ -35,18 +29,6 @@ pub struct M68kDebugger {
pub stack_tracer: StackTracer,
}
impl M68kDebugger {
pub fn new() -> M68kDebugger {
M68kDebugger {
enabled: false,
breakpoints: vec!(),
use_tracing: false,
step_until_return: None,
stack_tracer: StackTracer::new(),
}
}
}
impl Debuggable for M68k {
fn debugging_enabled(&mut self) -> bool {
self.debugger.enabled

View File

@ -50,7 +50,7 @@ impl M68kDecoder {
pub fn new(cputype: M68kType, start: u32) -> M68kDecoder {
M68kDecoder {
cputype,
start: start,
start,
end: start,
instruction_word: 0,
instruction: Instruction::NOP,
@ -85,7 +85,7 @@ impl M68kDecoder {
0b0000 => Ok(Instruction::ORtoCCR(data as u8)),
0b0010 => Ok(Instruction::ANDtoCCR(data as u8)),
0b1010 => Ok(Instruction::EORtoCCR(data as u8)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
0b01 => {
@ -94,10 +94,10 @@ impl M68kDecoder {
0b0000 => Ok(Instruction::ORtoSR(data)),
0b0010 => Ok(Instruction::ANDtoSR(data)),
0b1010 => Ok(Instruction::EORtoSR(data)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if (ins & 0x138) == 0x108 {
let dreg = get_high_reg(ins);
@ -124,7 +124,7 @@ impl M68kDecoder {
0b01 => Ok(Instruction::BCHG(bitnum, target, size)),
0b10 => Ok(Instruction::BCLR(bitnum, target, size)),
0b11 => Ok(Instruction::BSET(bitnum, target, size)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else {
let size = get_size(ins);
@ -143,7 +143,7 @@ impl M68kDecoder {
0b0110 => Ok(Instruction::ADD(Target::Immediate(data), target, size.unwrap())),
0b1010 => Ok(Instruction::EOR(Target::Immediate(data), target, size.unwrap())),
0b1100 => Ok(Instruction::CMP(Target::Immediate(data), target, size.unwrap())),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}
},
@ -221,7 +221,7 @@ impl M68kDecoder {
match get_size(ins) {
Some(size) => Ok(Instruction::CLR(target, size)),
None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)),
None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
None => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
0b100 => {
@ -236,7 +236,7 @@ impl M68kDecoder {
None => Ok(Instruction::MOVEtoSR(target)),
}
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if ins_0f00 == 0x800 || ins_0f00 == 0x900 {
let opmode = (ins & 0x01C0) >> 6;
@ -269,7 +269,7 @@ impl M68kDecoder {
(0b111, 0b000) => {
Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if ins_0f00 == 0xA00 {
if (ins & 0x0FF) == 0xFC {
@ -332,11 +332,11 @@ impl M68kDecoder {
};
Ok(Instruction::MOVEC(target, creg, dir))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}
} else {
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
Err(Error::processor(Exceptions::IllegalInstruction as u32))
}
},
OPCG_ADDQ_SUBQ => {
@ -354,12 +354,10 @@ impl M68kDecoder {
} else {
Ok(Instruction::SUBA(Target::Immediate(data), reg, size))
}
} else if (ins & 0x0100) == 0 {
Ok(Instruction::ADD(Target::Immediate(data), target, size))
} else {
if (ins & 0x0100) == 0 {
Ok(Instruction::ADD(Target::Immediate(data), target, size))
} else {
Ok(Instruction::SUB(Target::Immediate(data), target, size))
}
Ok(Instruction::SUB(Target::Immediate(data), target, size))
}
},
None => {
@ -402,11 +400,7 @@ impl M68kDecoder {
OPCG_DIV_OR => {
let size = get_size(ins);
if size.is_none() {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign))
} else if (ins & 0x1F0) == 0x100 {
if (ins & 0x1F0) == 0x100 {
let regx = get_high_reg(ins);
let regy = get_low_reg(ins);
@ -414,11 +408,15 @@ impl M68kDecoder {
false => Ok(Instruction::SBCD(Target::DirectDReg(regy), Target::DirectDReg(regx))),
true => Ok(Instruction::SBCD(Target::IndirectARegDec(regy), Target::IndirectARegDec(regx))),
}
} else {
} else if let Some(size) = size {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(memory, ins, size)?;
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(size))?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::OR(from, to, size.unwrap()))
Ok(Instruction::OR(from, to, size))
} else {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
Ok(Instruction::DIVW(effective_addr, get_high_reg(ins), sign))
}
},
OPCG_SUB => {
@ -472,7 +470,7 @@ impl M68kDecoder {
let target = self.decode_lower_effective_address(memory, ins, Some(size))?;
Ok(Instruction::CMPA(target, reg, size))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
OPCG_MUL_AND => {
@ -486,24 +484,24 @@ impl M68kDecoder {
false => Ok(Instruction::ABCD(Target::DirectDReg(regy), Target::DirectDReg(regx))),
true => Ok(Instruction::ABCD(Target::IndirectARegDec(regy), Target::IndirectARegDec(regx))),
}
} else if (ins & 0b0001_0011_0000) == 0b0001_0000_0000 && !size.is_none() {
} else if (ins & 0b0001_0011_0000) == 0b0001_0000_0000 && size.is_some() {
let regx = get_high_reg(ins);
let regy = get_low_reg(ins);
match (ins & 0x00F8) >> 3 {
0b01000 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectDReg(regy))),
0b01001 => Ok(Instruction::EXG(Target::DirectAReg(regx), Target::DirectAReg(regy))),
0b10001 => Ok(Instruction::EXG(Target::DirectDReg(regx), Target::DirectAReg(regy))),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if size.is_none() {
} else if let Some(size) = size {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(size))?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::AND(from, to, size))
} else {
let sign = if (ins & 0x0100) == 0 { Sign::Unsigned } else { Sign::Signed };
let effective_addr = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?;
Ok(Instruction::MULW(effective_addr, get_high_reg(ins), sign))
} else {
let data_reg = Target::DirectDReg(get_high_reg(ins));
let effective_addr = self.decode_lower_effective_address(memory, ins, size)?;
let (from, to) = if (ins & 0x0100) == 0 { (effective_addr, data_reg) } else { (data_reg, effective_addr) };
Ok(Instruction::AND(from, to, size.unwrap()))
}
},
OPCG_ADD => {
@ -552,7 +550,7 @@ impl M68kDecoder {
0b01 => Ok(Instruction::LSd(count, Target::DirectDReg(reg), size, dir)),
0b10 => Ok(Instruction::ROXd(count, Target::DirectDReg(reg), size, dir)),
0b11 => Ok(Instruction::ROd(count, Target::DirectDReg(reg), size, dir)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
},
None => {
@ -564,7 +562,7 @@ impl M68kDecoder {
0b01 => Ok(Instruction::LSd(count, target, Size::Word, dir)),
0b10 => Ok(Instruction::ROXd(count, target, Size::Word, dir)),
0b11 => Ok(Instruction::ROd(count, target, Size::Word, dir)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else if self.cputype > M68kType::MC68020 {
// Bitfield instructions (MC68020+)
@ -591,10 +589,10 @@ impl M68kDecoder {
0b111 => Ok(Instruction::BFINS(reg, target, offset, width)),
0b110 => Ok(Instruction::BFSET(target, offset, width)),
0b000 => Ok(Instruction::BFTST(target, offset, width)),
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
} else {
return Err(Error::processor(Exceptions::IllegalInstruction as u32));
Err(Error::processor(Exceptions::IllegalInstruction as u32))
}
},
}
@ -605,7 +603,7 @@ impl M68kDecoder {
OPCG_FLINE => {
Ok(Instruction::UnimplementedF(ins))
},
_ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)),
_ => Err(Error::processor(Exceptions::IllegalInstruction as u32)),
}
}

View File

@ -21,7 +21,7 @@ use crate::instructions::{
};
const DEV_NAME: &'static str = "m68k-cpu";
const DEV_NAME: &str = "m68k-cpu";
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Used {
@ -358,14 +358,14 @@ impl M68k {
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
let mut src_val = self.get_target_value(target, size, Used::Twice)?;
let mask = self.set_bit_test_flags(src_val, bitnum, size);
src_val = src_val & !mask;
src_val &= !mask;
self.set_target_value(target, src_val, size, Used::Twice)?;
},
Instruction::BSET(bitnum, target, size) => {
let bitnum = self.get_target_value(bitnum, Size::Byte, Used::Once)?;
let mut value = self.get_target_value(target, size, Used::Twice)?;
let mask = self.set_bit_test_flags(value, bitnum, size);
value = value | mask;
value |= mask;
self.set_target_value(target, value, size, Used::Twice)?;
},
Instruction::BTST(bitnum, target, size) => {
@ -1562,7 +1562,7 @@ fn rotate_operation(value: u32, size: Size, dir: ShiftDirection, use_extend: Opt
}
},
ShiftDirection::Right => {
let bit = if (value & 0x01) != 0 { true } else { false };
let bit = (value & 0x01) != 0;
let mask = if use_extend.unwrap_or(bit) { get_msb_mask(0xffffffff, size) } else { 0x0 };
((value >> 1) | mask, bit)
},

View File

@ -1,66 +1,66 @@
use std::fmt;
use std::fmt::{self, Write};
pub type Register = u8;
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Size {
Byte,
Word,
Long,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Sign {
Signed,
Unsigned,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Direction {
FromTarget,
ToTarget,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ShiftDirection {
Right,
Left,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum XRegister {
DReg(u8),
AReg(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum BaseRegister {
None,
PC,
AReg(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct IndexRegister {
pub xreg: XRegister,
pub scale: u8,
pub size: Size,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum RegOrImmediate {
DReg(u8),
Immediate(u8),
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ControlRegister {
VBR,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Condition {
True,
False,
@ -80,7 +80,7 @@ pub enum Condition {
LessThanOrEqual,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Target {
Immediate(u32),
DirectDReg(Register),
@ -94,7 +94,7 @@ pub enum Target {
IndirectMemory(u32, Size),
}
#[derive(Clone, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Instruction {
ABCD(Target, Target),
ADD(Target, Target, Size),
@ -318,7 +318,7 @@ fn fmt_index_disp(index: &Option<IndexRegister>) -> String {
Some(index) => {
let mut result = format!(", %{}", index.xreg);
if index.scale != 0 {
result += &format!("<< {}", index.scale);
write!(result, "<< {}", index.scale).unwrap();
}
result
},
@ -433,7 +433,7 @@ impl fmt::Display for Instruction {
Instruction::DBcc(cond, reg, offset) => write!(f, "db{}\t%d{}, {}", cond, reg, offset),
Instruction::DIVW(src, dest, sign) => write!(f, "div{}w\t{}, %d{}", sign, src, dest),
Instruction::DIVL(src, desth, destl, sign) => {
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or("".to_string());
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or_else(|| "".to_string());
write!(f, "div{}l\t{}, {}%d{}", sign, src, opt_reg, destl)
},
@ -478,7 +478,7 @@ impl fmt::Display for Instruction {
},
Instruction::MULW(src, dest, sign) => write!(f, "mul{}w\t{}, %d{}", sign, src, dest),
Instruction::MULL(src, desth, destl, sign) => {
let opt_reg = desth.map(|reg| format!("%d{}:", reg)).unwrap_or("".to_string());
let