Thumb 4 - Take care of "neg" case.
I overlooked it :/ Former-commit-id: 360eb755bcf343cddd98807e9faeff007c94cf64
This commit is contained in:
parent
34233fa654
commit
65de0c4e9d
|
@ -3,7 +3,7 @@ use num::FromPrimitive;
|
|||
|
||||
use super::{Core, CpuError, CpuResult, REG_PC};
|
||||
|
||||
#[derive(Debug, Primitive)]
|
||||
#[derive(Debug, Primitive, PartialEq)]
|
||||
pub enum AluOpCode {
|
||||
AND = 0b0000,
|
||||
EOR = 0b0001,
|
||||
|
@ -229,6 +229,26 @@ impl Core {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_barrel_shifted_value(&mut self, sval: BarrelShifterValue) -> i32 {
|
||||
// TODO decide if error handling or panic here
|
||||
match sval {
|
||||
BarrelShifterValue::ImmediateValue(offset) => offset,
|
||||
BarrelShifterValue::ShiftedRegister {
|
||||
reg,
|
||||
shift,
|
||||
added: Some(added),
|
||||
} => {
|
||||
let abs = self.register_shift(reg, shift).unwrap();
|
||||
if added {
|
||||
abs
|
||||
} else {
|
||||
-abs
|
||||
}
|
||||
}
|
||||
_ => panic!("bad barrel shift"),
|
||||
}
|
||||
}
|
||||
|
||||
fn alu_sub_flags(a: i32, b: i32, carry: &mut bool, overflow: &mut bool) -> i32 {
|
||||
let res = a.wrapping_sub(b);
|
||||
*carry = b <= a;
|
||||
|
|
|
@ -135,26 +135,6 @@ impl Core {
|
|||
Ok(pipeline_action)
|
||||
}
|
||||
|
||||
fn get_rn_offset(&mut self, sval: BarrelShifterValue) -> i32 {
|
||||
// TODO decide if error handling or panic here
|
||||
match sval {
|
||||
BarrelShifterValue::ImmediateValue(offset) => offset,
|
||||
BarrelShifterValue::ShiftedRegister {
|
||||
reg,
|
||||
shift,
|
||||
added: Some(added),
|
||||
} => {
|
||||
let abs = self.register_shift(reg, shift).unwrap();
|
||||
if added {
|
||||
abs
|
||||
} else {
|
||||
-abs
|
||||
}
|
||||
}
|
||||
_ => panic!("bad barrel shift"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Memory Load/Store
|
||||
/// Instruction | Cycles | Flags | Expl.
|
||||
/// ------------------------------------------------------------------------------
|
||||
|
@ -178,7 +158,7 @@ impl Core {
|
|||
addr = insn.pc + 8; // prefetching
|
||||
}
|
||||
|
||||
let offset = self.get_rn_offset(insn.ldr_str_offset());
|
||||
let offset = self.get_barrel_shifted_value(insn.ldr_str_offset());
|
||||
|
||||
let effective_addr = (addr as i32).wrapping_add(offset) as Addr;
|
||||
addr = if insn.pre_index_flag() {
|
||||
|
@ -238,7 +218,7 @@ impl Core {
|
|||
addr = insn.pc + 8; // prefetching
|
||||
}
|
||||
|
||||
let offset = self.get_rn_offset(insn.ldr_str_hs_offset().unwrap());
|
||||
let offset = self.get_barrel_shifted_value(insn.ldr_str_hs_offset().unwrap());
|
||||
|
||||
let effective_addr = (addr as i32).wrapping_add(offset) as Addr;
|
||||
addr = if insn.pre_index_flag() {
|
||||
|
|
|
@ -37,9 +37,16 @@ impl ThumbInstruction {
|
|||
}
|
||||
|
||||
fn fmt_thumb_alu_ops(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use ShiftedRegister::ByRegister;
|
||||
let (op, shft) = self.alu_opcode();
|
||||
if let Some(ShiftedRegister::ByRegister(_, op)) = shft {
|
||||
if let Some(BarrelShifterValue::ShiftedRegister {
|
||||
shift: ByRegister(_, op),
|
||||
..
|
||||
}) = shft
|
||||
{
|
||||
write!(f, "{}", op)?;
|
||||
} else if op == AluOpCode::RSB {
|
||||
write!(f, "neg")?;
|
||||
} else {
|
||||
write!(f, "{}", op)?;
|
||||
}
|
||||
|
|
|
@ -92,8 +92,7 @@ impl Core {
|
|||
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
|
||||
self.get_barrel_shifted_value(shft)
|
||||
} else {
|
||||
self.get_reg(insn.rs()) as i32
|
||||
};
|
||||
|
|
|
@ -242,36 +242,42 @@ impl ThumbInstruction {
|
|||
OpFormat5::from_u8(self.raw.bit_range(8..10) as u8).unwrap()
|
||||
}
|
||||
|
||||
pub fn alu_opcode(&self) -> (AluOpCode, Option<ShiftedRegister>) {
|
||||
pub fn alu_opcode(&self) -> (AluOpCode, Option<BarrelShifterValue>) {
|
||||
use ShiftedRegister::*;
|
||||
match self.raw.bit_range(6..10) {
|
||||
0b0010 => (
|
||||
AluOpCode::MOV,
|
||||
Some(ShiftedRegister::ByRegister(
|
||||
self.rs(),
|
||||
BarrelShiftOpCode::LSL,
|
||||
)),
|
||||
Some(BarrelShifterValue::ShiftedRegister {
|
||||
reg: self.rd(),
|
||||
shift: ByRegister(self.rs(), BarrelShiftOpCode::LSL),
|
||||
added: Some(true),
|
||||
}),
|
||||
),
|
||||
0b0011 => (
|
||||
AluOpCode::MOV,
|
||||
Some(ShiftedRegister::ByRegister(
|
||||
self.rs(),
|
||||
BarrelShiftOpCode::LSR,
|
||||
)),
|
||||
Some(BarrelShifterValue::ShiftedRegister {
|
||||
reg: self.rd(),
|
||||
shift: ByRegister(self.rs(), BarrelShiftOpCode::LSR),
|
||||
added: Some(true),
|
||||
}),
|
||||
),
|
||||
0b0100 => (
|
||||
AluOpCode::MOV,
|
||||
Some(ShiftedRegister::ByRegister(
|
||||
self.rs(),
|
||||
BarrelShiftOpCode::ASR,
|
||||
)),
|
||||
Some(BarrelShifterValue::ShiftedRegister {
|
||||
reg: self.rd(),
|
||||
shift: ByRegister(self.rs(), BarrelShiftOpCode::ASR),
|
||||
added: Some(true),
|
||||
}),
|
||||
),
|
||||
0b0111 => (
|
||||
AluOpCode::MOV,
|
||||
Some(ShiftedRegister::ByRegister(
|
||||
self.rs(),
|
||||
BarrelShiftOpCode::ROR,
|
||||
)),
|
||||
Some(BarrelShifterValue::ShiftedRegister {
|
||||
reg: self.rd(),
|
||||
shift: ByRegister(self.rs(), BarrelShiftOpCode::ROR),
|
||||
added: Some(true),
|
||||
}),
|
||||
),
|
||||
0b1001 => (AluOpCode::RSB, Some(BarrelShifterValue::ImmediateValue(0))),
|
||||
0b1101 => panic!("tried to decode MUL"),
|
||||
op => (AluOpCode::from_u16(op).unwrap(), None),
|
||||
}
|
||||
|
|
Reference in a new issue