1mod disassemble; 2 3use crate::bus::{BusInterface, MemoryCycle}; 4use crate::{Arm7Tdmi, CpuMode, CpuState, Exception, Registers, StatusRegister}; 5use jgenesis_common::define_bit_enum; 6use jgenesis_common::num::GetBit; 7use jgenesis_proc_macros::{FakeDecode, FakeEncode}; 8use std::array; 9use std::cmp::Ordering; 10use std::ops::Deref; 11 12const ARM_OPCODE_LEN: u32 = 4; 13const THUMB_OPCODE_LEN: u32 = 2; 14 15#[derive(Debug, Clone, Copy)] 16struct ConditionCodes { 17 sign: bool, 18 zero: bool, 19 carry: bool, 20 overflow: bool, 21} 22 23impl ConditionCodes { 24 fn logical(value: u32, shifter_out: bool, overflow: bool) -> Self { 25 Self { sign: value.bit(31), zero: value == 0, carry: shifter_out, overflow } 26 } 27} 28 29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 30enum Condition { 31 Equal = 0x0, // EQ (Z=1) 32 NotEqual = 0x1, // NE (Z=0) 33 CarrySet = 0x2, // CS (C=1) 34 CarryClear = 0x3, // CC (C=0) 35 Minus = 0x4, // MI (N=1) 36 Plus = 0x5, // PL (N=0) 37 OverflowSet = 0x6, // VS (V=1) 38 OverflowClear = 0x7, // VC (V=0) 39 Higher = 0x8, // HI (C=1 and Z=0) 40 LowerOrSame = 0x9, // LS (C=0 or Z=1) 41 GreaterOrEqual = 0xA, // GE (N=V) 42 Less = 0xB, // LT (N!=V) 43 Greater = 0xC, // GT (Z=0 and N=V) 44 LessOrEqual = 0xD, // LE (Z=1 or N!=V) 45 Always = 0xE, // AL (always true) 46 Reserved = 0xF, // Reserved - treat as always false 47} 48 49impl Condition { 50 fn from_bits(bits: u32) -> Self { 51 match bits & 0xF { 52 0x0 => Self::Equal, 53 0x1 => Self::NotEqual, 54 0x2 => Self::CarrySet, 55 0x3 => Self::CarryClear, 56 0x4 => Self::Minus, 57 0x5 => Self::Plus, 58 0x6 => Self::OverflowSet, 59 0x7 => Self::OverflowClear, 60 0x8 => Self::Higher, 61 0x9 => Self::LowerOrSame, 62 0xA => Self::GreaterOrEqual, 63 0xB => Self::Less, 64 0xC => Self::Greater, 65 0xD => Self::LessOrEqual, 66 0xE => Self::Always, 67 0xF => Self::Reserved, 68 _ => unreachable!("value is always <= 0xF"), 69 } 70 } 71 72 fn from_arm_opcode(opcode: u32) -> Self { 73 Self::from_bits(opcode >> 28) 74 } 75 76 fn check(self, cpsr: StatusRegister) -> bool { 77 match self { 78 Self::Equal => cpsr.zero, 79 Self::NotEqual => !cpsr.zero, 80 Self::CarrySet => cpsr.carry, 81 Self::CarryClear => !cpsr.carry, 82 Self::Minus => cpsr.sign, 83 Self::Plus => !cpsr.sign, 84 Self::OverflowSet => cpsr.overflow, 85 Self::OverflowClear => !cpsr.overflow, 86 Self::Higher => cpsr.carry && !cpsr.zero, 87 Self::LowerOrSame => !cpsr.carry || cpsr.zero, 88 Self::GreaterOrEqual => cpsr.sign == cpsr.overflow, 89 Self::Less => cpsr.sign != cpsr.overflow, 90 Self::Greater => !cpsr.zero && cpsr.sign == cpsr.overflow, 91 Self::LessOrEqual => cpsr.zero || cpsr.sign != cpsr.overflow, 92 Self::Always => true, 93 Self::Reserved => false, 94 } 95 } 96 97 fn suffix(self) -> &'static str { 98 match self { 99 Self::Equal => "EQ", 100 Self::NotEqual => "NE", 101 Self::CarrySet => "CS", 102 Self::CarryClear => "CC", 103 Self::Minus => "MI", 104 Self::Plus => "PL", 105 Self::OverflowSet => "VS", 106 Self::OverflowClear => "VC", 107 Self::Higher => "HI", 108 Self::LowerOrSame => "LS", 109 Self::GreaterOrEqual => "GE", 110 Self::Less => "LT", 111 Self::Greater => "GT", 112 Self::LessOrEqual => "LE", 113 Self::Always => "", 114 Self::Reserved => "(invalid)", 115 } 116 } 117} 118 119#[derive(Debug, Clone, Copy, PartialEq, Eq)] 120enum AluOp { 121 And = 0x0, 122 ExclusiveOr = 0x1, 123 Subtract = 0x2, 124 ReverseSubtract = 0x3, 125 Add = 0x4, 126 AddCarry = 0x5, 127 SubtractCarry = 0x6, 128 ReverseSubtractCarry = 0x7, 129 Test = 0x8, 130 TestEqual = 0x9, 131 Compare = 0xA, 132 CompareNegate = 0xB, 133 Or = 0xC, 134 Move = 0xD, 135 BitClear = 0xE, 136 MoveNegate = 0xF, 137} 138 139impl AluOp { 140 fn from_bits(bits: u32) -> Self { 141 match bits & 0xF { 142 0x0 => Self::And, 143 0x1 => Self::ExclusiveOr, 144 0x2 => Self::Subtract, 145 0x3 => Self::ReverseSubtract, 146 0x4 => Self::Add, 147 0x5 => Self::AddCarry, 148 0x6 => Self::SubtractCarry, 149 0x7 => Self::ReverseSubtractCarry, 150 0x8 => Self::Test, 151 0x9 => Self::TestEqual, 152 0xA => Self::Compare, 153 0xB => Self::CompareNegate, 154 0xC => Self::Or, 155 0xD => Self::Move, 156 0xE => Self::BitClear, 157 0xF => Self::MoveNegate, 158 _ => unreachable!("value & 0xF is always <= 0xF"), 159 } 160 } 161 162 // TST, TEQ, CMP, CMN 163 fn is_test(self) -> bool { 164 matches!(self, Self::Test | Self::TestEqual | Self::Compare | Self::CompareNegate) 165 } 166} 167 168#[derive(Debug, Clone, Copy, PartialEq, Eq)] 169enum ShiftType { 170 Left = 0, 171 LogicalRight = 1, 172 ArithmeticRight = 2, 173 RotateRight = 3, 174} 175 176impl ShiftType { 177 fn from_bits(bits: u32) -> Self { 178 match bits & 3 { 179 0 => Self::Left, 180 1 => Self::LogicalRight, 181 2 => Self::ArithmeticRight, 182 3 => Self::RotateRight, 183 _ => unreachable!("value & 3 is always <= 3"), 184 } 185 } 186} 187 188define_bit_enum!(LoadIndexing, [Post, Pre]); 189define_bit_enum!(IndexOp, [Subtract, Add]); 190define_bit_enum!(WriteBack, [No, Yes]); 191 192#[derive(Debug, Clone, Copy, PartialEq, Eq)] 193enum HalfwordLoadType { 194 UnsignedHalfword, 195 SignedByte, 196 SignedHalfword, 197} 198 199impl HalfwordLoadType { 200 fn from_bits(bits: u32) -> Option<Self> { 201 match bits & 3 { 202 0 => None, 203 1 => Some(Self::UnsignedHalfword), 204 2 => Some(Self::SignedByte), 205 3 => Some(Self::SignedHalfword), 206 _ => unreachable!("value & 3 is always <= 3"), 207 } 208 } 209} 210 211define_bit_enum!(LoadSize, [Word, Byte]); 212 213pub type ArmFn<Bus> = fn(&mut Arm7Tdmi<Bus>, u32, &mut Bus); 214 215struct ArmDecode<Bus: BusInterface> { 216 mask: u32, 217 target: u32, 218 op_fn: ArmFn<Bus>, 219} 220 221impl<Bus: BusInterface> ArmDecode<Bus> { 222 fn new(mask: u32, target: u32, op_fn: ArmFn<Bus>) -> Self { 223 Self { mask, target, op_fn } 224 } 225} 226 227type ArmFnArray<Bus> = [ArmFn<Bus>; 4096]; 228 229#[derive(Debug, Clone, FakeEncode, FakeDecode)] 230pub struct ArmOpTable<Bus: BusInterface>(Box<ArmFnArray<Bus>>); 231 232impl<Bus: BusInterface> Default for ArmOpTable<Bus> { 233 fn default() -> Self { 234 Self(Box::new(Arm7Tdmi::<Bus>::new_arm_op_table())) 235 } 236} 237 238impl<Bus: BusInterface> Deref for ArmOpTable<Bus> { 239 type Target = Box<ArmFnArray<Bus>>; 240 241 fn deref(&self) -> &Self::Target { 242 &self.0 243 } 244} 245 246pub type ThumbFn<Bus> = fn(&mut Arm7Tdmi<Bus>, u16, &mut Bus); 247 248struct ThumbDecode<Bus: BusInterface> { 249 mask: u16, 250 target: u16, 251 op_fn: ThumbFn<Bus>, 252} 253 254impl<Bus: BusInterface> ThumbDecode<Bus> { 255 const fn new(mask: u16, target: u16, op_fn: ThumbFn<Bus>) -> Self { 256 Self { mask, target, op_fn } 257 } 258} 259 260type ThumbFnArray<Bus> = [ThumbFn<Bus>; 256]; 261 262#[derive(Debug, Clone, FakeEncode, FakeDecode)] 263pub struct ThumbOpTable<Bus: BusInterface>(Box<ThumbFnArray<Bus>>); 264 265impl<Bus: BusInterface> Default for ThumbOpTable<Bus> { 266 fn default() -> Self { 267 Self(Box::new(Arm7Tdmi::<Bus>::new_thumb_op_table())) 268 } 269} 270 271impl<Bus: BusInterface> Deref for ThumbOpTable<Bus> { 272 type Target = Box<ThumbFnArray<Bus>>; 273 274 fn deref(&self) -> &Self::Target { 275 &self.0 276 } 277} 278 279impl<Bus: BusInterface> Arm7Tdmi<Bus> { 280 fn new_arm_op_table() -> ArmFnArray<Bus> { 281 #[rustfmt::skip] 282 let decode_table = &[ 283 ArmDecode::new(0b1111_1111_1111, 0b0001_0010_0001, Self::arm_bx), 284 ArmDecode::new(0b1111_1100_1111, 0b0000_0000_1001, Self::arm_multiply), 285 ArmDecode::new(0b1111_1000_1111, 0b0000_1000_1001, Self::arm_multiply_long), 286 ArmDecode::new(0b1111_1011_1111, 0b0001_0000_1001, Self::arm_swap), 287 ArmDecode::new(0b1110_0101_1001, 0b0000_0000_1001, Self::arm_load_halfword::<false, false>), 288 ArmDecode::new(0b1110_0101_1001, 0b0000_0100_1001, Self::arm_load_halfword::<false, true>), 289 ArmDecode::new(0b1110_0101_1001, 0b0000_0001_1001, Self::arm_load_halfword::<true, false>), 290 ArmDecode::new(0b1110_0101_1001, 0b0000_0101_1001, Self::arm_load_halfword::<true, true>), 291 ArmDecode::new(0b1111_1011_1111, 0b0001_0000_0000, Self::arm_mrs), 292 ArmDecode::new(0b1111_1011_0000, 0b0001_0010_0000, Self::arm_msr::<false>), 293 ArmDecode::new(0b1111_1011_0000, 0b0011_0010_0000, Self::arm_msr::<true>), 294 ArmDecode::new(0b1110_0000_0000, 0b0000_0000_0000, Self::arm_alu::<false>), 295 ArmDecode::new(0b1110_0000_0000, 0b0010_0000_0000, Self::arm_alu::<true>), 296 ArmDecode::new(0b1110_0001_0000, 0b0100_0000_0000, Self::arm_load_word::<false, false>), 297 ArmDecode::new(0b1110_0001_0000, 0b0100_0001_0000, Self::arm_load_word::<true, false>), 298 ArmDecode::new(0b1110_0001_0000, 0b0110_0000_0000, Self::arm_load_word::<false, true>), 299 ArmDecode::new(0b1110_0001_0000, 0b0110_0001_0000, Self::arm_load_word::<true, true>), 300 ArmDecode::new(0b1111_1001_0000, 0b1000_0000_0000, Self::arm_ldm_stm::<false, false, true>), 301 ArmDecode::new(0b1111_1001_0000, 0b1000_0001_0000, Self::arm_ldm_stm::<true, false, true>), 302 ArmDecode::new(0b1111_1001_0000, 0b1000_1000_0000, Self::arm_ldm_stm::<false, true, true>), 303 ArmDecode::new(0b1111_1001_0000, 0b1000_1001_0000, Self::arm_ldm_stm::<true, true, true>), 304 ArmDecode::new(0b1111_1001_0000, 0b1001_0000_0000, Self::arm_ldm_stm::<false, false, false>), 305 ArmDecode::new(0b1111_1001_0000, 0b1001_0001_0000, Self::arm_ldm_stm::<true, false, false>), 306 ArmDecode::new(0b1111_1001_0000, 0b1001_1000_0000, Self::arm_ldm_stm::<false, true, false>), 307 ArmDecode::new(0b1111_1001_0000, 0b1001_1001_0000, Self::arm_ldm_stm::<true, true, false>), 308 ArmDecode::new(0b1111_0000_0000, 0b1010_0000_0000, Self::arm_branch::<false>), 309 ArmDecode::new(0b1111_0000_0000, 0b1011_0000_0000, Self::arm_branch::<true>), 310 ArmDecode::new(0b1111_0000_0000, 0b1111_0000_0000, Self::arm_swi), 311 ]; 312 313 array::from_fn(|opcode_mask| { 314 let opcode_mask = opcode_mask as u32; 315 for &ArmDecode { mask, target, op_fn } in decode_table { 316 if opcode_mask & mask == target { 317 return op_fn; 318 } 319 } 320 321 |cpu, opcode, bus| { 322 log::error!("Executed undefined ARM opcode: {opcode:08X}"); 323 cpu.handle_exception(Exception::UndefinedInstruction, bus); 324 } 325 }) 326 } 327 328 pub(crate) fn execute_arm_opcode(&mut self, opcode: u32, bus: &mut Bus) { 329 if log::log_enabled!(log::Level::Trace) { 330 log::trace!( 331 "Executing opcode {opcode:08X}, PC+8={:08X}, str={}", 332 self.registers.r[15], 333 disassemble::arm(opcode) 334 ); 335 log::trace!(" R={:08X?}", self.registers.r); 336 } 337 338 let condition = Condition::from_arm_opcode(opcode); 339 if !condition.check(self.registers.cpsr) { 340 return; 341 } 342 343 let opcode_mask = ((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0xF); 344 self.arm_op_table[opcode_mask as usize](self, opcode, bus); 345 } 346 347 fn new_thumb_op_table() -> ThumbFnArray<Bus> { 348 #[rustfmt::skip] 349 let decode_table = &[ 350 ThumbDecode::new(0xF8, 0x18, Self::thumb_add_sub), 351 ThumbDecode::new(0xE0, 0x00, Self::thumb_move_shifted_register), 352 ThumbDecode::new(0xE0, 0x20, Self::thumb_alu_immediate), 353 ThumbDecode::new(0xFC, 0x40, Self::thumb_alu), 354 ThumbDecode::new(0xFC, 0x44, Self::thumb_high_register_op), 355 ThumbDecode::new(0xF8, 0x48, Self::thumb_pc_relative_load), 356 ThumbDecode::new(0xF2, 0x50, Self::thumb_load_register_offset), 357 ThumbDecode::new(0xF2, 0x52, Self::thumb_load_sign_extended), 358 ThumbDecode::new(0xE0, 0x60, Self::thumb_load_immediate_offset), 359 ThumbDecode::new(0xF0, 0x80, Self::thumb_load_halfword), 360 ThumbDecode::new(0xF0, 0x90, Self::thumb_load_sp_relative), 361 ThumbDecode::new(0xF0, 0xA0, Self::thumb_load_address), 362 ThumbDecode::new(0xFF, 0xB0, Self::thumb_add_offset_sp), 363 ThumbDecode::new(0xF6, 0xB4, Self::thumb_push_pop), 364 ThumbDecode::new(0xF0, 0xC0, Self::thumb_load_multiple), 365 ThumbDecode::new(0xFF, 0xDF, Self::thumb_software_interrupt), 366 ThumbDecode::new(0xF0, 0xD0, Self::thumb_conditional_branch), 367 ThumbDecode::new(0xF8, 0xE0, Self::thumb_unconditional_branch), 368 ThumbDecode::new(0xF0, 0xF0, Self::thumb_long_branch), 369 ]; 370 371 array::from_fn(|opcode_mask| { 372 let opcode_mask = opcode_mask as u16; 373 374 for &ThumbDecode { mask, target, op_fn } in decode_table { 375 if opcode_mask & mask == target { 376 return op_fn; 377 } 378 } 379 380 |cpu, opcode, bus| { 381 log::error!("Executed undefined Thumb opcode: {opcode:04X}"); 382 cpu.handle_exception(Exception::UndefinedInstruction, bus); 383 } 384 }) 385 } 386 387 pub(crate) fn execute_thumb_opcode(&mut self, opcode: u16, bus: &mut Bus) { 388 if log::log_enabled!(log::Level::Trace) { 389 log::trace!( 390 "Executing opcode {opcode:04X}, PC+4={:08X}, str={}", 391 self.registers.r[15], 392 disassemble::thumb(opcode) 393 ); 394 log::trace!(" R={:08X?}", self.registers.r); 395 } 396 397 let opcode_mask = opcode >> 8; 398 self.thumb_op_table[opcode_mask as usize](self, opcode, bus); 399 } 400 401 // B: Branch 402 // BL: Branch and link 403 fn arm_branch<const LINK: bool>(&mut self, opcode: u32, bus: &mut Bus) { 404 // Offset is a 24-bit signed value, shifted left 2 405 let offset = (((opcode & 0xFFFFFF) as i32) << 8) >> 6; 406 self.branch::<LINK, ARM_OPCODE_LEN>(offset, bus); 407 } 408 409 fn branch<const LINK: bool, const OPCODE_LEN: u32>(&mut self, offset: i32, bus: &mut Bus) { 410 if LINK { 411 self.registers.r[14] = self.prev_r15.wrapping_sub(OPCODE_LEN); 412 } 413 414 self.registers.r[15] = self.prev_r15.wrapping_add_signed(offset); 415 self.refill_prefetch(bus); 416 } 417 418 // BX: Branch and exchange ARM/Thumb state 419 fn arm_bx(&mut self, opcode: u32, bus: &mut Bus) { 420 self.branch_exchange(opcode & 0xF, bus); 421 } 422 423 fn branch_exchange(&mut self, rn: u32, bus: &mut Bus) { 424 let new_pc = self.read_register(rn); 425 self.registers.cpsr.state = CpuState::from_bit(new_pc.bit(0)); 426 427 log::trace!("CPU state is now {:?}", self.registers.cpsr.state); 428 429 self.registers.r[15] = new_pc; 430 self.refill_prefetch(bus); 431 } 432 433 // MRS: Transfer PSR contents to register 434 fn arm_mrs(&mut self, opcode: u32, _bus: &mut Bus) { 435 let rd = (opcode >> 12) & 0xF; 436 let spsr = opcode.bit(22); 437 438 if spsr { 439 let spsr = match self.registers.cpsr.mode.spsr(&mut self.registers) { 440 Some(spsr) => *spsr, 441 None => { 442 // SPSR reads in user/system mode access CPSR 443 self.registers.cpsr 444 } 445 }; 446 self.registers.r[rd as usize] = spsr.into(); 447 } else { 448 self.registers.r[rd as usize] = self.registers.cpsr.into(); 449 } 450 } 451 452 // MSR: Transfer register contents to PSR 453 fn arm_msr<const IMMEDIATE: bool>(&mut self, opcode: u32, _bus: &mut Bus) { 454 const CONTROL_MASK: u32 = 0xFF; 455 const FLAGS_MASK: u32 = 0xF << 28; 456 457 let mut operand = if IMMEDIATE { 458 let (immediate, rotation) = arm_parse_rotated_immediate(opcode); 459 immediate.rotate_right(rotation) 460 } else { 461 self.read_register(opcode & 0xF) 462 }; 463 464 let spsr = opcode.bit(22); 465 let psr = if spsr { 466 match self.registers.cpsr.mode.spsr(&mut self.registers) { 467 Some(spsr) => spsr, 468 None => { 469 // SPSR writes in user/system mode do nothing 470 return; 471 } 472 } 473 } else { 474 &mut self.registers.cpsr 475 }; 476 477 let control = opcode.bit(16); 478 let flags = opcode.bit(19); 479 480 if !control { 481 operand = (operand & !CONTROL_MASK) | (u32::from(*psr) & CONTROL_MASK); 482 } 483 if !flags { 484 operand = (operand & !FLAGS_MASK) | (u32::from(*psr) & FLAGS_MASK); 485 } 486 487 if spsr { 488 *psr = operand.into(); 489 } else { 490 self.write_cpsr(operand); 491 } 492 } 493 494 fn arm_swap(&mut self, opcode: u32, bus: &mut Bus) { 495 let rm = opcode & 0xF; 496 let rd = (opcode >> 12) & 0xF; 497 let rn = (opcode >> 16) & 0xF; 498 let size = LoadSize::from_bit(opcode.bit(22)); 499 500 self.swap(rm, rd, rn, size, bus); 501 } 502 503 fn swap(&mut self, rm: u32, rd: u32, rn: u32, size: LoadSize, bus: &mut Bus) { 504 let address = self.registers.r[rn as usize]; 505 506 bus.lock(); 507 508 match size { 509 LoadSize::Word => { 510 let value = bus.read_word(address, MemoryCycle::N).rotate_right(8 * (address & 3)); 511 bus.write_word(address, self.read_register(rm), MemoryCycle::S); 512 self.registers.r[rd as usize] = value; 513 } 514 LoadSize::Byte => { 515 let value = bus.read_byte(address, MemoryCycle::N); 516 bus.write_byte(address, self.read_register(rm) as u8, MemoryCycle::S); 517 self.registers.r[rd as usize] = value.into(); 518 } 519 } 520 521 bus.unlock(); 522 523 bus.internal_cycles(1); 524 } 525 526 // Data processing instructions 527 // AND: And 528 // EOR: Exclusive or 529 // SUB: Subtract 530 // RSB: Reverse subtract 531 // ADD: Add 532 // ADC: Add with carry 533 // SBC: Subtract with carry 534 // RSC: Reverse subtract with carry 535 // TST: Test bits 536 // TEQ: Test equal 537 // CMP: Compare 538 // CMN: Compare negated 539 // ORR: Or 540 // MOV: Move 541 // BIC: Bit clear 542 // MVN: Move negated 543 fn arm_alu<const IMMEDIATE: bool>(&mut self, opcode: u32, bus: &mut Bus) { 544 let alu_op = AluOp::from_bits(opcode >> 21); 545 let set_condition_codes = opcode.bit(20); 546 let rn = (opcode >> 16) & 0xF; 547 let rd = (opcode >> 12) & 0xF; 548 549 if IMMEDIATE { 550 let (immediate, rotation) = arm_parse_rotated_immediate(opcode); 551 self.alu_rotated_immediate( 552 alu_op, 553 rn, 554 rd, 555 set_condition_codes, 556 immediate, 557 rotation, 558 bus, 559 ); 560 } else if opcode.bit(4) { 561 let rm = opcode & 0xF; 562 let rs = (opcode >> 8) & 0xF; 563 let shift_type = ShiftType::from_bits(opcode >> 5); 564 self.alu_register_shift::<ARM_OPCODE_LEN>( 565 alu_op, 566 rn, 567 rd, 568 set_condition_codes, 569 rm, 570 shift_type, 571 rs, 572 bus, 573 ); 574 } else { 575 let rm = opcode & 0xF; 576 let shift_type = ShiftType::from_bits(opcode >> 5); 577 let shift = (opcode >> 7) & 0x1F; 578 self.alu_immediate_shift( 579 alu_op, 580 rn, 581 rd, 582 set_condition_codes, 583 rm, 584 shift_type, 585 shift, 586 bus, 587 ); 588 } 589 } 590 591 #[inline] 592 #[allow(clippy::too_many_arguments)] 593 fn alu_rotated_immediate( 594 &mut self, 595 op: AluOp, 596 rn: u32, 597 rd: u32, 598 set_condition_codes: bool, 599 immediate: u32, 600 rotation: u32, 601 bus: &mut Bus, 602 ) { 603 let (operand2, shifter_out) = if rotation != 0 { 604 (immediate.rotate_right(rotation), immediate.bit((rotation - 1) as u8)) 605 } else { 606 (immediate, self.registers.cpsr.carry) 607 }; 608 609 self.alu(op, self.read_register(rn), rd, set_condition_codes, operand2, shifter_out, bus); 610 } 611 612 #[inline] 613 #[allow(clippy::too_many_arguments)] 614 fn alu_immediate_shift( 615 &mut self, 616 op: AluOp, 617 rn: u32, 618 rd: u32, 619 set_condition_codes: bool, 620 rm: u32, 621 shift_type: ShiftType, 622 shift: u32, 623 bus: &mut Bus, 624 ) { 625 let value = self.read_register(rm); 626 627 let (operand2, shifter_out) = 628 apply_immediate_shift(value, shift_type, shift, self.registers.cpsr.carry); 629 630 self.alu(op, self.read_register(rn), rd, set_condition_codes, operand2, shifter_out, bus); 631 } 632 633 #[inline] 634 #[allow(clippy::too_many_arguments)] 635 fn alu_register_shift<const OPCODE_LEN: u32>( 636 &mut self, 637 op: AluOp, 638 rn: u32, 639 rd: u32, 640 set_condition_codes: bool, 641 rm: u32, 642 shift_type: ShiftType, 643 rs: u32, 644 bus: &mut Bus, 645 ) { 646 let value = self.registers.r[rm as usize]; 647 let shift = self.registers.r[rs as usize] & 0xFF; 648 649 let (operand2, shifter_out) = if shift == 0 { 650 (value, self.registers.cpsr.carry) 651 } else { 652 match shift_type { 653 ShiftType::Left => match shift.cmp(&32) { 654 Ordering::Less => (value << shift, value.bit((32 - shift) as u8)), 655 Ordering::Equal => (0, value.bit(0)), 656 Ordering::Greater => (0, false), 657 }, 658 ShiftType::LogicalRight => match shift.cmp(&32) { 659 Ordering::Less => (value >> shift, value.bit((shift - 1) as u8)), 660 Ordering::Equal => (0, value.bit(31)), 661 Ordering::Greater => (0, false), 662 }, 663 ShiftType::ArithmeticRight => { 664 if shift < 32 { 665 (((value as i32) >> shift) as u32, value.bit((shift - 1) as u8)) 666 } else { 667 (((value as i32) >> 31) as u32, value.bit(31)) 668 } 669 } 670 ShiftType::RotateRight => { 671 let mut shift = shift; 672 while shift > 32 { 673 shift -= 32; 674 } 675 676 if shift == 32 { 677 (value, value.bit(31)) 678 } else { 679 (value.rotate_right(shift), value.bit((shift - 1) as u8)) 680 } 681 } 682 } 683 }; 684 685 let operand1 = self.registers.r[rn as usize]; 686 687 // Register specified shift adds 1I 688 bus.internal_cycles(1); 689 690 self.alu(op, operand1, rd, set_condition_codes, operand2, shifter_out, bus); 691 } 692 693 #[inline] 694 #[allow(clippy::too_many_arguments)] 695 fn alu( 696 &mut self, 697 op: AluOp, 698 operand1: u32, 699 rd: u32, 700 set_condition_codes: bool, 701 operand2: u32, 702 shifter_out: bool, 703 bus: &mut Bus, 704 ) { 705 let (result, codes) = match op { 706 AluOp::And | AluOp::Test => { 707 let result = operand1 & operand2; 708 (result, ConditionCodes::logical(result, shifter_out, self.registers.cpsr.overflow)) 709 } 710 AluOp::ExclusiveOr | AluOp::TestEqual => { 711 let result = operand1 ^ operand2; 712 (result, ConditionCodes::logical(result, shifter_out, self.registers.cpsr.overflow)) 713 } 714 AluOp::Subtract | AluOp::Compare => alu_add(operand1, !operand2, true), 715 AluOp::ReverseSubtract => alu_add(operand2, !operand1, true), 716 AluOp::Add | AluOp::CompareNegate => alu_add(operand1, operand2, false), 717 AluOp::AddCarry => alu_add(operand1, operand2, self.registers.cpsr.carry), 718 AluOp::SubtractCarry => alu_add(operand1, !operand2, self.registers.cpsr.carry), 719 AluOp::ReverseSubtractCarry => alu_add(operand2, !operand1, self.registers.cpsr.carry), 720 AluOp::Or => { 721 let result = operand1 | operand2; 722 (result, ConditionCodes::logical(result, shifter_out, self.registers.cpsr.overflow)) 723 } 724 AluOp::Move => ( 725 operand2, 726 ConditionCodes::logical(operand2, shifter_out, self.registers.cpsr.overflow), 727 ), 728 AluOp::BitClear => { 729 let result = operand1 & !operand2; 730 (result, ConditionCodes::logical(result, shifter_out, self.registers.cpsr.overflow)) 731 } 732 AluOp::MoveNegate => ( 733 !operand2, 734 ConditionCodes::logical(!operand2, shifter_out, self.registers.cpsr.overflow), 735 ), 736 }; 737 738 if set_condition_codes { 739 if rd == 15 { 740 self.spsr_to_cpsr(); 741 } else { 742 self.registers.cpsr.sign = codes.sign; 743 self.registers.cpsr.zero = codes.zero; 744 self.registers.cpsr.carry = codes.carry; 745 self.registers.cpsr.overflow = codes.overflow; 746 } 747 } 748 749 if !op.is_test() { 750 self.registers.r[rd as usize] = result; 751 752 if rd == 15 { 753 self.refill_prefetch(bus); 754 } 755 } 756 } 757 758 fn arm_multiply(&mut self, opcode: u32, bus: &mut Bus) { 759 let rm = opcode & 0xF; 760 let rs = (opcode >> 8) & 0xF; 761 let rn = (opcode >> 12) & 0xF; 762 let rd = (opcode >> 16) & 0xF; 763 let set_condition_codes = opcode.bit(20); 764 let accumulate = opcode.bit(21); 765 766 self.multiply(rm, rs, rn, rd, set_condition_codes, accumulate, bus); 767 } 768 769 #[allow(clippy::too_many_arguments)] 770 fn multiply( 771 &mut self, 772 rm: u32, 773 rs: u32, 774 rn: u32, 775 rd: u32, 776 set_condition_codes: bool, 777 accumulate: bool, 778 bus: &mut Bus, 779 ) { 780 let operand = self.registers.r[rs as usize]; 781 let mut product = self.registers.r[rm as usize].wrapping_mul(operand); 782 if accumulate { 783 product = product.wrapping_add(self.registers.r[rn as usize]); 784 } 785 786 self.registers.r[rd as usize] = product; 787 788 if set_condition_codes { 789 self.registers.cpsr.sign = product.bit(31); 790 self.registers.cpsr.zero = product == 0; 791 // TODO carry bit? 792 } 793 794 let m = if operand & 0xFFFFFF00 == 0 || operand & 0xFFFFFF00 == 0xFFFFFF00 { 795 1 796 } else if operand & 0xFFFF0000 == 0 || operand & 0xFFFF0000 == 0xFFFF0000 { 797 2 798 } else if operand & 0xFF000000 == 0 || operand & 0xFF000000 == 0xFF000000 { 799 3 800 } else { 801 4 802 }; 803 804 let i_cycles = m + u32::from(accumulate); 805 bus.internal_cycles(i_cycles); 806 } 807 808 fn arm_multiply_long(&mut self, opcode: u32, bus: &mut Bus) { 809 let rm = opcode & 0xF; 810 let rs = (opcode >> 8) & 0xF; 811 let rdlo = (opcode >> 12) & 0xF; 812 let rdhi = (opcode >> 16) & 0xF; 813 let set_condition_codes = opcode.bit(20); 814 let accumulate = opcode.bit(21); 815 let signed = opcode.bit(22); 816 817 self.multiply_long(rm, rs, rdlo, rdhi, set_condition_codes, accumulate, signed, bus); 818 } 819 820 #[inline] 821 #[allow(clippy::too_many_arguments)] 822 fn multiply_long( 823 &mut self, 824 rm: u32, 825 rs: u32, 826 rdlo: u32, 827 rdhi: u32, 828 set_condition_codes: bool, 829 accumulate: bool, 830 signed: bool, 831 bus: &mut Bus, 832 ) { 833 let operand = self.registers.r[rs as usize]; 834 let product = if signed { 835 let mut product = 836 i64::from(self.registers.r[rm as usize] as i32) * i64::from(operand as i32); 837 if accumulate { 838 let existing = (i64::from(self.registers.r[rdhi as usize]) << 32) 839 | i64::from(self.registers.r[rdlo as usize]); 840 product = product.wrapping_add(existing); 841 } 842 product as u64 843 } else { 844 let mut product = u64::from(self.registers.r[rm as usize]) * u64::from(operand); 845 if accumulate { 846 let existing = (u64::from(self.registers.r[rdhi as usize]) << 32) 847 | u64::from(self.registers.r[rdlo as usize]); 848 product = product.wrapping_add(existing); 849 } 850 product 851 }; 852 853 self.registers.r[rdlo as usize] = product as u32; 854 self.registers.r[rdhi as usize] = (product >> 32) as u32; 855 856 if set_condition_codes { 857 self.registers.cpsr.sign = product.bit(63); 858 self.registers.cpsr.zero = product == 0; 859 // TODO carry and overflow flags? 860 } 861 862 let m = if operand & 0xFFFFFF00 == 0 || (signed && operand & 0xFFFFFF00 == 0xFFFFFF00) { 863 1 864 } else if operand & 0xFFFF0000 == 0 || (signed && operand & 0xFFFF0000 == 0xFFFF0000) { 865 2 866 } else if operand & 0xFF000000 == 0 || (signed && operand & 0xFF000000 == 0xFF000000) { 867 3 868 } else { 869 4 870 }; 871 872 let i_cycles = 1 + m + u32::from(accumulate); 873 bus.internal_cycles(i_cycles); 874 } 875 876 // LDR: Load word 877 // STR: Store word 878 fn arm_load_word<const LOAD: bool, const REGISTER_OFFSET: bool>( 879 &mut self, 880 opcode: u32, 881 bus: &mut Bus, 882 ) { 883 let indexing = LoadIndexing::from_bit(opcode.bit(24)); 884 let index_op = IndexOp::from_bit(opcode.bit(23)); 885 let size = LoadSize::from_bit(opcode.bit(22)); 886 let write_back = WriteBack::from_bit(opcode.bit(21)); 887 let rn = (opcode >> 16) & 0xF; 888 let rd = (opcode >> 12) & 0xF; 889 890 let offset = if REGISTER_OFFSET { 891 let rm = opcode & 0xF; 892 let value = self.registers.r[rm as usize]; 893 let shift_type = ShiftType::from_bits(opcode >> 5); 894 let shift = (opcode >> 7) & 0x1F; 895 896 let (shifted, _) = 897 apply_immediate_shift(value, shift_type, shift, self.registers.cpsr.carry); 898 shifted 899 } else { 900 opcode & 0xFFF 901 }; 902 903 self.load_word::<LOAD>(rn, rd, offset, size, indexing, index_op, write_back, bus); 904 } 905 906 #[inline] 907 #[allow(clippy::too_many_arguments)] 908 fn load_word<const LOAD: bool>( 909 &mut self, 910 rn: u32, 911 rd: u32, 912 mut offset: u32, 913 size: LoadSize, 914 indexing: LoadIndexing, 915 index_op: IndexOp, 916 write_back: WriteBack, 917 bus: &mut Bus, 918 ) { 919 if index_op == IndexOp::Subtract { 920 offset = (!offset).wrapping_add(1); 921 } 922 923 let mut address = self.read_register(rn); 924 925 if indexing == LoadIndexing::Pre { 926 address = address.wrapping_add(offset); 927 } 928 929 if LOAD { 930 self.registers.r[rd as usize] = match size { 931 LoadSize::Word => { 932 let word = bus.read_word(address, MemoryCycle::N); 933 word.rotate_right(8 * (address & 3)) 934 } 935 LoadSize::Byte => bus.read_byte(address, MemoryCycle::N).into(), 936 }; 937 938 bus.internal_cycles(1); 939 940 if rd == 15 { 941 self.refill_prefetch(bus); 942 } 943 } else { 944 let value = self.registers.r[rd as usize]; 945 match size { 946 LoadSize::Word => bus.write_word(address, value, MemoryCycle::N), 947 LoadSize::Byte => bus.write_byte(address, value as u8, MemoryCycle::N), 948 } 949 950 // Next opcode fetch is N 951 self.fetch_cycle = MemoryCycle::N; 952 } 953 954 // Write back only applies on loads if the base register and destination register are different 955 if !(LOAD && rn == rd) { 956 if indexing == LoadIndexing::Post { 957 self.registers.r[rn as usize] = address.wrapping_add(offset); 958 if rn == 15 { 959 self.refill_prefetch(bus); 960 } 961 } else if write_back == WriteBack::Yes { 962 self.registers.r[rn as usize] = address; 963 if rn == 15 { 964 self.refill_prefetch(bus); 965 } 966 } 967 } 968 } 969 970 // LDRH: Load halfword 971 // STRH: Store halfword 972 // LDRSB: Load sign-extended byte 973 // LDRSH: Load sign-extended halfword 974 fn arm_load_halfword<const LOAD: bool, const IMMEDIATE_OFFSET: bool>( 975 &mut self, 976 opcode: u32, 977 bus: &mut Bus, 978 ) { 979 let indexing = LoadIndexing::from_bit(opcode.bit(24)); 980 let index_op = IndexOp::from_bit(opcode.bit(23)); 981 let write_back = WriteBack::from_bit(opcode.bit(21)); 982 let rn = (opcode >> 16) & 0xF; 983 let rd = (opcode >> 12) & 0xF; 984 985 let offset = if IMMEDIATE_OFFSET { 986 ((opcode >> 4) & 0xF0) | (opcode & 0xF) 987 } else { 988 let rm = opcode & 0xF; 989 self.read_register(rm) 990 }; 991 992 let Some(load_type) = HalfwordLoadType::from_bits(opcode >> 5) else { 993 // TODO this is definitely not correct; how should these opcodes decode? 994 return self.arm_swap(opcode, bus); 995 }; 996 997 self.load_halfword::<LOAD>(rn, rd, offset, load_type, indexing, index_op, write_back, bus); 998 } 999 1000 #[inline] 1001 #[allow(clippy::too_many_arguments)] 1002 fn load_halfword<const LOAD: bool>( 1003 &mut self, 1004 rn: u32, 1005 rd: u32, 1006 mut offset: u32, 1007 load_type: HalfwordLoadType, 1008 indexing: LoadIndexing, 1009 index_op: IndexOp, 1010 write_back: WriteBack, 1011 bus: &mut Bus, 1012 ) { 1013 if index_op == IndexOp::Subtract { 1014 offset = (!offset).wrapping_add(1); 1015 } 1016 1017 let mut address = self.read_register(rn); 1018 if indexing == LoadIndexing::Pre { 1019 address = address.wrapping_add(offset); 1020 } 1021 1022 if LOAD { 1023 let value = match load_type { 1024 HalfwordLoadType::UnsignedHalfword => { 1025 let halfword: u32 = bus.read_halfword(address, MemoryCycle::N).into(); 1026 halfword.rotate_right(8 * (address & 1)) 1027 } 1028 HalfwordLoadType::SignedByte => bus.read_byte(address, MemoryCycle::N) as i8 as u32, 1029 HalfwordLoadType::SignedHalfword => { 1030 if !address.bit(0) { 1031 bus.read_halfword(address, MemoryCycle::N) as i16 as u32 1032 } else { 1033 // Unaligned LDRSH seems to behave the same as LDRSB 1034 bus.read_byte(address, MemoryCycle::N) as i8 as u32 1035 } 1036 } 1037 }; 1038 self.registers.r[rd as usize] = value; 1039 1040 bus.internal_cycles(1); 1041 1042 if rd == 15 { 1043 self.refill_prefetch(bus); 1044 } 1045 } else { 1046 let halfword = self.registers.r[rd as usize] as u16; 1047 bus.write_halfword(address, halfword, MemoryCycle::N); 1048 1049 // Next opcode fetch is N 1050 self.fetch_cycle = MemoryCycle::N; 1051 } 1052 1053 // Write back only applies on loads if the base register and destination register are different 1054 if !(LOAD && rn == rd) { 1055 if indexing == LoadIndexing::Post { 1056 self.registers.r[rn as usize] = address.wrapping_add(offset); 1057 } else if write_back == WriteBack::Yes { 1058 self.registers.r[rn as usize] = address; 1059 } 1060 } 1061 } 1062 1063 fn arm_ldm_stm<const LOAD: bool, const INCREMENT: bool, const AFTER: bool>( 1064 &mut self, 1065 opcode: u32, 1066 bus: &mut Bus, 1067 ) { 1068 let register_bits = opcode & 0xFFFF; 1069 let rn = (opcode >> 16) & 0xF; 1070 let write_back = WriteBack::from_bit(opcode.bit(21)); 1071 let s_bit = opcode.bit(22); 1072 1073 self.load_multiple::<LOAD, INCREMENT, AFTER>(register_bits, rn, write_back, s_bit, bus); 1074 } 1075 1076 #[inline] 1077 fn load_multiple<const LOAD: bool, const INCREMENT: bool, const AFTER: bool>( 1078 &mut self, 1079 mut register_bits: u32, 1080 rn: u32, 1081 write_back: WriteBack, 1082 s_bit: bool, 1083 bus: &mut Bus, 1084 ) { 1085 let mut empty_list = false; 1086 if register_bits == 0 { 1087 // Hardware quirk: empty list loads/stores only R15, and Rb is adjusted by 4 * 16 1088 register_bits = 1 << 15; 1089 empty_list = true; 1090 } 1091 1092 let count = register_bits.count_ones(); 1093 let r15_loaded = register_bits.bit(15); 1094 1095 let base_addr = self.read_register(rn); 1096 let count_for_final_addr = if empty_list { 16 } else { count }; 1097 let final_addr = if INCREMENT { 1098 base_addr.wrapping_add(4 * count_for_final_addr) 1099 } else { 1100 base_addr.wrapping_sub(4 * count_for_final_addr) 1101 }; 1102 1103 let mut address = if INCREMENT { base_addr } else { final_addr }; 1104 1105 let mut first = true; 1106 let mut need_write_back = write_back == WriteBack::Yes; 1107 for r in 0..16 { 1108 if !register_bits.bit(r) { 1109 continue; 1110 } 1111 1112 let memory_cycle = if first { 1113 first = false; 1114 MemoryCycle::N 1115 } else { 1116 MemoryCycle::S 1117 }; 1118 1119 if LOAD && need_write_back { 1120 self.registers.r[rn as usize] = final_addr; 1121 log::trace!(" Wrote back to R{rn}: {:08X}", self.registers.r[rn as usize]); 1122 need_write_back = false; 1123 } 1124 1125 if !(AFTER ^ !INCREMENT) { 1126 address = address.wrapping_add(4); 1127 } 1128 1129 if LOAD { 1130 if r == 15 { 1131 self.registers.r[15] = bus.read_word(address, memory_cycle); 1132 1133 if s_bit { 1134 self.spsr_to_cpsr(); 1135 } 1136 } else if s_bit && !r15_loaded { 1137 let register = get_user_register(&mut self.registers, r.into()); 1138 *register = bus.read_word(address, memory_cycle); 1139 } else { 1140 self.registers.r[r as usize] = bus.read_word(address, memory_cycle); 1141 } 1142 log::trace!(" LDM: Loaded R{r} from {address:08X}"); 1143 } else { 1144 let value = if s_bit { 1145 *get_user_register(&mut self.registers, r.into()) 1146 } else { 1147 self.registers.r[r as usize] 1148 }; 1149 bus.write_word(address, value, memory_cycle); 1150 log::trace!(" STM: Stored R{r} to {address:08X}"); 1151 } 1152 1153 if AFTER ^ !INCREMENT { 1154 address = address.wrapping_add(4); 1155 } 1156 1157 if !LOAD && need_write_back { 1158 self.registers.r[rn as usize] = final_addr; 1159 log::trace!(" Wrote back to R{rn}: {:08X}", self.registers.r[rn as usize]); 1160 need_write_back = false; 1161 } 1162 } 1163 1164 if LOAD { 1165 bus.internal_cycles(1); 1166 1167 if r15_loaded { 1168 self.refill_prefetch(bus); 1169 } 1170 } else { 1171 // Next opcode fetch is N 1172 self.fetch_cycle = MemoryCycle::N; 1173 } 1174 } 1175 1176 fn arm_swi(&mut self, _opcode: u32, bus: &mut Bus) { 1177 self.handle_exception(Exception::SoftwareInterrupt, bus); 1178 } 1179 1180 // Format 1: Move shifted register 1181 fn thumb_move_shifted_register(&mut self, opcode: u16, bus: &mut Bus) { 1182 let rd = opcode & 7; 1183 let rs = (opcode >> 3) & 7; 1184 let shift = (opcode >> 6) & 0x1F; 1185 let shift_type = ShiftType::from_bits((opcode >> 11).into()); 1186 1187 self.alu_immediate_shift( 1188 AluOp::Move, 1189 rd.into(), 1190 rd.into(), 1191 true, 1192 rs.into(), 1193 shift_type, 1194 shift.into(), 1195 bus, 1196 ); 1197 } 1198 1199 // Format 2: Add/subtract 1200 fn thumb_add_sub(&mut self, opcode: u16, bus: &mut Bus) { 1201 let rd = opcode & 7; 1202 let rs = (opcode >> 3) & 7; 1203 let rn = (opcode >> 6) & 7; 1204 let alu_op = if opcode.bit(9) { AluOp::Subtract } else { AluOp::Add }; 1205 1206 let immediate = opcode.bit(10); 1207 if immediate { 1208 self.alu_rotated_immediate(alu_op, rs.into(), rd.into(), true, rn.into(), 0, bus); 1209 } else { 1210 self.alu_immediate_shift( 1211 alu_op, 1212 rs.into(), 1213 rd.into(), 1214 true, 1215 rn.into(), 1216 ShiftType::Left, 1217 0, 1218 bus, 1219 ); 1220 } 1221 } 1222 1223 // Format 3: Move/compare/add/subtract immediate 1224 fn thumb_alu_immediate(&mut self, opcode: u16, bus: &mut Bus) { 1225 let immediate = opcode & 0xFF; 1226 let rd = (opcode >> 8) & 7; 1227 let alu_op = match (opcode >> 11) & 3 { 1228 0 => AluOp::Move, 1229 1 => AluOp::Compare, 1230 2 => AluOp::Add, 1231 3 => AluOp::Subtract, 1232 _ => unreachable!("value & 3 is always <= 3"), 1233 }; 1234 1235 self.alu_rotated_immediate(alu_op, rd.into(), rd.into(), true, immediate.into(), 0, bus); 1236 } 1237 1238 // Format 4: ALU operations 1239 fn thumb_alu(&mut self, opcode: u16, bus: &mut Bus) { 1240 let rd = opcode & 7; 1241 let rs = (opcode >> 3) & 7; 1242 1243 let basic_op = match (opcode >> 6) & 0xF { 1244 0x0 => AluOp::And, 1245 0x1 => AluOp::ExclusiveOr, 1246 op @ (0x2..=0x4 | 0x7) => { 1247 // LSL/LSR/ASR/ROR 1248 let shift_type = match op { 1249 2 => ShiftType::Left, 1250 3 => ShiftType::LogicalRight, 1251 4 => ShiftType::ArithmeticRight, 1252 7 => ShiftType::RotateRight, 1253 _ => unreachable!("nested match expressions"), 1254 }; 1255 1256 return self.alu_register_shift::<THUMB_OPCODE_LEN>( 1257 AluOp::Move, 1258 rd.into(), 1259 rd.into(), 1260 true, 1261 rd.into(), 1262 shift_type, 1263 rs.into(), 1264 bus, 1265 ); 1266 } 1267 0x5 => AluOp::AddCarry, 1268 0x6 => AluOp::SubtractCarry, 1269 0x8 => AluOp::Test, 1270 0x9 => { 1271 // NEG 1272 return self.alu_rotated_immediate( 1273 AluOp::ReverseSubtract, 1274 rs.into(), 1275 rd.into(), 1276 true, 1277 0, 1278 0, 1279 bus, 1280 ); 1281 } 1282 0xA => AluOp::Compare, 1283 0xB => AluOp::CompareNegate, 1284 0xC => AluOp::Or, 1285 0xD => { 1286 // MUL 1287 return self.multiply(rs.into(), rd.into(), rd.into(), rd.into(), true, false, bus); 1288 } 1289 0xE => AluOp::BitClear, 1290 0xF => AluOp::MoveNegate, 1291 _ => unreachable!("value & 0xF is always <= 0xF"), 1292 }; 1293 1294 self.alu_immediate_shift( 1295 basic_op, 1296 rd.into(), 1297 rd.into(), 1298 true, 1299 rs.into(), 1300 ShiftType::Left, 1301 0, 1302 bus, 1303 ); 1304 } 1305 1306 // Format 5: Hi register operations / branch exchange 1307 fn thumb_high_register_op(&mut self, opcode: u16, bus: &mut Bus) { 1308 let mut rd = opcode & 7; 1309 let mut rs = (opcode >> 3) & 7; 1310 1311 if opcode.bit(6) { 1312 rs += 8; 1313 } 1314 1315 if opcode.bit(7) { 1316 rd += 8; 1317 } 1318 1319 let alu_op = match (opcode >> 8) & 3 { 1320 0 => AluOp::Add, 1321 1 => AluOp::Compare, 1322 2 => AluOp::Move, 1323 3 => return self.branch_exchange(rs.into(), bus), 1324 _ => unreachable!("value & 3 is always <= 3"), 1325 }; 1326 1327 let set_condition_codes = alu_op == AluOp::Compare; 1328 1329 self.alu_immediate_shift( 1330 alu_op, 1331 rd.into(), 1332 rd.into(), 1333 set_condition_codes, 1334 rs.into(), 1335 ShiftType::Left, 1336 0, 1337 bus, 1338 ); 1339 } 1340 1341 // Format 6: PC-relative load 1342 fn thumb_pc_relative_load(&mut self, opcode: u16, bus: &mut Bus) { 1343 // Bit 1 of PC is forcibly cleared for PC-relative loads 1344 let mut offset: u32 = ((opcode & 0xFF) << 2).into(); 1345 offset = offset.wrapping_sub(self.prev_r15 & 2); 1346 1347 let rd = (opcode >> 8) & 7; 1348 1349 self.load_word::<true>( 1350 15, 1351 rd.into(), 1352 offset, 1353 LoadSize::Word, 1354 LoadIndexing::Pre, 1355 IndexOp::Add, 1356 WriteBack::No, 1357 bus, 1358 ); 1359 } 1360 1361 // Format 7: Load/store with register offset 1362 fn thumb_load_register_offset(&mut self, opcode: u16, bus: &mut Bus) { 1363 let rd = opcode & 7; 1364 let rb = (opcode >> 3) & 7; 1365 let ro = (opcode >> 6) & 7; 1366 let size = LoadSize::from_bit(opcode.bit(10)); 1367 let load = opcode.bit(11); 1368 1369 let offset = self.read_register(ro.into()); 1370 1371 if load { 1372 self.load_word::<true>( 1373 rb.into(), 1374 rd.into(), 1375 offset, 1376 size, 1377 LoadIndexing::Pre, 1378 IndexOp::Add, 1379 WriteBack::No, 1380 bus, 1381 ); 1382 } else { 1383 self.load_word::<false>( 1384 rb.into(), 1385 rd.into(), 1386 offset, 1387 size, 1388 LoadIndexing::Pre, 1389 IndexOp::Add, 1390 WriteBack::No, 1391 bus, 1392 ); 1393 } 1394 } 1395 1396 // Format 8: Load/store sign-extended byte/halfword 1397 fn thumb_load_sign_extended(&mut self, opcode: u16, bus: &mut Bus) { 1398 let rd = opcode & 7; 1399 let rb = (opcode >> 3) & 7; 1400 let ro = (opcode >> 6) & 7; 1401 1402 let offset = self.read_register(ro.into()); 1403 1404 let sh_bits = (opcode >> 10) & 3; 1405 if sh_bits == 0 { 1406 // STRH 1407 self.load_halfword::<false>( 1408 rb.into(), 1409 rd.into(), 1410 offset, 1411 HalfwordLoadType::UnsignedHalfword, 1412 LoadIndexing::Pre, 1413 IndexOp::Add, 1414 WriteBack::No, 1415 bus, 1416 ); 1417 } else { 1418 let load_type = match sh_bits { 1419 1 => HalfwordLoadType::SignedByte, 1420 2 => HalfwordLoadType::UnsignedHalfword, 1421 3 => HalfwordLoadType::SignedHalfword, 1422 _ => unreachable!(), 1423 }; 1424 1425 self.load_halfword::<true>( 1426 rb.into(), 1427 rd.into(), 1428 offset, 1429 load_type, 1430 LoadIndexing::Pre, 1431 IndexOp::Add, 1432 WriteBack::No, 1433 bus, 1434 ); 1435 } 1436 } 1437 1438 // Format 9: Load/store with immediate offset 1439 fn thumb_load_immediate_offset(&mut self, opcode: u16, bus: &mut Bus) { 1440 let rd = opcode & 7; 1441 let rb = (opcode >> 3) & 7; 1442 let mut offset = (opcode >> 6) & 0x1F; 1443 let load = opcode.bit(11); 1444 let size = LoadSize::from_bit(opcode.bit(12)); 1445 1446 if size == LoadSize::Word { 1447 offset <<= 2; 1448 } 1449 1450 if load { 1451 self.load_word::<true>( 1452 rb.into(), 1453 rd.into(), 1454 offset.into(), 1455 size, 1456 LoadIndexing::Pre, 1457 IndexOp::Add, 1458 WriteBack::No, 1459 bus, 1460 ); 1461 } else { 1462 self.load_word::<false>( 1463 rb.into(), 1464 rd.into(), 1465 offset.into(), 1466 size, 1467 LoadIndexing::Pre, 1468 IndexOp::Add, 1469 WriteBack::No, 1470 bus, 1471 ); 1472 } 1473 } 1474 1475 // Format 10: Load/store halfword 1476 fn thumb_load_halfword(&mut self, opcode: u16, bus: &mut Bus) { 1477 let rd = opcode & 7; 1478 let rb = (opcode >> 3) & 7; 1479 let offset = ((opcode >> 6) & 0x1F) << 1; 1480 let load = opcode.bit(11); 1481 1482 if load { 1483 self.load_halfword::<true>( 1484 rb.into(), 1485 rd.into(), 1486 offset.into(), 1487 HalfwordLoadType::UnsignedHalfword, 1488 LoadIndexing::Pre, 1489 IndexOp::Add, 1490 WriteBack::No, 1491 bus, 1492 ); 1493 } else { 1494 self.load_halfword::<false>( 1495 rb.into(), 1496 rd.into(), 1497 offset.into(), 1498 HalfwordLoadType::UnsignedHalfword, 1499 LoadIndexing::Pre, 1500 IndexOp::Add, 1501 WriteBack::No, 1502 bus, 1503 ); 1504 } 1505 } 1506 1507 // Format 11: SP-relative load/store 1508 fn thumb_load_sp_relative(&mut self, opcode: u16, bus: &mut Bus) { 1509 let offset = (opcode & 0xFF) << 2; 1510 let rd = (opcode >> 8) & 7; 1511 let load = opcode.bit(11); 1512 1513 if load { 1514 self.load_word::<true>( 1515 13, 1516 rd.into(), 1517 offset.into(), 1518 LoadSize::Word, 1519 LoadIndexing::Pre, 1520 IndexOp::Add, 1521 WriteBack::No, 1522 bus, 1523 ); 1524 } else { 1525 self.load_word::<false>( 1526 13, 1527 rd.into(), 1528 offset.into(), 1529 LoadSize::Word, 1530 LoadIndexing::Pre, 1531 IndexOp::Add, 1532 WriteBack::No, 1533 bus, 1534 ); 1535 } 1536 } 1537 1538 // Format 12: Load address 1539 fn thumb_load_address(&mut self, opcode: u16, bus: &mut Bus) { 1540 let mut immediate: u32 = ((opcode & 0xFF) << 2).into(); 1541 let rd = (opcode >> 8) & 7; 1542 1543 // Bit 11 selects between SP (R13) and PC (R15) 1544 let rn = if opcode.bit(11) { 13 } else { 15 }; 1545 1546 // Bit 1 is forced clear when PC is used as Rn 1547 if rn == 15 { 1548 immediate = immediate.wrapping_sub(self.prev_r15 & 2); 1549 } 1550 1551 self.alu_rotated_immediate(AluOp::Add, rn, rd.into(), false, immediate, 0, bus); 1552 } 1553 1554 // Format 13: Add offset to stack pointer 1555 fn thumb_add_offset_sp(&mut self, opcode: u16, bus: &mut Bus) { 1556 let mut offset: u32 = ((opcode & 0x7F) << 2).into(); 1557 if opcode.bit(7) { 1558 offset = (!offset).wrapping_add(1); 1559 } 1560 1561 self.alu_rotated_immediate(AluOp::Add, 13, 13, false, offset, 0, bus); 1562 } 1563 1564 // Format 14: Push/pop registers 1565 fn thumb_push_pop(&mut self, opcode: u16, bus: &mut Bus) { 1566 let lr_pc_bit = opcode.bit(8); 1567 let load = opcode.bit(11); 1568 1569 let mut register_bits = opcode & 0xFF; 1570 if lr_pc_bit { 1571 // Store LR, load PC 1572 register_bits |= 1 << (14 + u32::from(load)); 1573 } 1574 1575 if load { 1576 self.load_multiple::<true, true, true>( 1577 register_bits.into(), 1578 13, 1579 WriteBack::Yes, 1580 false, 1581 bus, 1582 ); 1583 } else { 1584 self.load_multiple::<false, false, false>( 1585 register_bits.into(), 1586 13, 1587 WriteBack::Yes, 1588 false, 1589 bus, 1590 ); 1591 } 1592 } 1593 1594 // Format 15: Multiple load/store 1595 fn thumb_load_multiple(&mut self, opcode: u16, bus: &mut Bus) { 1596 let register_bits = opcode & 0xFF; 1597 let rb = (opcode >> 8) & 7; 1598 let load = opcode.bit(11); 1599 1600 if load { 1601 self.load_multiple::<true, true, true>( 1602 register_bits.into(), 1603 rb.into(), 1604 WriteBack::Yes, 1605 false, 1606 bus, 1607 ); 1608 } else { 1609 self.load_multiple::<false, true, true>( 1610 register_bits.into(), 1611 rb.into(), 1612 WriteBack::Yes, 1613 false, 1614 bus, 1615 ); 1616 } 1617 } 1618 1619 // Format 16: Conditional branch 1620 fn thumb_conditional_branch(&mut self, opcode: u16, bus: &mut Bus) { 1621 let condition = Condition::from_bits((opcode >> 8).into()); 1622 if !condition.check(self.registers.cpsr) { 1623 return; 1624 } 1625 1626 let offset = i32::from(opcode as i8) << 1; 1627 self.branch::<false, THUMB_OPCODE_LEN>(offset, bus); 1628 } 1629 1630 // Format 17: Software interrupt 1631 fn thumb_software_interrupt(&mut self, _opcode: u16, bus: &mut Bus) { 1632 self.handle_exception(Exception::SoftwareInterrupt, bus); 1633 } 1634 1635 // Format 18: Unconditional branch 1636 fn thumb_unconditional_branch(&mut self, opcode: u16, bus: &mut Bus) { 1637 let offset = (i32::from(opcode & 0x7FF) << 21) >> 20; 1638 self.branch::<false, THUMB_OPCODE_LEN>(offset, bus); 1639 } 1640 1641 // Format 19: Long branch with link 1642 // This instruction has no ARM equivalent 1643 fn thumb_long_branch(&mut self, opcode: u16, bus: &mut Bus) { 1644 // Offset is a signed 23-bit value split across two opcodes, with 11 bits in each 1645 // First opcode has H=0 and second opcode has H=1 1646 // It is possible to have an H=1 opcode without an H=0 opcode; Golden Sun: The Lost Age does this 1647 if !opcode.bit(11) { 1648 // First opcode: Write highest 11 bits of jump address to LR 1649 let unsigned_offset = i32::from(opcode & 0x7FF) << 12; 1650 1651 // Clip to signed 23-bit 1652 let offset = (unsigned_offset << 9) >> 9; 1653 1654 self.registers.r[14] = self.prev_r15.wrapping_add_signed(offset); 1655 } else { 1656 // Second opcode: Add lowest 11 bits of jump address to LR, jump, and write return address to LR 1657 let offset_low = u32::from(opcode & 0x7FF) << 1; 1658 let jump_address = self.registers.r[14].wrapping_add(offset_low); 1659 1660 let return_address = self.prev_r15.wrapping_sub(2); 1661 self.registers.r[14] = return_address | 1; 1662 1663 self.registers.r[15] = jump_address; 1664 self.refill_prefetch(bus); 1665 } 1666 } 1667} 1668 1669#[inline] 1670fn arm_parse_rotated_immediate(opcode: u32) -> (u32, u32) { 1671 let immediate = opcode & 0xFF; 1672 let rotation = ((opcode >> 8) & 0xF) << 1; 1673 (immediate, rotation) 1674} 1675 1676fn apply_immediate_shift( 1677 value: u32, 1678 shift_type: ShiftType, 1679 shift: u32, 1680 carry_in: bool, 1681) -> (u32, bool) { 1682 match (shift_type, shift) { 1683 (ShiftType::Left, 0) => (value, carry_in), 1684 (ShiftType::Left, _) => (value << shift, value.bit((32 - shift) as u8)), 1685 (ShiftType::LogicalRight, 0) => (0, value.bit(31)), 1686 (ShiftType::LogicalRight, _) => (value >> shift, value.bit((shift - 1) as u8)), 1687 (ShiftType::ArithmeticRight, 0) => (((value as i32) >> 31) as u32, value.bit(31)), 1688 (ShiftType::ArithmeticRight, _) => { 1689 (((value as i32) >> shift) as u32, value.bit((shift - 1) as u8)) 1690 } 1691 (ShiftType::RotateRight, 0) => { 1692 // RRX: Rotate right through carry 1693 let result = (value >> 1) | (u32::from(carry_in) << 31); 1694 (result, value.bit(0)) 1695 } 1696 (ShiftType::RotateRight, _) => (value.rotate_right(shift), value.bit((shift - 1) as u8)), 1697 } 1698} 1699 1700fn alu_add(operand1: u32, operand2: u32, carry_in: bool) -> (u32, ConditionCodes) { 1701 let carry_in: u32 = carry_in.into(); 1702 1703 let (partial_sum, carry1) = operand1.overflowing_add(operand2); 1704 let (sum, carry2) = partial_sum.overflowing_add(carry_in); 1705 let carry = carry1 || carry2; 1706 1707 let bit_30_carry = (operand1 & 0x7FFFFFFF) + (operand2 & 0x7FFFFFFF) + carry_in >= 0x80000000; 1708 let overflow = bit_30_carry != carry; 1709 1710 (sum, ConditionCodes { sign: sum.bit(31), zero: sum == 0, carry, overflow }) 1711} 1712 1713fn get_user_register(registers: &mut Registers, r: u32) -> &mut u32 { 1714 match (registers.cpsr.mode, r) { 1715 (CpuMode::User | CpuMode::System, _) => &mut registers.r[r as usize], 1716 (CpuMode::Fiq, 8..=12) => &mut registers.other_r_8_12[(r - 8) as usize], 1717 (_, 13) => &mut registers.r13_usr, 1718 (_, 14) => &mut registers.r14_usr, 1719 _ => &mut registers.r[r as usize], 1720 } 1721}