mirror of
https://github.com/transistorfet/moa.git
synced 2024-11-06 12:07:12 +00:00
Fixed all clippy warnings
This commit is contained in:
parent
0ac3f48b64
commit
7bdd63bc76
1
.clippy.toml
Normal file
1
.clippy.toml
Normal file
@ -0,0 +1 @@
|
||||
msrv = "1.60.0"
|
@ -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(())
|
||||
|
@ -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>;
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ErrorType {
|
||||
Assertion,
|
||||
Emulator,
|
||||
|
@ -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),
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Key {
|
||||
A,
|
||||
B,
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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"));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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, ®)?, 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, ®)?, 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)))
|
||||
|
@ -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
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
},
|
||||
|
@ -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 |