use crate::addressing_modes::AddressingMode;
use crate::decoder::DECODER;
use crate::disassembler::DLUT;
use crate::isa::{Isa, IsaEntry};
use crate::memory_access::{MemoryAccess, MemoryIter};
use crate::utils::{bit, bits};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "ffi", repr(C))]
pub struct Instruction {
pub opcode: u16,
pub pc: u32,
pub operands: Operands,
}
impl Instruction {
pub fn from_opcode<M: MemoryAccess + ?Sized>(opcode: u16, pc: u32, memory: &mut MemoryIter<M>) -> Self {
let isa = Isa::from(opcode);
let decode = IsaEntry::<M>::ISA_ENTRY[isa as usize].decode;
let operands = decode(opcode, memory);
Instruction {
opcode,
pc,
operands,
}
}
pub fn from_memory<M: MemoryAccess + ?Sized>(memory: &mut MemoryIter<M>) -> Result<Self, u8> {
let pc = memory.next_addr;
let opcode = memory.next().unwrap()?;
Ok(Self::from_opcode(opcode, pc, memory))
}
pub fn disassemble(&self) -> String {
let isa = Isa::from(self.opcode);
(DLUT[isa as usize])(self)
}
}
impl std::fmt::Display for Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.disassemble())
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "ffi", repr(C))]
pub enum Direction {
RegisterToMemory,
MemoryToRegister,
DstReg,
DstEa,
Left,
Right,
RegisterToUsp,
UspToRegister,
RegisterToRegister,
MemoryToMemory,
ExchangeData,
ExchangeAddress,
ExchangeDataAddress,
}
impl std::fmt::Display for Direction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Left => write!(f, "L"),
Self::Right => write!(f, "R"),
_ => Ok(()),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "ffi", repr(C))]
pub enum Size {
Byte = 1,
Word = 2,
Long = 4,
}
impl Size {
#[inline(always)]
pub fn as_word_long(self) -> Self {
if self == Self::Byte {
Self::Word
} else {
self
}
}
#[inline(always)]
pub fn from_bit(d: bool) -> Self {
match d {
false => Self::Word,
true => Self::Long,
}
}
#[inline(always)]
pub fn into_bit(self) -> u16 {
match self {
Self::Word => 0,
Self::Long => 1,
_ => panic!("[Size::into_bit] Wrong size : expected word or long, got {}", self),
}
}
#[inline(always)]
pub fn from_move(d: u16) -> Self {
match d {
1 => Self::Byte,
3 => Self::Word,
2 => Self::Long,
_ => panic!("[Size::from_move] Wrong Size : expected 1, 3 or 2, got {}", d),
}
}
#[inline(always)]
pub const fn into_move(self) -> u16 {
match self {
Self::Byte => 1,
Self::Word => 3,
Self::Long => 2,
}
}
#[inline(always)]
pub fn is_byte(self) -> bool {
self == Self::Byte
}
#[inline(always)]
pub fn is_word(self) -> bool {
self == Self::Word
}
#[inline(always)]
pub fn is_long(self) -> bool {
self == Self::Long
}
}
impl From<u16> for Size {
fn from(d: u16) -> Self {
match d {
0 => Self::Byte,
1 => Self::Word,
2 => Self::Long,
_ => panic!("[Size::from<u16>] Wrong size : expected 0, 1 or 2, got {}", d),
}
}
}
impl From<Size> for u16 {
fn from(s: Size) -> Self {
match s {
Size::Byte => 0,
Size::Word => 1,
Size::Long => 2,
}
}
}
impl std::fmt::Display for Size {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Size::Byte => write!(f, "B"),
Size::Word => write!(f, "W"),
Size::Long => write!(f, "L"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "ffi", repr(C))]
pub enum Operands {
NoOperands,
Immediate(u16),
SizeEffectiveAddressImmediate(Size, AddressingMode, u32),
EffectiveAddressCount(AddressingMode, u8),
EffectiveAddress(AddressingMode),
SizeEffectiveAddress(Size, AddressingMode),
RegisterEffectiveAddress(u8, AddressingMode),
RegisterDirectionSizeRegisterDisplacement(u8, Direction, Size, u8, i16),
SizeRegisterEffectiveAddress(Size, u8, AddressingMode),
SizeEffectiveAddressEffectiveAddress(Size, AddressingMode, AddressingMode),
RegisterOpmodeRegister(u8, Direction, u8),
OpmodeRegister(u8, u8),
Vector(u8),
RegisterDisplacement(u8, i16),
Register(u8),
DirectionRegister(Direction, u8),
DirectionSizeEffectiveAddressList(Direction, Size, AddressingMode, u16),
DataSizeEffectiveAddress(u8, Size, AddressingMode),
ConditionEffectiveAddress(u8, AddressingMode),
ConditionRegisterDisplacement(u8, u8, i16),
Displacement(i16),
ConditionDisplacement(u8, i16),
RegisterData(u8, i8),
RegisterDirectionSizeEffectiveAddress(u8, Direction, Size, AddressingMode),
RegisterSizeEffectiveAddress(u8, Size, AddressingMode),
RegisterSizeModeRegister(u8, Size, Direction, u8),
RegisterSizeRegister(u8, Size, u8),
DirectionEffectiveAddress(Direction, AddressingMode),
RotationDirectionSizeModeRegister(u8, Direction, Size, bool, u8),
}
impl Operands {
pub const fn immediate(self) -> u16 {
match self {
Self::Immediate(i) => i,
_ => panic!("[Operands::immediate]"),
}
}
pub const fn size_effective_address_immediate(self) -> (Size, AddressingMode, u32) {
match self {
Self::SizeEffectiveAddressImmediate(s, e, i) => (s, e, i),
_ => panic!("[Operands::size_effective_address_immediate]"),
}
}
pub const fn effective_address_count(self) -> (AddressingMode, u8) {
match self {
Self::EffectiveAddressCount(e, c) => (e, c),
_ => panic!("[Operands::effective_address_count]"),
}
}
pub const fn effective_address(self) -> AddressingMode {
match self {
Self::EffectiveAddress(e) => e,
_ => panic!("[Operands::effective_address]"),
}
}
pub const fn size_effective_address(self) -> (Size, AddressingMode) {
match self {
Self::SizeEffectiveAddress(s, e) => (s, e),
_ => panic!("[Operands::size_effective_address]"),
}
}
pub const fn register_effective_address(self) -> (u8, AddressingMode) {
match self {
Self::RegisterEffectiveAddress(r, e) => (r, e),
_ => panic!("[Operands::register_effective_address]"),
}
}
pub const fn register_direction_size_register_displacement(self) -> (u8, Direction, Size, u8, i16) {
match self {
Self::RegisterDirectionSizeRegisterDisplacement(r, d, s, rr, dd) => (r, d, s, rr, dd),
_ => panic!("[Operands::register_direction_size_register_displacement]"),
}
}
pub const fn size_register_effective_address(self) -> (Size, u8, AddressingMode) {
match self {
Self::SizeRegisterEffectiveAddress(s, r, e) => (s, r, e),
_ => panic!("[Operands::size_register_effective_address]"),
}
}
pub const fn size_effective_address_effective_address(self) -> (Size, AddressingMode, AddressingMode) {
match self {
Self::SizeEffectiveAddressEffectiveAddress(s, e, ee) => (s, e, ee),
_ => panic!("[Operands::size_effective_address_effective_address]"),
}
}
pub const fn register_opmode_register(self) -> (u8, Direction, u8) {
match self {
Self::RegisterOpmodeRegister(r, o, rr) => (r, o, rr),
_ => panic!("[Operands::register_opmode_register]"),
}
}
pub const fn opmode_register(self) -> (u8, u8) {
match self {
Self::OpmodeRegister(o, r) => (o, r),
_ => panic!("[Operands::opmode_register]"),
}
}
pub const fn vector(self) -> u8 {
match self {
Self::Vector(v) => v,
_ => panic!("[Operands::vector]"),
}
}
pub const fn register_displacement(self) -> (u8, i16) {
match self {
Self::RegisterDisplacement(r, d) => (r, d),
_ => panic!("[Operands::register_displacement]"),
}
}
pub const fn register(self) -> u8 {
match self {
Self::Register(r) => r,
_ => panic!("[Operands::register]"),
}
}
pub const fn direction_register(self) -> (Direction, u8) {
match self {
Self::DirectionRegister(d, r) => (d, r),
_ => panic!("[Operands::direction_register]"),
}
}
pub const fn direction_size_effective_address_list(self) -> (Direction, Size, AddressingMode, u16) {
match self {
Self::DirectionSizeEffectiveAddressList(d, s, e, l) => (d, s, e, l),
_ => panic!("[Operands::direction_size_effective_address_list]"),
}
}
pub const fn data_size_effective_address(self) -> (u8, Size, AddressingMode) {
match self {
Self::DataSizeEffectiveAddress(d, s, e) => (d, s, e),
_ => panic!("[Operands::data_size_effective_address]"),
}
}
pub const fn condition_effective_address(self) -> (u8, AddressingMode) {
match self {
Self::ConditionEffectiveAddress(c, e) => (c, e),
_ => panic!("[Operands::condition_effective_address]"),
}
}
pub const fn condition_register_displacement(self) -> (u8, u8, i16) {
match self {
Self::ConditionRegisterDisplacement(c, r, d) => (c, r, d),
_ => panic!("[Operands::condition_register_displacement]"),
}
}
pub const fn displacement(self) -> i16 {
match self {
Self::Displacement(d) => d,
_ => panic!("[Operands::displacement]"),
}
}
pub const fn condition_displacement(self) -> (u8, i16) {
match self {
Self::ConditionDisplacement(c, d) => (c, d),
_ => panic!("[Operands::condition_displacement]"),
}
}
pub const fn register_data(self) -> (u8, i8) {
match self {
Self::RegisterData(r, d) => (r, d),
_ => panic!("[Operands::register_data]"),
}
}
pub const fn register_direction_size_effective_address(self) -> (u8, Direction, Size, AddressingMode) {
match self {
Self::RegisterDirectionSizeEffectiveAddress(r, d, s, e) => (r, d, s, e),
_ => panic!("[Operands::register_direction_size_effective_address]"),
}
}
pub const fn register_size_effective_address(self) -> (u8, Size, AddressingMode) {
match self {
Self::RegisterSizeEffectiveAddress(r, s, e) => (r, s, e),
_ => panic!("[Operands::register_size_effective_address]"),
}
}
pub const fn register_size_mode_register(self) -> (u8, Size, Direction, u8) {
match self {
Self::RegisterSizeModeRegister(r, s, m, rr) => (r, s, m, rr),
_ => panic!("[Operands::register_size_mode_register]"),
}
}
pub const fn register_size_register(self) -> (u8, Size, u8) {
match self {
Self::RegisterSizeRegister(r, s, rr) => (r, s, rr),
_ => panic!("[Operands::register_size_register]"),
}
}
pub const fn direction_effective_address(self) -> (Direction, AddressingMode) {
match self {
Self::DirectionEffectiveAddress(d, e) => (d, e),
_ => panic!("[Operands::direction_effective_address]"),
}
}
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]"),
}
}
pub fn new_no_operands<M: MemoryAccess + ?Sized>(_: u16, _: &mut MemoryIter<M>) -> Self {
Self::NoOperands
}
pub fn new_immediate<M: MemoryAccess + ?Sized>(_: u16, memory: &mut MemoryIter<M>) -> Self {
Self::Immediate(immediate(memory))
}
pub fn new_size_effective_address_immediate<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (size, am, imm) = size_effective_address_immediate(opcode, memory);
Self::SizeEffectiveAddressImmediate(size, am, imm)
}
pub fn new_effective_address_count<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (am, count) = effective_address_count(opcode, memory);
Self::EffectiveAddressCount(am, count)
}
pub fn new_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
Self::EffectiveAddress(effective_address(opcode, memory))
}
pub fn new_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (size, am) = size_effective_address(opcode, memory);
Self::SizeEffectiveAddress(size, am)
}
pub fn new_register_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (reg, am) = register_effective_address(opcode, memory);
Self::RegisterEffectiveAddress(reg, am)
}
pub fn new_register_direction_size_register_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (dreg, dir, size, areg, disp) = register_direction_size_register_displacement(opcode, memory);
Self::RegisterDirectionSizeRegisterDisplacement(dreg, dir, size, areg, disp)
}
pub fn new_size_register_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (size, areg, am) = size_register_effective_address(opcode, memory);
Self::SizeRegisterEffectiveAddress(size, areg, am)
}
pub fn new_size_effective_address_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (size, dst, src) = size_effective_address_effective_address(opcode, memory);
Self::SizeEffectiveAddressEffectiveAddress(size, dst, src)
}
pub fn new_register_opmode_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (regl, dir, regr) = register_opmode_register(opcode);
Self::RegisterOpmodeRegister(regl, dir, regr)
}
pub fn new_opmode_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (opmode, reg) = opmode_register(opcode);
Self::OpmodeRegister(opmode, reg)
}
pub fn new_vector<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
Self::Vector(vector(opcode))
}
pub fn new_register_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (reg, disp) = register_displacement(opcode, memory);
Self::RegisterDisplacement(reg, disp)
}
pub fn new_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
Self::Register(register(opcode))
}
pub fn new_direction_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (dir, reg) = direction_register(opcode);
Self::DirectionRegister(dir, reg)
}
pub fn new_direction_size_effective_address_list<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (dir, size, am, list) = direction_size_effective_address_list(opcode, memory);
Self::DirectionSizeEffectiveAddressList(dir, size, am, list)
}
pub fn new_data_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (data, size, am) = data_size_effective_address(opcode, memory);
Self::DataSizeEffectiveAddress(data, size, am)
}
pub fn new_condition_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (condition, am) = condition_effective_address(opcode, memory);
Self::ConditionEffectiveAddress(condition, am)
}
pub fn new_condition_register_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (condition, reg, disp) = condition_register_displacement(opcode, memory);
Self::ConditionRegisterDisplacement(condition, reg, disp)
}
pub fn new_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
Self::Displacement(displacement(opcode, memory))
}
pub fn new_condition_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (condition, disp) = condition_displacement(opcode, memory);
Self::ConditionDisplacement(condition, disp)
}
pub fn new_register_data<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (reg, data) = register_data(opcode);
Self::RegisterData(reg, data)
}
pub fn new_register_direction_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (reg, dir, size, am) = register_direction_size_effective_address(opcode, memory);
Self::RegisterDirectionSizeEffectiveAddress(reg, dir, size, am)
}
pub fn new_register_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (reg, size, am) = register_size_effective_address(opcode, memory);
Self::RegisterSizeEffectiveAddress(reg, size, am)
}
pub fn new_register_size_mode_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (regl, size, mode, regr) = register_size_mode_register(opcode);
Self::RegisterSizeModeRegister(regl, size, mode, regr)
}
pub fn new_register_size_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (regl, size, regr) = register_size_register(opcode);
Self::RegisterSizeRegister(regl, size, regr)
}
pub fn new_direction_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> Self {
let (dir, am) = direction_effective_address(opcode, memory);
Self::DirectionEffectiveAddress(dir, am)
}
pub fn new_rotation_direction_size_mode_register<M: MemoryAccess + ?Sized>(opcode: u16, _: &mut MemoryIter<M>) -> Self {
let (count, dir, size, mode, reg) = rotation_direction_size_mode_register(opcode);
Self::RotationDirectionSizeModeRegister(count, dir, size, mode, reg)
}
}
pub fn immediate<M: MemoryAccess + ?Sized>(memory: &mut MemoryIter<M>) -> u16 {
memory.next().unwrap().expect("Access error occured when fetching immediate operand.")
}
pub fn size_effective_address_immediate<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (Size, AddressingMode, u32) {
let size = Size::from(bits(opcode, 6, 7));
let imm = if size.is_long() {
let high = memory.next().unwrap().expect("Access error occured when fetching immediate operand high.");
let low = memory.next().unwrap().expect("Access error occured when fetching immediate operand low.");
(high as u32) << 16 | low as u32
} else {
memory.next().unwrap().expect("Access error occured when fetching immediate operand.") as u32
};
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(size, am, imm)
}
pub fn effective_address_count<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (AddressingMode, u8) {
let count = if bit(opcode, 8) { bits(opcode, 9, 11) as u8
} else { memory.next().unwrap().expect("Access error occured when fetching count operand.") as u8
};
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let size = if eamode == 0 { Some(Size::Long) } else { Some(Size::Byte) };
let am = AddressingMode::from_memory(eamode, eareg, size, memory);
(am, count)
}
pub fn effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> AddressingMode {
let isa = DECODER[opcode as usize];
let size = if isa == Isa::Nbcd || isa == Isa::Tas {
Some(Size::Byte)
} else if isa == Isa::Moveccr || isa == Isa::Movefsr || isa == Isa::Movesr {
Some(Size::Word)
} else if isa == Isa::Pea {
Some(Size::Long)
} else {
None
};
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
AddressingMode::from_memory(eamode, eareg, size, memory)
}
pub fn size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (Size, AddressingMode) {
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let size = Size::from(bits(opcode, 6, 7));
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(size, am)
}
pub fn register_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, AddressingMode) {
let isa = DECODER[opcode as usize];
let reg = bits(opcode, 9, 11) as u8;
let size = if isa == Isa::Lea {
Some(Size::Long)
} else {
Some(Size::Word)
};
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let am = AddressingMode::from_memory(eamode, eareg, size, memory);
(reg, am)
}
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 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;
(dreg, dir, size, areg, disp)
}
pub fn size_register_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (Size, u8, AddressingMode) {
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let areg = bits(opcode, 9, 11) as u8;
let size = Size::from_move(bits(opcode, 12, 13));
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(size, areg, am)
}
pub fn size_effective_address_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (Size, AddressingMode, AddressingMode) {
let size = Size::from_move(bits(opcode, 12, 13));
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let src = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
let eamode = bits(opcode, 6, 8);
let eareg = bits(opcode, 9, 11) as u8;
let dst = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(size, dst, src)
}
pub fn register_opmode_register(opcode: u16) -> (u8, Direction, u8) {
let regl = bits(opcode, 9, 11) as u8;
let opmode = bits(opcode, 3, 7) as u8;
let regr = bits(opcode, 0, 2) as u8;
let dir = if opmode == 0b01000 {
Direction::ExchangeData
} else if opmode == 0b01001 {
Direction::ExchangeAddress
} else {
Direction::ExchangeDataAddress
};
(regl, dir, regr)
}
pub fn opmode_register(opcode: u16) -> (u8, u8) {
let opmode = bits(opcode, 6, 8) as u8;
let reg = bits(opcode, 0, 2) as u8;
(opmode, reg)
}
pub fn vector(opcode: u16) -> u8 {
bits(opcode, 0, 3) as u8
}
pub fn register_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, i16) {
let reg = bits(opcode, 0, 2) as u8;
let disp = memory.next().unwrap().expect("Access error occured when fetching displacement operand.") as i16;
(reg, disp)
}
pub fn register(opcode: u16) -> u8 {
bits(opcode, 0, 2) as u8
}
pub fn direction_register(opcode: u16) -> (Direction, u8) {
let dir = if bit(opcode, 3) { Direction::UspToRegister } else { Direction::RegisterToUsp };
let reg = bits(opcode, 0, 2) as u8;
(dir, reg)
}
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 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);
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(dir, size, am, list)
}
pub fn data_size_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, Size, AddressingMode) {
let data = bits(opcode, 9, 11) as u8;
let size = Size::from(bits(opcode, 6, 7));
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(data, size, am)
}
pub fn condition_effective_address<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, AddressingMode) {
let condition = bits(opcode, 8, 11) as u8;
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let am = AddressingMode::from_memory(eamode, eareg, Some(Size::Byte), memory);
(condition, am)
}
pub fn condition_register_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, u8, i16) {
let disp = memory.next().unwrap().expect("Access error occured when fetching displacement operand.") as i16;
let condition = bits(opcode, 8, 11) as u8;
let reg = bits(opcode, 0, 2) as u8;
(condition, reg, disp)
}
pub fn displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> i16 {
let mut disp = opcode as i8 as i16;
if disp == 0 {
disp = memory.next().unwrap().expect("Access error occured when fetching displacement operand.") as i16;
}
disp
}
pub fn condition_displacement<M: MemoryAccess + ?Sized>(opcode: u16, memory: &mut MemoryIter<M>) -> (u8, i16) {
let mut disp = opcode as i8 as i16;
if disp == 0 {
disp = memory.next().unwrap().expect("Access error occured when fetching displacement operand.") as i16;
}
let condition = bits(opcode, 8, 11) as u8;
(condition, disp)
}
pub fn register_data(opcode: u16) -> (u8, i8) {
let reg = bits(opcode, 9, 11) as u8;
let data = opcode as i8;
(reg, data)
}
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 bit(opcode, 8) { Direction::DstEa } else { Direction::DstReg }; let size = Size::from(bits(opcode, 6, 7));
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(reg, dir, size, am)
}
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(bit(opcode, 8));
let eareg = bits(opcode, 0, 2) as u8;
let eamode = bits(opcode, 3, 5);
let am = AddressingMode::from_memory(eamode, eareg, Some(size), memory);
(reg, size, am)
}
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 bit(opcode, 3) { Direction::MemoryToMemory } else { Direction::RegisterToRegister };
let regr = bits(opcode, 0, 2) as u8;
(regl, size, mode, regr)
}
pub fn register_size_register(opcode: u16) -> (u8, Size, u8) {
let regl = bits(opcode, 9, 11) as u8;
let size = Size::from(bits(opcode, 6, 7));
let regr = bits(opcode, 0, 2) as u8;
(regl, size, regr)
}
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 bit(opcode, 8) { Direction::Left } else { Direction::Right };
let am = AddressingMode::from_memory(eamode, eareg, Some(Size::Byte), memory);
(dir, am)
}
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 bit(opcode, 8) { Direction::Left } else { Direction::Right };
let size = Size::from(bits(opcode, 6, 7));
let mode = bit(opcode, 5);
let reg = bits(opcode, 0, 2) as u8;
(count, dir, size, mode, reg)
}