From bc4f63baf3887e7b7ffb8cf5408007e540c2509a Mon Sep 17 00:00:00 2001 From: transistor Date: Sat, 25 Mar 2023 16:06:03 -0700 Subject: [PATCH] Refactored m68k decode --- emulator/cpus/m68k/src/decode.rs | 1059 ++++++++++++++++-------------- 1 file changed, 548 insertions(+), 511 deletions(-) diff --git a/emulator/cpus/m68k/src/decode.rs b/emulator/cpus/m68k/src/decode.rs index dcb28a1..5ccc0bb 100644 --- a/emulator/cpus/m68k/src/decode.rs +++ b/emulator/cpus/m68k/src/decode.rs @@ -74,536 +74,573 @@ impl M68kDecoder { self.instruction_word = ins; match ((ins & 0xF000) >> 12) as u8 { - OPCG_BIT_OPS => { - let optype = (ins & 0x0F00) >> 8; + OPCG_BIT_OPS => self.decode_group_bit_ops(memory, ins), + OPCG_MOVE_BYTE => self.decode_group_move_byte(memory, ins), + OPCG_MOVE_LONG => self.decode_group_move_long(memory, ins), + OPCG_MOVE_WORD => self.decode_group_move_word(memory, ins), + OPCG_MISC => self.decode_group_misc(memory, ins), + OPCG_ADDQ_SUBQ => self.decode_group_addq_subq(memory, ins), + OPCG_BRANCH => self.decode_group_branch(memory, ins), + OPCG_MOVEQ => self.decode_group_moveq(memory, ins), + OPCG_DIV_OR => self.decode_group_div_or(memory, ins), + OPCG_SUB => self.decode_group_sub(memory, ins), + OPCG_ALINE => Ok(Instruction::UnimplementedA(ins)), + OPCG_CMP_EOR => self.decode_group_cmp_eor(memory, ins), + OPCG_MUL_AND => self.decode_group_mul_and(memory, ins), + OPCG_ADD => self.decode_group_add(memory, ins), + OPCG_SHIFT => self.decode_group_shift(memory, ins), + OPCG_FLINE => Ok(Instruction::UnimplementedF(ins)), + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } - if (ins & 0x13F) == 0x03C { - match (ins & 0x00C0) >> 6 { - 0b00 => { - let data = self.read_instruction_word(memory)?; - match optype { - 0b0000 => Ok(Instruction::ORtoCCR(data as u8)), - 0b0010 => Ok(Instruction::ANDtoCCR(data as u8)), - 0b1010 => Ok(Instruction::EORtoCCR(data as u8)), - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - }, - 0b01 => { - let data = self.read_instruction_word(memory)?; - match optype { - 0b0000 => Ok(Instruction::ORtoSR(data)), - 0b0010 => Ok(Instruction::ANDtoSR(data)), - 0b1010 => Ok(Instruction::EORtoSR(data)), - _ => 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); - let areg = get_low_reg(ins); - let dir = if (ins & 0x0080) == 0 { Direction::FromTarget } else { Direction::ToTarget }; - let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; - let offset = self.read_instruction_word(memory)? as i16; - Ok(Instruction::MOVEP(dreg, areg, offset, size, dir)) - } else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 { - let bitnum = if (ins & 0x0100) == 0x0100 { - Target::DirectDReg(get_high_reg(ins)) - } else { - Target::Immediate(self.read_instruction_word(memory)? as u32) - }; - - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; - let size = match target { - Target::DirectAReg(_) | Target::DirectDReg(_) => Size::Long, - _ => Size::Byte, - }; - - match (ins & 0x00C0) >> 6 { - 0b00 => Ok(Instruction::BTST(bitnum, target, size)), - 0b01 => Ok(Instruction::BCHG(bitnum, target, size)), - 0b10 => Ok(Instruction::BCLR(bitnum, target, size)), - 0b11 => Ok(Instruction::BSET(bitnum, target, size)), - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - } else { - let size = get_size(ins); - let data = match size { - Some(Size::Byte) => self.read_instruction_word(memory)? as u32 & 0xFF, - Some(Size::Word) => self.read_instruction_word(memory)? as u32, - Some(Size::Long) => self.read_instruction_long(memory)?, - None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), - }; - let target = self.decode_lower_effective_address(memory, ins, size)?; + #[inline] + fn decode_group_bit_ops(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let optype = (ins & 0x0F00) >> 8; + if (ins & 0x13F) == 0x03C { + match (ins & 0x00C0) >> 6 { + 0b00 => { + let data = self.read_instruction_word(memory)?; match optype { - 0b0000 => Ok(Instruction::OR(Target::Immediate(data), target, size.unwrap())), - 0b0010 => Ok(Instruction::AND(Target::Immediate(data), target, size.unwrap())), - 0b0100 => Ok(Instruction::SUB(Target::Immediate(data), target, size.unwrap())), - 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())), + 0b0000 => Ok(Instruction::ORtoCCR(data as u8)), + 0b0010 => Ok(Instruction::ANDtoCCR(data as u8)), + 0b1010 => Ok(Instruction::EORtoCCR(data as u8)), _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), } - } - }, - OPCG_MOVE_BYTE => { - let src = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; - let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Byte))?; - Ok(Instruction::MOVE(src, dest, Size::Byte)) - }, - OPCG_MOVE_LONG => { - let src = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?; - let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Long))?; - if let Target::DirectAReg(reg) = dest { - Ok(Instruction::MOVEA(src, reg, Size::Long)) - } else { - Ok(Instruction::MOVE(src, dest, Size::Long)) - } - }, - OPCG_MOVE_WORD => { - let src = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; - let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Word))?; - if let Target::DirectAReg(reg) = dest { - Ok(Instruction::MOVEA(src, reg, Size::Word)) - } else { - Ok(Instruction::MOVE(src, dest, Size::Word)) - } - }, - OPCG_MISC => { - let ins_0f00 = ins & 0xF00; - let ins_00f0 = ins & 0x0F0; + }, + 0b01 => { + let data = self.read_instruction_word(memory)?; + match optype { + 0b0000 => Ok(Instruction::ORtoSR(data)), + 0b0010 => Ok(Instruction::ANDtoSR(data)), + 0b1010 => Ok(Instruction::EORtoSR(data)), + _ => 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); + let areg = get_low_reg(ins); + let dir = if (ins & 0x0080) == 0 { Direction::FromTarget } else { Direction::ToTarget }; + let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; + let offset = self.read_instruction_word(memory)? as i16; + Ok(Instruction::MOVEP(dreg, areg, offset, size, dir)) + } else if (ins & 0x0100) == 0x0100 || (ins & 0x0F00) == 0x0800 { + let bitnum = if (ins & 0x0100) == 0x0100 { + Target::DirectDReg(get_high_reg(ins)) + } else { + Target::Immediate(self.read_instruction_word(memory)? as u32) + }; - if (ins & 0x180) == 0x180 { - if (ins & 0x040) == 0 { - let size = match get_size(ins) { - Some(Size::Word) => Size::Word, - Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long, - // On the 68000, long words in CHK are not supported, but the opcode maps to the word size instruction - Some(Size::Long) => Size::Word, + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + let size = match target { + Target::DirectAReg(_) | Target::DirectDReg(_) => Size::Long, + _ => Size::Byte, + }; + + match (ins & 0x00C0) >> 6 { + 0b00 => Ok(Instruction::BTST(bitnum, target, size)), + 0b01 => Ok(Instruction::BCHG(bitnum, target, size)), + 0b10 => Ok(Instruction::BCLR(bitnum, target, size)), + 0b11 => Ok(Instruction::BSET(bitnum, target, size)), + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } else { + let size = get_size(ins); + let data = match size { + Some(Size::Byte) => self.read_instruction_word(memory)? as u32 & 0xFF, + Some(Size::Word) => self.read_instruction_word(memory)? as u32, + Some(Size::Long) => self.read_instruction_long(memory)?, + None => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), + }; + let target = self.decode_lower_effective_address(memory, ins, size)?; + + match optype { + 0b0000 => Ok(Instruction::OR(Target::Immediate(data), target, size.unwrap())), + 0b0010 => Ok(Instruction::AND(Target::Immediate(data), target, size.unwrap())), + 0b0100 => Ok(Instruction::SUB(Target::Immediate(data), target, size.unwrap())), + 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())), + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } + } + + #[inline] + fn decode_group_move_byte(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let src = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Byte))?; + Ok(Instruction::MOVE(src, dest, Size::Byte)) + } + + #[inline] + fn decode_group_move_long(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let src = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?; + let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Long))?; + if let Target::DirectAReg(reg) = dest { + Ok(Instruction::MOVEA(src, reg, Size::Long)) + } else { + Ok(Instruction::MOVE(src, dest, Size::Long)) + } + } + + #[inline] + fn decode_group_move_word(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let src = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let dest = self.decode_upper_effective_address(memory, ins, Some(Size::Word))?; + if let Target::DirectAReg(reg) = dest { + Ok(Instruction::MOVEA(src, reg, Size::Word)) + } else { + Ok(Instruction::MOVE(src, dest, Size::Word)) + } + } + + #[inline] + fn decode_group_misc(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let ins_0f00 = ins & 0xF00; + let ins_00f0 = ins & 0x0F0; + + if (ins & 0x180) == 0x180 { + if (ins & 0x040) == 0 { + let size = match get_size(ins) { + Some(Size::Word) => Size::Word, + Some(Size::Long) if self.cputype >= M68kType::MC68020 => Size::Long, + // On the 68000, long words in CHK are not supported, but the opcode maps to the word size instruction + Some(Size::Long) => Size::Word, + _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), + }; + + let reg = get_high_reg(ins); + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + Ok(Instruction::CHK(target, reg, size)) + } else { + let src = self.decode_lower_effective_address(memory, ins, None)?; + let dest = get_high_reg(ins); + Ok(Instruction::LEA(src, dest)) + } + } else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 { + let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; + let data = self.read_instruction_word(memory)?; + let target = self.decode_lower_effective_address(memory, ins, None)?; + let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget }; + Ok(Instruction::MOVEM(target, size, dir, data)) + } else if (ins & 0xF80) == 0xC00 && self.cputype >= M68kType::MC68020 { + let extension = self.read_instruction_word(memory)?; + let reg_h = if (extension & 0x0400) != 0 { Some(get_low_reg(ins)) } else { None }; + let reg_l = ((extension & 0x7000) >> 12) as u8; + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?; + let sign = if (ins & 0x0800) == 0 { Sign::Unsigned } else { Sign::Signed }; + match (ins & 0x040) == 0 { + true => Ok(Instruction::MULL(target, reg_h, reg_l, sign)), + false => Ok(Instruction::DIVL(target, reg_h, reg_l, sign)), + } + } else if (ins & 0x800) == 0 { + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + match (ins & 0x0700) >> 8 { + 0b000 => { + match get_size(ins) { + Some(size) => Ok(Instruction::NEGX(target, size)), + None => Ok(Instruction::MOVEfromSR(target)), + } + }, + 0b010 => { + match get_size(ins) { + Some(size) => Ok(Instruction::CLR(target, size)), + None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)), + None => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + }, + 0b100 => { + match get_size(ins) { + Some(size) => Ok(Instruction::NEG(target, size)), + None => Ok(Instruction::MOVEtoCCR(target)), + } + }, + 0b110 => { + match get_size(ins) { + Some(size) => Ok(Instruction::NOT(target, size)), + None => Ok(Instruction::MOVEtoSR(target)), + } + }, + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } else if ins_0f00 == 0x800 || ins_0f00 == 0x900 { + let opmode = (ins & 0x01C0) >> 6; + let mode = get_low_mode(ins); + match (opmode, mode) { + (0b000, 0b001) if self.cputype >= M68kType::MC68020 => { + let data = self.read_instruction_long(memory)? as i32; + Ok(Instruction::LINK(get_low_reg(ins), data)) + }, + (0b000, _) => { + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + Ok(Instruction::NBCD(target)) + }, + (0b001, 0b000) => { + Ok(Instruction::SWAP(get_low_reg(ins))) + }, + (0b001, 0b001) => { + Ok(Instruction::BKPT(get_low_reg(ins))) + }, + (0b001, _) => { + let target = self.decode_lower_effective_address(memory, ins, None)?; + Ok(Instruction::PEA(target)) + }, + (0b010, 0b000) => { + Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Word)) + }, + (0b011, 0b000) => { + Ok(Instruction::EXT(get_low_reg(ins), Size::Word, Size::Long)) + }, + (0b111, 0b000) => { + Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long)) + }, + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } else if ins_0f00 == 0xA00 { + if (ins & 0x0FF) == 0xFC { + Ok(Instruction::ILLEGAL) + } else { + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + match get_size(ins) { + Some(size) => Ok(Instruction::TST(target, size)), + None => Ok(Instruction::TAS(target)), + } + } + } else if ins_0f00 == 0xE00 { + if (ins & 0x80) == 0x80 { + let target = self.decode_lower_effective_address(memory, ins, None)?; + if (ins & 0b01000000) == 0 { + Ok(Instruction::JSR(target)) + } else { + Ok(Instruction::JMP(target)) + } + } else if ins_00f0 == 0x40 { + Ok(Instruction::TRAP((ins & 0x000F) as u8)) + } else if ins_00f0 == 0x50 { + let reg = get_low_reg(ins); + if (ins & 0b1000) == 0 { + let data = (self.read_instruction_word(memory)? as i16) as i32; + Ok(Instruction::LINK(reg, data)) + } else { + Ok(Instruction::UNLK(reg)) + } + } else if ins_00f0 == 0x60 { + let reg = get_low_reg(ins); + let dir = if (ins & 0b1000) == 0 { Direction::FromTarget } else { Direction::ToTarget }; + Ok(Instruction::MOVEUSP(Target::DirectAReg(reg), dir)) + } else { + match ins & 0x00FF { + 0x70 => Ok(Instruction::RESET), + 0x71 => Ok(Instruction::NOP), + 0x72 => { + let data = self.read_instruction_word(memory)?; + Ok(Instruction::STOP(data)) + }, + 0x73 => Ok(Instruction::RTE), + 0x74 if self.cputype >= M68kType::MC68010 => { + let offset = self.read_instruction_word(memory)? as i16; + Ok(Instruction::RTD(offset)) + }, + 0x75 => Ok(Instruction::RTS), + 0x76 => Ok(Instruction::TRAPV), + 0x77 => Ok(Instruction::RTR), + 0x7A | 0x7B if self.cputype >= M68kType::MC68010 => { + let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget }; + let ins2 = self.read_instruction_word(memory)?; + let target = match ins2 & 0x8000 { + 0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8), + _ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8), + }; + let creg = match ins2 & 0xFFF { + 0x801 => ControlRegister::VBR, _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), }; + Ok(Instruction::MOVEC(target, creg, dir)) + }, + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } + } else { + Err(Error::processor(Exceptions::IllegalInstruction as u32)) + } + } - let reg = get_high_reg(ins); - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - Ok(Instruction::CHK(target, reg, size)) + #[inline] + fn decode_group_addq_subq(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + match get_size(ins) { + Some(size) => { + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + let mut data = ((ins & 0x0E00) >> 9) as u32; + if data == 0 { + data = 8; + } + + if let Target::DirectAReg(reg) = target { + if (ins & 0x0100) == 0 { + Ok(Instruction::ADDA(Target::Immediate(data), reg, size)) } else { - let src = self.decode_lower_effective_address(memory, ins, None)?; - let dest = get_high_reg(ins); - Ok(Instruction::LEA(src, dest)) + Ok(Instruction::SUBA(Target::Immediate(data), reg, size)) } - } else if (ins & 0xB80) == 0x880 && (ins & 0x038) != 0 { - let size = if (ins & 0x0040) == 0 { Size::Word } else { Size::Long }; - let data = self.read_instruction_word(memory)?; - let target = self.decode_lower_effective_address(memory, ins, None)?; - let dir = if (ins & 0x0400) == 0 { Direction::ToTarget } else { Direction::FromTarget }; - Ok(Instruction::MOVEM(target, size, dir, data)) - } else if (ins & 0xF80) == 0xC00 && self.cputype >= M68kType::MC68020 { - let extension = self.read_instruction_word(memory)?; - let reg_h = if (extension & 0x0400) != 0 { Some(get_low_reg(ins)) } else { None }; - let reg_l = ((extension & 0x7000) >> 12) as u8; - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Long))?; - let sign = if (ins & 0x0800) == 0 { Sign::Unsigned } else { Sign::Signed }; - match (ins & 0x040) == 0 { - true => Ok(Instruction::MULL(target, reg_h, reg_l, sign)), - false => Ok(Instruction::DIVL(target, reg_h, reg_l, sign)), + } else if (ins & 0x0100) == 0 { + Ok(Instruction::ADD(Target::Immediate(data), target, size)) + } else { + Ok(Instruction::SUB(Target::Immediate(data), target, size)) + } + }, + None => { + let mode = get_low_mode(ins); + let condition = get_condition(ins); + + if mode == 0b001 { + let reg = get_low_reg(ins); + let disp = self.read_instruction_word(memory)? as i16; + Ok(Instruction::DBcc(condition, reg, disp)) + } else { + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; + Ok(Instruction::Scc(condition, target)) + } + }, + } + } + + #[inline] + fn decode_group_branch(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let mut disp = ((ins & 0xFF) as i8) as i32; + if disp == 0 { + disp = (self.read_instruction_word(memory)? as i16) as i32; + } else if disp == -1 && self.cputype >= M68kType::MC68020 { + disp = self.read_instruction_long(memory)? as i32; + } + let condition = get_condition(ins); + match condition { + Condition::True => Ok(Instruction::BRA(disp)), + Condition::False => Ok(Instruction::BSR(disp)), + _ => Ok(Instruction::Bcc(condition, disp)), + } + } + + #[inline] + fn decode_group_moveq(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + if (ins & 0x0100) != 0 { + return Err(Error::processor(Exceptions::IllegalInstruction as u32)); + } + let reg = get_high_reg(ins); + let data = (ins & 0xFF) as u8; + Ok(Instruction::MOVEQ(data, reg)) + } + + #[inline] + fn decode_group_div_or(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let size = get_size(ins); + + if (ins & 0x1F0) == 0x100 { + let regx = get_high_reg(ins); + let regy = get_low_reg(ins); + + match (ins & 0x08) != 0 { + false => Ok(Instruction::SBCD(Target::DirectDReg(regy), Target::DirectDReg(regx))), + true => Ok(Instruction::SBCD(Target::IndirectARegDec(regy), Target::IndirectARegDec(regx))), + } + } 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::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)) + } + } + + #[inline] + fn decode_group_sub(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let reg = get_high_reg(ins); + let dir = (ins & 0x0100) >> 8; + let size = get_size(ins); + match size { + Some(size) => { + if (ins & 0b100110000) == 0b100000000 { + let src = get_low_reg(ins); + let dest = get_high_reg(ins); + match (ins & 0x08) == 0 { + true => Ok(Instruction::SUBX(Target::DirectDReg(src), Target::DirectDReg(dest), size)), + false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), } - } else if (ins & 0x800) == 0 { + } else { + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + if dir == 0 { + Ok(Instruction::SUB(target, Target::DirectDReg(reg), size)) + } else { + Ok(Instruction::SUB(Target::DirectDReg(reg), target, size)) + } + } + }, + None => { + let size = if dir == 0 { Size::Word } else { Size::Long }; + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + Ok(Instruction::SUBA(target, reg, size)) + }, + } + } + + #[inline] + fn decode_group_cmp_eor(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let reg = get_high_reg(ins); + let optype = (ins & 0x0100) >> 8; + let size = get_size(ins); + match (optype, size) { + (0b1, Some(size)) => { + if get_low_mode(ins) == 0b001 { + Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size)) + } else { + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + Ok(Instruction::EOR(Target::DirectDReg(reg), target, size)) + } + }, + (0b0, Some(size)) => { + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + Ok(Instruction::CMP(target, Target::DirectDReg(reg), size)) + }, + (_, None) => { + let size = if optype == 0 { Size::Word } else { Size::Long }; + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + Ok(Instruction::CMPA(target, reg, size)) + }, + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } + + #[inline] + fn decode_group_mul_and(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let size = get_size(ins); + + if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 { + let regx = get_high_reg(ins); + let regy = get_low_reg(ins); + + match (ins & 0x08) != 0 { + 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_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))), + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } 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)) + } + } + + #[inline] + fn decode_group_add(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let reg = get_high_reg(ins); + let dir = (ins & 0x0100) >> 8; + let size = get_size(ins); + match size { + Some(size) => { + if (ins & 0b100110000) == 0b100000000 { + let src = get_low_reg(ins); + let dest = get_high_reg(ins); + match (ins & 0x08) == 0 { + true => Ok(Instruction::ADDX(Target::DirectDReg(src), Target::DirectDReg(dest), size)), + false => Ok(Instruction::ADDX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), + } + } else { + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + if dir == 0 { + Ok(Instruction::ADD(target, Target::DirectDReg(reg), size)) + } else { + Ok(Instruction::ADD(Target::DirectDReg(reg), target, size)) + } + } + }, + None => { + let size = if dir == 0 { Size::Word } else { Size::Long }; + let target = self.decode_lower_effective_address(memory, ins, Some(size))?; + Ok(Instruction::ADDA(target, reg, size)) + }, + } + } + + fn decode_group_shift(&mut self, memory: &mut dyn Addressable, ins: u16) -> Result { + let dir = if (ins & 0x0100) == 0 { ShiftDirection::Right } else { ShiftDirection::Left }; + match get_size(ins) { + Some(size) => { + let reg = get_low_reg(ins); + let rotation = get_high_reg(ins); + let count = if (ins & 0x0020) == 0 { + Target::Immediate(if rotation != 0 { rotation as u32 } else { 8 }) + } else { + Target::DirectDReg(rotation) + }; + + match (ins & 0x0018) >> 3 { + 0b00 => Ok(Instruction::ASd(count, Target::DirectDReg(reg), size, dir)), + 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)), + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + }, + None => { + if (ins & 0x800) == 0 { + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; + let count = Target::Immediate(1); + match (ins & 0x0600) >> 9 { + 0b00 => Ok(Instruction::ASd(count, target, Size::Word, dir)), + 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)), + _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), + } + } else if self.cputype > M68kType::MC68020 { + // Bitfield instructions (MC68020+) + let ext = self.read_instruction_word(memory)?; + let reg = ((ext & 0x7000) >> 12) as u8; + + let offset = match (ext & 0x0800) == 0 { + true => RegOrImmediate::Immediate(((ext & 0x07C0) >> 6) as u8), + false => RegOrImmediate::DReg(((ext & 0x01C0) >> 6) as u8), + }; + + let width = match (ext & 0x0020) == 0 { + true => RegOrImmediate::Immediate((ext & 0x001F) as u8), + false => RegOrImmediate::DReg((ext & 0x0007) as u8), + }; + let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; match (ins & 0x0700) >> 8 { - 0b000 => { - match get_size(ins) { - Some(size) => Ok(Instruction::NEGX(target, size)), - None => Ok(Instruction::MOVEfromSR(target)), - } - }, - 0b010 => { - match get_size(ins) { - Some(size) => Ok(Instruction::CLR(target, size)), - None if self.cputype >= M68kType::MC68010 => Ok(Instruction::MOVEfromCCR(target)), - None => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - }, - 0b100 => { - match get_size(ins) { - Some(size) => Ok(Instruction::NEG(target, size)), - None => Ok(Instruction::MOVEtoCCR(target)), - } - }, - 0b110 => { - match get_size(ins) { - Some(size) => Ok(Instruction::NOT(target, size)), - None => Ok(Instruction::MOVEtoSR(target)), - } - }, + 0b010 => Ok(Instruction::BFCHG(target, offset, width)), + 0b100 => Ok(Instruction::BFCLR(target, offset, width)), + 0b011 => Ok(Instruction::BFEXTS(target, offset, width, reg)), + 0b001 => Ok(Instruction::BFEXTU(target, offset, width, reg)), + 0b101 => Ok(Instruction::BFFFO(target, offset, width, reg)), + 0b111 => Ok(Instruction::BFINS(reg, target, offset, width)), + 0b110 => Ok(Instruction::BFSET(target, offset, width)), + 0b000 => Ok(Instruction::BFTST(target, offset, width)), _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), } - } else if ins_0f00 == 0x800 || ins_0f00 == 0x900 { - let opmode = (ins & 0x01C0) >> 6; - let mode = get_low_mode(ins); - match (opmode, mode) { - (0b000, 0b001) if self.cputype >= M68kType::MC68020 => { - let data = self.read_instruction_long(memory)? as i32; - Ok(Instruction::LINK(get_low_reg(ins), data)) - }, - (0b000, _) => { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; - Ok(Instruction::NBCD(target)) - }, - (0b001, 0b000) => { - Ok(Instruction::SWAP(get_low_reg(ins))) - }, - (0b001, 0b001) => { - Ok(Instruction::BKPT(get_low_reg(ins))) - }, - (0b001, _) => { - let target = self.decode_lower_effective_address(memory, ins, None)?; - Ok(Instruction::PEA(target)) - }, - (0b010, 0b000) => { - Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Word)) - }, - (0b011, 0b000) => { - Ok(Instruction::EXT(get_low_reg(ins), Size::Word, Size::Long)) - }, - (0b111, 0b000) => { - Ok(Instruction::EXT(get_low_reg(ins), Size::Byte, Size::Long)) - }, - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - } else if ins_0f00 == 0xA00 { - if (ins & 0x0FF) == 0xFC { - Ok(Instruction::ILLEGAL) - } else { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; - match get_size(ins) { - Some(size) => Ok(Instruction::TST(target, size)), - None => Ok(Instruction::TAS(target)), - } - } - } else if ins_0f00 == 0xE00 { - if (ins & 0x80) == 0x80 { - let target = self.decode_lower_effective_address(memory, ins, None)?; - if (ins & 0b01000000) == 0 { - Ok(Instruction::JSR(target)) - } else { - Ok(Instruction::JMP(target)) - } - } else if ins_00f0 == 0x40 { - Ok(Instruction::TRAP((ins & 0x000F) as u8)) - } else if ins_00f0 == 0x50 { - let reg = get_low_reg(ins); - if (ins & 0b1000) == 0 { - let data = (self.read_instruction_word(memory)? as i16) as i32; - Ok(Instruction::LINK(reg, data)) - } else { - Ok(Instruction::UNLK(reg)) - } - } else if ins_00f0 == 0x60 { - let reg = get_low_reg(ins); - let dir = if (ins & 0b1000) == 0 { Direction::FromTarget } else { Direction::ToTarget }; - Ok(Instruction::MOVEUSP(Target::DirectAReg(reg), dir)) - } else { - match ins & 0x00FF { - 0x70 => Ok(Instruction::RESET), - 0x71 => Ok(Instruction::NOP), - 0x72 => { - let data = self.read_instruction_word(memory)?; - Ok(Instruction::STOP(data)) - }, - 0x73 => Ok(Instruction::RTE), - 0x74 if self.cputype >= M68kType::MC68010 => { - let offset = self.read_instruction_word(memory)? as i16; - Ok(Instruction::RTD(offset)) - }, - 0x75 => Ok(Instruction::RTS), - 0x76 => Ok(Instruction::TRAPV), - 0x77 => Ok(Instruction::RTR), - 0x7A | 0x7B if self.cputype >= M68kType::MC68010 => { - let dir = if ins & 0x01 == 0 { Direction::ToTarget } else { Direction::FromTarget }; - let ins2 = self.read_instruction_word(memory)?; - let target = match ins2 & 0x8000 { - 0 => Target::DirectDReg(((ins2 & 0x7000) >> 12) as u8), - _ => Target::DirectAReg(((ins2 & 0x7000) >> 12) as u8), - }; - let creg = match ins2 & 0xFFF { - 0x801 => ControlRegister::VBR, - _ => return Err(Error::processor(Exceptions::IllegalInstruction as u32)), - }; - Ok(Instruction::MOVEC(target, creg, dir)) - }, - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - } } else { Err(Error::processor(Exceptions::IllegalInstruction as u32)) } }, - OPCG_ADDQ_SUBQ => { - match get_size(ins) { - Some(size) => { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - let mut data = ((ins & 0x0E00) >> 9) as u32; - if data == 0 { - data = 8; - } - - if let Target::DirectAReg(reg) = target { - if (ins & 0x0100) == 0 { - Ok(Instruction::ADDA(Target::Immediate(data), reg, size)) - } else { - Ok(Instruction::SUBA(Target::Immediate(data), reg, size)) - } - } else if (ins & 0x0100) == 0 { - Ok(Instruction::ADD(Target::Immediate(data), target, size)) - } else { - Ok(Instruction::SUB(Target::Immediate(data), target, size)) - } - }, - None => { - let mode = get_low_mode(ins); - let condition = get_condition(ins); - - if mode == 0b001 { - let reg = get_low_reg(ins); - let disp = self.read_instruction_word(memory)? as i16; - Ok(Instruction::DBcc(condition, reg, disp)) - } else { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Byte))?; - Ok(Instruction::Scc(condition, target)) - } - }, - } - }, - OPCG_BRANCH => { - let mut disp = ((ins & 0xFF) as i8) as i32; - if disp == 0 { - disp = (self.read_instruction_word(memory)? as i16) as i32; - } else if disp == -1 && self.cputype >= M68kType::MC68020 { - disp = self.read_instruction_long(memory)? as i32; - } - let condition = get_condition(ins); - match condition { - Condition::True => Ok(Instruction::BRA(disp)), - Condition::False => Ok(Instruction::BSR(disp)), - _ => Ok(Instruction::Bcc(condition, disp)), - } - }, - OPCG_MOVEQ => { - if (ins & 0x0100) != 0 { - return Err(Error::processor(Exceptions::IllegalInstruction as u32)); - } - let reg = get_high_reg(ins); - let data = (ins & 0xFF) as u8; - Ok(Instruction::MOVEQ(data, reg)) - }, - OPCG_DIV_OR => { - let size = get_size(ins); - - if (ins & 0x1F0) == 0x100 { - let regx = get_high_reg(ins); - let regy = get_low_reg(ins); - - match (ins & 0x08) != 0 { - false => Ok(Instruction::SBCD(Target::DirectDReg(regy), Target::DirectDReg(regx))), - true => Ok(Instruction::SBCD(Target::IndirectARegDec(regy), Target::IndirectARegDec(regx))), - } - } 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::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 => { - let reg = get_high_reg(ins); - let dir = (ins & 0x0100) >> 8; - let size = get_size(ins); - match size { - Some(size) => { - if (ins & 0b100110000) == 0b100000000 { - let src = get_low_reg(ins); - let dest = get_high_reg(ins); - match (ins & 0x08) == 0 { - true => Ok(Instruction::SUBX(Target::DirectDReg(src), Target::DirectDReg(dest), size)), - false => Ok(Instruction::SUBX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), - } - } else { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - if dir == 0 { - Ok(Instruction::SUB(target, Target::DirectDReg(reg), size)) - } else { - Ok(Instruction::SUB(Target::DirectDReg(reg), target, size)) - } - } - }, - None => { - let size = if dir == 0 { Size::Word } else { Size::Long }; - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - Ok(Instruction::SUBA(target, reg, size)) - }, - } - }, - OPCG_CMP_EOR => { - let reg = get_high_reg(ins); - let optype = (ins & 0x0100) >> 8; - let size = get_size(ins); - match (optype, size) { - (0b1, Some(size)) => { - if get_low_mode(ins) == 0b001 { - Ok(Instruction::CMP(Target::IndirectARegInc(get_low_reg(ins)), Target::IndirectARegInc(reg), size)) - } else { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - Ok(Instruction::EOR(Target::DirectDReg(reg), target, size)) - } - }, - (0b0, Some(size)) => { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - Ok(Instruction::CMP(target, Target::DirectDReg(reg), size)) - }, - (_, None) => { - let size = if optype == 0 { Size::Word } else { Size::Long }; - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - Ok(Instruction::CMPA(target, reg, size)) - }, - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - }, - OPCG_MUL_AND => { - let size = get_size(ins); - - if (ins & 0b0001_1111_0000) == 0b0001_0000_0000 { - let regx = get_high_reg(ins); - let regy = get_low_reg(ins); - - match (ins & 0x08) != 0 { - 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_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))), - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - } 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)) - } - }, - OPCG_ADD => { - let reg = get_high_reg(ins); - let dir = (ins & 0x0100) >> 8; - let size = get_size(ins); - match size { - Some(size) => { - if (ins & 0b100110000) == 0b100000000 { - let src = get_low_reg(ins); - let dest = get_high_reg(ins); - match (ins & 0x08) == 0 { - true => Ok(Instruction::ADDX(Target::DirectDReg(src), Target::DirectDReg(dest), size)), - false => Ok(Instruction::ADDX(Target::IndirectARegDec(src), Target::IndirectARegDec(dest), size)), - } - } else { - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - if dir == 0 { - Ok(Instruction::ADD(target, Target::DirectDReg(reg), size)) - } else { - Ok(Instruction::ADD(Target::DirectDReg(reg), target, size)) - } - } - }, - None => { - let size = if dir == 0 { Size::Word } else { Size::Long }; - let target = self.decode_lower_effective_address(memory, ins, Some(size))?; - Ok(Instruction::ADDA(target, reg, size)) - }, - } - }, - OPCG_SHIFT => { - let dir = if (ins & 0x0100) == 0 { ShiftDirection::Right } else { ShiftDirection::Left }; - match get_size(ins) { - Some(size) => { - let reg = get_low_reg(ins); - let rotation = get_high_reg(ins); - let count = if (ins & 0x0020) == 0 { - Target::Immediate(if rotation != 0 { rotation as u32 } else { 8 }) - } else { - Target::DirectDReg(rotation) - }; - - match (ins & 0x0018) >> 3 { - 0b00 => Ok(Instruction::ASd(count, Target::DirectDReg(reg), size, dir)), - 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)), - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - }, - None => { - if (ins & 0x800) == 0 { - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; - let count = Target::Immediate(1); - match (ins & 0x0600) >> 9 { - 0b00 => Ok(Instruction::ASd(count, target, Size::Word, dir)), - 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)), - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - } else if self.cputype > M68kType::MC68020 { - // Bitfield instructions (MC68020+) - let ext = self.read_instruction_word(memory)?; - let reg = ((ext & 0x7000) >> 12) as u8; - - let offset = match (ext & 0x0800) == 0 { - true => RegOrImmediate::Immediate(((ext & 0x07C0) >> 6) as u8), - false => RegOrImmediate::DReg(((ext & 0x01C0) >> 6) as u8), - }; - - let width = match (ext & 0x0020) == 0 { - true => RegOrImmediate::Immediate((ext & 0x001F) as u8), - false => RegOrImmediate::DReg((ext & 0x0007) as u8), - }; - - let target = self.decode_lower_effective_address(memory, ins, Some(Size::Word))?; - match (ins & 0x0700) >> 8 { - 0b010 => Ok(Instruction::BFCHG(target, offset, width)), - 0b100 => Ok(Instruction::BFCLR(target, offset, width)), - 0b011 => Ok(Instruction::BFEXTS(target, offset, width, reg)), - 0b001 => Ok(Instruction::BFEXTU(target, offset, width, reg)), - 0b101 => Ok(Instruction::BFFFO(target, offset, width, reg)), - 0b111 => Ok(Instruction::BFINS(reg, target, offset, width)), - 0b110 => Ok(Instruction::BFSET(target, offset, width)), - 0b000 => Ok(Instruction::BFTST(target, offset, width)), - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), - } - } else { - Err(Error::processor(Exceptions::IllegalInstruction as u32)) - } - }, - } - }, - OPCG_ALINE => { - Ok(Instruction::UnimplementedA(ins)) - }, - OPCG_FLINE => { - Ok(Instruction::UnimplementedF(ins)) - }, - _ => Err(Error::processor(Exceptions::IllegalInstruction as u32)), } } @@ -694,7 +731,7 @@ impl M68kDecoder { } } - pub fn get_mode_as_target(&mut self, memory: &mut dyn Addressable, mode: u8, reg: u8, size: Option) -> Result { + fn get_mode_as_target(&mut self, memory: &mut dyn Addressable, mode: u8, reg: u8, size: Option) -> Result { let value = match mode { 0b000 => Target::DirectDReg(reg), 0b001 => Target::DirectAReg(reg),