thumb: Fix ALU ops for barrel shifter opcodes

I kinda missed these when I read the manual ><


Former-commit-id: 7d6c21b6c3b46bf065a177c1c7f7a7a1baa6b8fa
This commit is contained in:
Michel Heily 2019-07-08 01:47:41 +03:00
parent 163d8bda59
commit ecdd6e0ed4
3 changed files with 51 additions and 10 deletions

View file

@ -37,10 +37,15 @@ impl ThumbInstruction {
}
fn fmt_thumb_alu_ops(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (op, shft) = self.alu_opcode();
if let Some(ArmRegisterShift::ShiftRegister(_, shftOp)) = shft {
write!(f, "{}", shftOp)?;
} else {
write!(f, "{}", op)?;
}
write!(
f,
"{op}\t{Rd}, {Rs}",
op = self.alu_opcode(),
"\t{Rd}, {Rs}",
Rd = reg_string(self.rd()),
Rs = reg_string(self.rs())
)

View file

@ -1,4 +1,4 @@
use crate::arm7tdmi::arm::*;
use crate::arm7tdmi::arm::exec::*;
use crate::arm7tdmi::bus::Bus;
use crate::arm7tdmi::cpu::{Core, CpuExecResult, CpuPipelineAction};
use crate::arm7tdmi::*;
@ -82,12 +82,20 @@ impl Core {
}
fn exec_thumb_alu_ops(&mut self, _bus: &mut Bus, insn: ThumbInstruction) -> CpuExecResult {
let arm_alu_op: ArmOpCode = insn.alu_opcode();
let op1 = self.get_reg(insn.rd()) as i32;
let op2 = self.get_reg(insn.rs()) as i32;
let rd = insn.rd();
let (arm_alu_op, shft) = insn.alu_opcode();
let op1 = self.get_reg(rd) as i32;
let op2 = if let Some(shft) = shft {
let bs_result = self.register_shift(rd, shft)?;
bs_result
} else {
self.get_reg(insn.rs()) as i32
};
let result = self.alu(arm_alu_op, op1, op2, true);
if let Some(result) = result {
self.set_reg(insn.rd(), result as u32);
self.set_reg(rd, result as u32);
}
Ok(CpuPipelineAction::IncPC)

View file

@ -4,7 +4,7 @@ use crate::bit::BitIndex;
use crate::byteorder::{LittleEndian, ReadBytesExt};
use crate::num::FromPrimitive;
use super::arm::{ArmCond, ArmOpCode, ArmShiftType};
use super::arm::*;
use super::{Addr, InstructionDecoder, InstructionDecoderError};
pub mod display;
@ -241,10 +241,38 @@ impl ThumbInstruction {
OpFormat5::from_u8(self.raw.bit_range(8..10) as u8).unwrap()
}
pub fn alu_opcode(&self) -> ArmOpCode {
pub fn alu_opcode(&self) -> (ArmOpCode, Option<ArmRegisterShift>) {
match self.raw.bit_range(6..10) {
0b0010 => (
ArmOpCode::MOV,
Some(ArmRegisterShift::ShiftRegister(
self.rs(),
ArmShiftType::LSL,
)),
),
0b0011 => (
ArmOpCode::MOV,
Some(ArmRegisterShift::ShiftRegister(
self.rs(),
ArmShiftType::LSR,
)),
),
0b0100 => (
ArmOpCode::MOV,
Some(ArmRegisterShift::ShiftRegister(
self.rs(),
ArmShiftType::ASR,
)),
),
0b0111 => (
ArmOpCode::MOV,
Some(ArmRegisterShift::ShiftRegister(
self.rs(),
ArmShiftType::ROR,
)),
),
0b1101 => panic!("tried to decode MUL"),
op => ArmOpCode::from_u16(op).unwrap(),
op => (ArmOpCode::from_u16(op).unwrap(), None),
}
}