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}; use super::{Core, CpuError, CpuResult, REG_PC};
#[derive(Debug, Primitive)] #[derive(Debug, Primitive, PartialEq)]
pub enum AluOpCode { pub enum AluOpCode {
AND = 0b0000, AND = 0b0000,
EOR = 0b0001, 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 { fn alu_sub_flags(a: i32, b: i32, carry: &mut bool, overflow: &mut bool) -> i32 {
let res = a.wrapping_sub(b); let res = a.wrapping_sub(b);
*carry = b <= a; *carry = b <= a;

View file

@ -135,26 +135,6 @@ impl Core {
Ok(pipeline_action) 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 /// Memory Load/Store
/// Instruction | Cycles | Flags | Expl. /// Instruction | Cycles | Flags | Expl.
/// ------------------------------------------------------------------------------ /// ------------------------------------------------------------------------------
@ -178,7 +158,7 @@ impl Core {
addr = insn.pc + 8; // prefetching 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; let effective_addr = (addr as i32).wrapping_add(offset) as Addr;
addr = if insn.pre_index_flag() { addr = if insn.pre_index_flag() {
@ -238,7 +218,7 @@ impl Core {
addr = insn.pc + 8; // prefetching 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; let effective_addr = (addr as i32).wrapping_add(offset) as Addr;
addr = if insn.pre_index_flag() { 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 { fn fmt_thumb_alu_ops(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ShiftedRegister::ByRegister;
let (op, shft) = self.alu_opcode(); 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)?; write!(f, "{}", op)?;
} else if op == AluOpCode::RSB {
write!(f, "neg")?;
} else { } else {
write!(f, "{}", op)?; write!(f, "{}", op)?;
} }

View file

@ -92,8 +92,7 @@ impl Core {
let (arm_alu_op, shft) = insn.alu_opcode(); let (arm_alu_op, shft) = insn.alu_opcode();
let op1 = self.get_reg(rd) as i32; let op1 = self.get_reg(rd) as i32;
let op2 = if let Some(shft) = shft { let op2 = if let Some(shft) = shft {
let bs_result = self.register_shift(rd, shft)?; self.get_barrel_shifted_value(shft)
bs_result
} else { } else {
self.get_reg(insn.rs()) as i32 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() 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) { match self.raw.bit_range(6..10) {
0b0010 => ( 0b0010 => (
AluOpCode::MOV, AluOpCode::MOV,
Some(ShiftedRegister::ByRegister( Some(BarrelShifterValue::ShiftedRegister {
self.rs(), reg: self.rd(),
BarrelShiftOpCode::LSL, shift: ByRegister(self.rs(), BarrelShiftOpCode::LSL),
)), added: Some(true),
}),
), ),
0b0011 => ( 0b0011 => (
AluOpCode::MOV, AluOpCode::MOV,
Some(ShiftedRegister::ByRegister( Some(BarrelShifterValue::ShiftedRegister {
self.rs(), reg: self.rd(),
BarrelShiftOpCode::LSR, shift: ByRegister(self.rs(), BarrelShiftOpCode::LSR),
)), added: Some(true),
}),
), ),
0b0100 => ( 0b0100 => (
AluOpCode::MOV, AluOpCode::MOV,
Some(ShiftedRegister::ByRegister( Some(BarrelShifterValue::ShiftedRegister {
self.rs(), reg: self.rd(),
BarrelShiftOpCode::ASR, shift: ByRegister(self.rs(), BarrelShiftOpCode::ASR),
)), added: Some(true),
}),
), ),
0b0111 => ( 0b0111 => (
AluOpCode::MOV, AluOpCode::MOV,
Some(ShiftedRegister::ByRegister( Some(BarrelShifterValue::ShiftedRegister {
self.rs(), reg: self.rd(),
BarrelShiftOpCode::ROR, shift: ByRegister(self.rs(), BarrelShiftOpCode::ROR),
)), added: Some(true),
}),
), ),
0b1001 => (AluOpCode::RSB, Some(BarrelShifterValue::ImmediateValue(0))),
0b1101 => panic!("tried to decode MUL"), 0b1101 => panic!("tried to decode MUL"),
op => (AluOpCode::from_u16(op).unwrap(), None), op => (AluOpCode::from_u16(op).unwrap(), None),
} }