Skip to content

Commit

Permalink
Add a bit() function
Browse files Browse the repository at this point in the history
  • Loading branch information
Stovent committed Mar 28, 2024
1 parent 0d0d0fd commit f20af54
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 109 deletions.
44 changes: 30 additions & 14 deletions m68000/src/addressing_modes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use crate::{CpuDetails, M68000, MemoryAccess};
use crate::memory_access::MemoryIter;
use crate::instruction::Size;
use crate::utils::bits;
use crate::utils::{bit, bits};

/// Addressing modes.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -248,33 +248,48 @@ impl std::fmt::UpperHex for AddressingMode {
pub struct BriefExtensionWord(pub u16);

impl BriefExtensionWord {
/// Returns the displacement associated with the brief extension word.
pub const fn disp(self) -> i8 {
self.0 as i8
}

/// Creates a new brief extension word, to be used when using the assembler.
///
/// - `address`: true if the index register is an address register, false for a data register.
/// - `reg`: the register number (must be <= 7).
/// - `long`: true if long size, false for word size.
/// - `disp:`: the associated displacement value.
pub const fn new(address: bool, reg: u8, long: bool, disp: i8) -> Self {
assert!(reg <= 7, "Invalid register.");
assert!(reg <= 7, "Invalid register");
let a = (address as u16) << 15;
let r = (reg as u16) << 12;
let s = (long as u16) << 11;
let d = disp as u8 as u16;
Self(a | r | s | d)
}

/// Returns the displacement associated with the brief extension word.
pub const fn disp(self) -> i8 {
self.0 as i8
}

#[inline(always)]
const fn is_address_reg(self) -> bool {
bit(self.0, 15)
}

#[inline(always)]
const fn reg(self) -> u8 {
bits(self.0, 12, 14) as u8
}

#[inline(always)]
const fn is_long(self) -> bool {
bit(self.0, 11)
}
}

impl std::fmt::Display for BriefExtensionWord {
/// Disassembles the index register field of a brief extension word.
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let x = if self.0 & 0x8000 != 0 { "A" } else { "D" };
let reg = bits(self.0, 12, 14);
let size = if self.0 & 0x0800 != 0 { "L" } else { "W" };
let x = if self.is_address_reg() { "A" } else { "D" };
let reg = self.reg();
let size = if self.is_long() { "L" } else { "W" };
write!(f, "{x}{reg}.{size}")
}
}
Expand Down Expand Up @@ -351,16 +366,17 @@ impl<CPU: CpuDetails> M68000<CPU> {
}

