Thumb 4 - Take care of "neg" case.

I overlooked it :/


Former-commit-id: 360eb755bcf343cddd98807e9faeff007c94cf64
This commit is contained in:
Michel Heily 2019-07-09 01:30:24 +03:00
parent 34233fa654
commit 65de0c4e9d
5 changed files with 55 additions and 43 deletions

View file

@ -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;

View file

@ -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() {

View file

@ -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)?;
}

View file

@ -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
};

View file

@ -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),
}