const fn get_index_register(&self, bew: BriefExtensionWord) -> u32 {
let reg = bits(bew.0, 12, 14) as u8;
let reg = bew.reg();
let long = bew.is_long();

if bew.0 & 0x8000 != 0 { // Address register
if bew.0 & 0x0800 != 0 { // Long
if bew.is_address_reg() {
if long {
self.regs.a(reg)
} else { // Word
self.regs.a(reg) as i16 as u32
}
} else { // Data register
if bew.0 & 0x0800 != 0 { // Long
if long {
self.regs.d[reg as usize].0
} else { // Word
self.regs.d[reg as usize].0 as i16 as u32
Expand Down
16 changes: 8 additions & 8 deletions m68000/src/disassembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ pub fn disassemble_asm(inst: &Instruction) -> String {
}

pub fn disassemble_asr(inst: &Instruction) -> String {
let (rot, d, s, mode, reg) = inst.operands.rotation_direction_size_mode_register();
if mode == 1 {
let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
if ir {
format!("AS{}.{} D{}, D{}", d, s, rot, reg)
} else {
let rot = if rot == 0 { 8 } else { rot };
Expand Down Expand Up @@ -261,8 +261,8 @@ pub fn disassemble_lsm(inst: &Instruction) -> String {
}

pub fn disassemble_lsr(inst: &Instruction) -> String {
let (rot, d, s, mode, reg) = inst.operands.rotation_direction_size_mode_register();
if mode == 1 {
let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
if ir {
format!("LS{}.{} D{}, D{}", d, s, rot, reg)
} else {
let rot = if rot == 0 { 8 } else { rot };
Expand Down Expand Up @@ -401,8 +401,8 @@ pub fn disassemble_rom(inst: &Instruction) -> String {
}

pub fn disassemble_ror(inst: &Instruction) -> String {
let (rot, d, s, mode, reg) = inst.operands.rotation_direction_size_mode_register();
if mode == 1 {
let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
if ir {
format!("RO{}.{} D{}, D{}", d, s, rot, reg)
} else {
let rot = if rot == 0 { 8 } else { rot };
Expand All @@ -416,8 +416,8 @@ pub fn disassemble_roxm(inst: &Instruction) -> String {
}

pub fn disassemble_roxr(inst: &Instruction) -> String {
let (rot, d, s, mode, reg) = inst.operands.rotation_direction_size_mode_register();
if mode == 1 {
let (rot, d, s, ir, reg) = inst.operands.rotation_direction_size_mode_register();
if ir {
format!("ROX{}.{} D{}, D{}", d, s, rot, reg)
} else {
let rot = if rot == 0 { 8 } else { rot };
Expand Down
39 changes: 19 additions & 20 deletions m68000/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::decoder::DECODER;
use crate::disassembler::DLUT;
use crate::isa::{Isa, IsaEntry};
use crate::memory_access::{MemoryAccess, MemoryIter};
use crate::utils::bits;
use crate::utils::{bit, bits};

/// M68000 instruction.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -149,11 +149,10 @@ impl Size {
/// - 0 => Word
/// - 1 => Long
#[inline(always)]
pub fn from_bit(d: u16) -> Self {
pub fn from_bit(d: bool) -> Self {
match d {
0 => Self::Word,
1 => Self::Long,
_ => panic!("[Size::from_bit] Wrong size : expected 0 or 1, got {}", d),
false => Self::Word,
true => Self::Long,
}
}

Expand Down Expand Up @@ -318,7 +317,7 @@ pub enum Operands {
/// ASm, LSm, ROm, ROXm
DirectionEffectiveAddress(Direction, AddressingMode),
/// ASr, LSr, ROr, ROXr
RotationDirectionSizeModeRegister(u8, Direction, Size, u8, u8),
RotationDirectionSizeModeRegister(u8, Direction, Size, bool, u8),
}

/// In the returned values, the first operand is the left-most operand in the instruction word (high-order bits).
Expand Down Expand Up @@ -541,7 +540,7 @@ impl Operands {
}

/// ASr, LSr, ROr, ROXr
pub const fn rotation_direction_size_mode_register(self) -> (u8, Direction, Size, u8, u8) {
pub const fn rotation_direction_size_mode_register(self) -> (u8, Direction, Size, bool, u8) {
match self {
Self::RotationDirectionSizeModeRegister(r, d, s, m, rr) => (r, d, s, m, rr),
_ => panic!("[Operands::rotation_direction_size_mode_register]"),
Expand Down Expand Up @@ -743,7 +742,7 @@ pub fn size_effective_address_immediate<M: MemoryAccess + ?Sized>(opcode: u16, m

/// BCHG, BCLR, BSET, BTST
pub fn effective_address_count<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (AddressingMode, u8) {
let count = if bits(opcode, 8, 8) != 0 { // dynamic bit number
let count = if bit(opcode, 8) { // dynamic bit number
bits(opcode, 9, 11) as u8
} else { // Static bit number
memory.next().unwrap().expect("Access error occured when fetching count operand.") as u8
Expand Down Expand Up @@ -805,8 +804,8 @@ pub fn register_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory:
/// MOVEP
pub fn register_direction_size_register_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, Direction, Size, u8, i16) {
let dreg = bits(opcode, 9, 11) as u8;
let dir = if bits(opcode, 7, 7) != 0 { Direction::RegisterToMemory } else { Direction::MemoryToRegister };
let size = if bits(opcode, 6, 6) != 0 { Size::Long } else { Size::Word };
let dir = if bit(opcode, 7) { Direction::RegisterToMemory } else { Direction::MemoryToRegister };
let size = if bit(opcode, 6) { Size::Long } else { Size::Word };
let areg = bits(opcode, 0, 2) as u8;
let disp = memory.next().unwrap().expect("Access error occured when fetching displacement operand.") as i16;

Expand Down Expand Up @@ -884,7 +883,7 @@ pub fn register(opcode: u16) -> u8 {

/// MOVE USP
pub fn direction_register(opcode: u16) -> (Direction, u8) {
let dir = if bits(opcode, 3, 3) != 0 { Direction::UspToRegister } else { Direction::RegisterToUsp };
let dir = if bit(opcode, 3) { Direction::UspToRegister } else { Direction::RegisterToUsp };
let reg = bits(opcode, 0, 2) as u8;

(dir, reg)
Expand All @@ -893,8 +892,8 @@ pub fn direction_register(opcode: u16) -> (Direction, u8) {
/// MOVEM
pub fn direction_size_effective_address_list<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (Direction, Size, AddressingMode, u16) {
let list = memory.next().unwrap().expect("Access error occured when fetching list operand.");
let dir = if bits(opcode, 10, 10) != 0 { Direction::MemoryToRegister } else { Direction::RegisterToMemory };
let size = Size::from_bit(bits(opcode, 6, 6));
let dir = if bit(opcode, 10) { Direction::MemoryToRegister } else { Direction::RegisterToMemory };
let size = Size::from_bit(bit(opcode, 6));

let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
Expand Down Expand Up @@ -964,7 +963,7 @@ pub fn register_data(opcode: u16) -> (u8, i8) {
/// ADD, AND, CMP, EOR, OR, SUB
pub fn register_direction_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, Direction, Size, AddressingMode) {
let reg = bits(opcode, 9, 11) as u8;
let dir = if bits(opcode, 8, 8) != 0 { Direction::DstEa } else { Direction::DstReg }; // CMP and EOR ignores it
let dir = if bit(opcode, 8) { Direction::DstEa } else { Direction::DstReg }; // CMP and EOR ignores it
let size = Size::from(bits(opcode, 6, 7));

let eareg = bits(opcode, 0, 2) as u8;
Expand All @@ -977,7 +976,7 @@ pub fn register_direction_size_effective_address<M: MemoryAccess + ?Sized>(opcod
/// ADDA, CMPA, SUBA
pub fn register_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, Size, AddressingMode) {
let reg = bits(opcode, 9, 11) as u8;
let size = Size::from_bit(bits(opcode, 8, 8));
let size = Size::from_bit(bit(opcode, 8));

let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
Expand All @@ -990,7 +989,7 @@ pub fn register_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, me
pub fn register_size_mode_register(opcode: u16) -> (u8, Size, Direction, u8) {
let regl = bits(opcode, 9, 11) as u8;
let size = Size::from(bits(opcode, 6, 7));
let mode = if bits(opcode, 3, 3) != 0 { Direction::MemoryToMemory } else { Direction::RegisterToRegister };
let mode = if bit(opcode, 3) { Direction::MemoryToMemory } else { Direction::RegisterToRegister };
let regr = bits(opcode, 0, 2) as u8;

(regl, size, mode, regr)
Expand All @@ -1009,18 +1008,18 @@ pub fn register_size_register(opcode: u16) -> (u8, Size, u8) {
pub fn direction_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (Direction, AddressingMode) {
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let dir = if bits(opcode, 8, 8) != 0 { Direction::Left } else { Direction::Right };
let dir = if bit(opcode, 8) { Direction::Left } else { Direction::Right };
let am = AddressingMode::from_memory(eamode, eareg, Some(Size::Byte), memory);

(dir, am)
}

/// ASr, LSr, ROr, ROXr
pub fn rotation_direction_size_mode_register(opcode: u16) -> (u8, Direction, Size, u8, u8) {
pub fn rotation_direction_size_mode_register(opcode: u16) -> (u8, Direction, Size, bool, u8) {
let count = bits(opcode, 9, 11) as u8;
let dir = if bits(opcode, 8, 8) != 0 { Direction::Left } else { Direction::Right };
let dir = if bit(opcode, 8) { Direction::Left } else { Direction::Right };
let size = Size::from(bits(opcode, 6, 7));
let mode = bits(opcode, 5, 5) as u8;
let mode = bit(opcode, 5);
let reg = bits(opcode, 0, 2) as u8;

(count, dir, size, mode, reg)
Expand Down
16 changes: 8 additions & 8 deletions m68000/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,11 +477,11 @@ impl<CPU: CpuDetails> M68000<CPU> {
Ok(exec_time)
}

pub(super) fn execute_asr(&mut self, rot: u8, dir: Direction, size: Size, mode: u8, reg: u8) -> InterpreterResult {
pub(super) fn execute_asr(&mut self, rot: u8, dir: Direction, size: Size, ir: bool, reg: u8) -> InterpreterResult {
self.regs.sr.v = false;
self.regs.sr.c = false;

let shift_count = if mode == 1 {
let shift_count = if ir {
(self.regs.d[rot as usize].0 % 64) as u8
} else if rot == 0 {
8
Expand Down Expand Up @@ -1132,11 +1132,11 @@ impl<CPU: CpuDetails> M68000<CPU> {
Ok(exec_time)
}

pub(super) fn execute_lsr(&mut self, rot: u8, dir: Direction, size: Size, mode: u8, reg: u8) -> InterpreterResult {
pub(super) fn execute_lsr(&mut self, rot: u8, dir: Direction, size: Size, ir: bool, reg: u8) -> InterpreterResult {
self.regs.sr.v = false;
self.regs.sr.c = false;

let shift_count = if mode == 1 {
let shift_count = if ir {
(self.regs.d[rot as usize].0 % 64) as u8
} else if rot == 0 {
8
Expand Down Expand Up @@ -1768,11 +1768,11 @@ impl<CPU: CpuDetails> M68000<CPU> {
Ok(exec_time)
}

pub(super) fn execute_ror(&mut self, rot: u8, dir: Direction, size: Size, mode: u8, reg: u8) -> InterpreterResult {
pub(super) fn execute_ror(&mut self, rot: u8, dir: Direction, size: Size, ir: bool, reg: u8) -> InterpreterResult {
self.regs.sr.v = false;
self.regs.sr.c = false;

let shift_count = if mode == 1 {
let shift_count = if ir {
(self.regs.d[rot as usize].0 % 64) as u8
} else if rot == 0 {
8
Expand Down Expand Up @@ -1859,11 +1859,11 @@ impl<CPU: CpuDetails> M68000<CPU> {
Ok(exec_time)
}

pub(super) fn execute_roxr(&mut self, rot: u8, dir: Direction, size: Size, mode: u8, reg: u8) -> InterpreterResult {
pub(super) fn execute_roxr(&mut self, rot: u8, dir: Direction, size: Size, ir: bool, reg: u8) -> InterpreterResult {
self.regs.sr.v = false;
self.regs.sr.c = self.regs.sr.x;

let shift_count = if mode == 1 {
let shift_count = if ir {
(self.regs.d[rot as usize].0 % 64) as u8
} else if rot == 0 {
8
Expand Down
16 changes: 8 additions & 8 deletions m68000/src/interpreter_disassembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ impl<CPU: CpuDetails> M68000<CPU> {
}

fn instruction_asr<M: MemoryAccess + ?Sized>(&mut self, _: &mut M, inst: &Instruction) -> InterpreterResult {
let (rot, dir, size, mode, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_asr(rot, dir, size, mode, reg)
let (rot, dir, size, ir, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_asr(rot, dir, size, ir, reg)
}

fn instruction_bcc<M: MemoryAccess + ?Sized>(&mut self, _: &mut M, inst: &Instruction) -> InterpreterResult {
Expand Down Expand Up @@ -288,8 +288,8 @@ impl<CPU: CpuDetails> M68000<CPU> {
}

fn instruction_lsr<M: MemoryAccess + ?Sized>(&mut self, _: &mut M, inst: &Instruction) -> InterpreterResult {
let (rot, dir, size, mode, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_lsr(rot, dir, size, mode, reg)
let (rot, dir, size, ir, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_lsr(rot, dir, size, ir, reg)
}

fn instruction_move<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, inst: &Instruction) -> InterpreterResult {
Expand Down Expand Up @@ -406,8 +406,8 @@ impl<CPU: CpuDetails> M68000<CPU> {
}

fn instruction_ror<M: MemoryAccess + ?Sized>(&mut self, _: &mut M, inst: &Instruction) -> InterpreterResult {
let (rot, dir, size, mode, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_ror(rot, dir, size, mode, reg)
let (rot, dir, size, ir, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_ror(rot, dir, size, ir, reg)
}

fn instruction_roxm<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, inst: &Instruction) -> InterpreterResult {
Expand All @@ -416,8 +416,8 @@ impl<CPU: CpuDetails> M68000<CPU> {
}

fn instruction_roxr<M: MemoryAccess + ?Sized>(&mut self, _: &mut M, inst: &Instruction) -> InterpreterResult {
let (rot, dir, size, mode, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_roxr(rot, dir, size, mode, reg)
let (rot, dir, size, ir, reg) = inst.operands.rotation_direction_size_mode_register();
self.execute_roxr(rot, dir, size, ir, reg)
}

fn instruction_rte<M: MemoryAccess + ?Sized>(&mut self, memory: &mut M, _: &Instruction) -> InterpreterResult {
Expand Down
Loading

0 comments on commit f20af54

Please sign in to comment.