Skip to content

Commit ef05f02

Browse files
committed
Rework block invalidation
* Optimize jit addr lookup
1 parent bbb3a00 commit ef05f02

28 files changed

+528
-651
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ assets = "./static"
1515
[dependencies]
1616
bilge = { git = "https://github.com/Grarak/bilge.git" }
1717
chrono = "0.4.38"
18-
paste = "1.0.15"
19-
static_assertions = "1.1.0"
2018
dsvita_macros = { path = "macros" }
2119
gl = { git = "https://github.com/bjz/gl-rs" }
2220
glyph_brush = "0.7.9"
21+
lazy_static = "1.5.0"
2322
rust-ini = "0.21.1"
23+
static_assertions = "1.1.0"
24+
paste = "1.0.15"
2425

2526
[target.armv7-unknown-linux-gnueabihf.dependencies]
2627
clap = { version = "4.5.17", features = ["cargo"] }

src/core/memory/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ impl Main {
2525
}
2626

2727
pub fn write_slice<T: Convert>(&mut self, addr_offset: u32, slice: &[T]) {
28-
utils::write_to_mem_slice(self.main.deref_mut(), addr_offset & (regions::MAIN_MEMORY_SIZE - 1), slice);
28+
utils::write_to_mem_slice(self.main.deref_mut(), (addr_offset & (regions::MAIN_MEMORY_SIZE - 1)) as usize, slice);
2929
}
3030
}

src/core/memory/mem.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::core::cp15::TcmState;
2-
use crate::core::emu::{get_cp15, Emu};
2+
use crate::core::emu::{get_cp15, get_regs, Emu};
33
use crate::core::memory::bios::{BiosArm7, BiosArm9};
44
use crate::core::memory::io_arm7::IoArm7;
55
use crate::core::memory::io_arm9::IoArm9;
@@ -15,7 +15,7 @@ use crate::core::memory::wram::Wram;
1515
use crate::core::spu::SoundSampler;
1616
use crate::core::CpuType;
1717
use crate::core::CpuType::ARM9;
18-
use crate::jit::jit_memory::JitMemory;
18+
use crate::jit::jit_memory::{JitMemory, JitRegion};
1919
use crate::logging::debug_println;
2020
use crate::utils::Convert;
2121
use std::intrinsics::{likely, unlikely};
@@ -36,7 +36,6 @@ pub struct Memory {
3636
pub jit: JitMemory,
3737
pub bios_arm9: BiosArm9,
3838
pub bios_arm7: BiosArm7,
39-
pub current_jit_block_addr: u32, // Check if the jit block we are currently executing gets written to
4039
pub breakout_imm: bool,
4140
pub mmu_arm9: MmuArm9,
4241
pub mmu_arm7: MmuArm7,
@@ -66,7 +65,6 @@ impl Memory {
6665
jit: JitMemory::new(),
6766
bios_arm9: BiosArm9::new(),
6867
bios_arm7: BiosArm7::new(),
69-
current_jit_block_addr: 0,
7068
breakout_imm: false,
7169
mmu_arm9: MmuArm9::new(),
7270
mmu_arm7: MmuArm7::new(),
@@ -199,8 +197,6 @@ impl Memory {
199197
}
200198
}
201199

202-
let mut invalidate_jit = || self.breakout_imm = self.jit.invalidate_block::<CPU>(aligned_addr, size_of::<T>(), self.current_jit_block_addr);
203-
204200
match addr_base {
205201
regions::INSTRUCTION_TCM_OFFSET | regions::INSTRUCTION_TCM_MIRROR_OFFSET => match CPU {
206202
ARM9 => {
@@ -209,7 +205,7 @@ impl Memory {
209205
if aligned_addr < cp15.itcm_size && cp15.itcm_state != TcmState::Disabled {
210206
self.tcm.write_itcm(aligned_addr, value);
211207
debug_println!("{:?} itcm write at {:x} with value {:x}", CPU, aligned_addr, value.into(),);
212-
invalidate_jit();
208+
self.breakout_imm = self.jit.invalidate_block::<{ JitRegion::Itcm }>(aligned_addr, size_of::<T>(), get_regs!(emu, CPU).pc);
213209
}
214210
}
215211
}
@@ -220,12 +216,12 @@ impl Memory {
220216
},
221217
regions::MAIN_MEMORY_OFFSET => {
222218
self.main.write(addr_offset, value);
223-
invalidate_jit();
219+
self.breakout_imm = self.jit.invalidate_block::<{ JitRegion::Main }>(aligned_addr, size_of::<T>(), get_regs!(emu, CPU).pc);
224220
}
225221
regions::SHARED_WRAM_OFFSET => {
226222
self.wram.write::<CPU, _>(addr_offset, value);
227223
if CPU == ARM7 {
228-
invalidate_jit();
224+
self.breakout_imm = self.jit.invalidate_block::<{ JitRegion::Wram }>(aligned_addr, size_of::<T>(), get_regs!(emu, CPU).pc);
229225
}
230226
}
231227
regions::IO_PORTS_OFFSET => match CPU {
@@ -247,7 +243,7 @@ impl Memory {
247243
regions::VRAM_OFFSET => {
248244
self.vram.write::<CPU, _>(addr_offset, value);
249245
if CPU == ARM7 {
250-
invalidate_jit();
246+
self.breakout_imm = self.jit.invalidate_block::<{ JitRegion::VramArm7 }>(aligned_addr, size_of::<T>(), get_regs!(emu, CPU).pc);
251247
}
252248
}
253249
regions::OAM_OFFSET => self.oam.write(addr_offset, value),

src/core/rtc.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,25 @@ impl Rtc {
135135
fn update_date_time(&mut self) {
136136
let local_now = chrono::Local::now();
137137

138-
let year = local_now.year() as u32 % 100;
139-
let month = local_now.month() as u8;
140-
let day = local_now.day() as u8;
141-
let (hour, is_pm) = {
142-
let hour = local_now.hour();
143-
((if self.cnt & 0x2 == 0 { hour % 12 } else { hour }) as u8, hour >= 12)
144-
};
145-
let min = local_now.minute() as u8;
146-
let sec = local_now.second() as u8;
147-
148-
// let year = 2000 as u32 % 100;
149-
// let month = 1 as u8;
150-
// let day = 1 as u8;
138+
// let year = local_now.year() as u32 % 100;
139+
// let month = local_now.month() as u8;
140+
// let day = local_now.day() as u8;
151141
// let (hour, is_pm) = {
152-
// let hour = 11;
142+
// let hour = local_now.hour();
153143
// ((if self.cnt & 0x2 == 0 { hour % 12 } else { hour }) as u8, hour >= 12)
154144
// };
155-
// let min = 0 as u8;
156-
// let sec = 0 as u8;
145+
// let min = local_now.minute() as u8;
146+
// let sec = local_now.second() as u8;
147+
148+
let year = 2000 as u32 % 100;
149+
let month = 1 as u8;
150+
let day = 1 as u8;
151+
let (hour, is_pm) = {
152+
let hour = 11;
153+
((if self.cnt & 0x2 == 0 { hour % 12 } else { hour }) as u8, hour >= 12)
154+
};
155+
let min = 0 as u8;
156+
let sec = 0 as u8;
157157

158158
self.date_time[0] = (((year / 10) << 4) | (year % 10)) as u8;
159159
self.date_time[1] = ((month / 10) << 4) | (month % 10);

src/jit/assembler/basic_block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ impl BasicBlock {
376376
}
377377
}
378378

379-
pub fn emit_opcodes(&self, asm: &mut BlockAsm, branch_placeholders: &mut Vec<usize>, opcodes_offset: usize) -> Vec<u32> {
379+
pub fn emit_opcodes(&self, asm: &mut BlockAsm, branch_placeholders: &mut Vec<usize>, opcodes_offset: usize, used_host_regs: RegReserve) -> Vec<u32> {
380380
let mut opcodes = Vec::new();
381381
let mut inst_opcodes = Vec::new();
382382
for entry in self.insts_link.iter() {
@@ -397,7 +397,7 @@ impl BasicBlock {
397397
}
398398

399399
inst_opcodes.clear();
400-
inst.emit_opcode(&mut inst_opcodes, opcodes.len(), branch_placeholders, opcodes_offset);
400+
inst.emit_opcode(&mut inst_opcodes, opcodes.len(), branch_placeholders, opcodes_offset, used_host_regs);
401401
opcodes.extend(&inst_opcodes);
402402
}
403403
opcodes

src/jit/assembler/block_asm.rs

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::jit::assembler::block_inst_list::BlockInstList;
66
use crate::jit::assembler::block_reg_set::BlockRegSet;
77
use crate::jit::assembler::{block_reg_allocator, BlockAsmBuf, BlockInst, BlockLabel, BlockOperand, BlockOperandShift, BlockReg, ANY_REG_LIMIT};
88
use crate::jit::inst_info::InstInfo;
9-
use crate::jit::reg::{reg_reserve, Reg, RegReserve};
9+
use crate::jit::reg::{Reg, RegReserve};
1010
use crate::jit::{Cond, MemoryAmount, ShiftType};
1111
use crate::utils::{NoHashMap, NoHashSet};
1212

@@ -55,7 +55,7 @@ pub struct BlockAsm<'a> {
5555
}
5656

5757
impl<'a> BlockAsm<'a> {
58-
pub fn new(thread_regs: &ThreadRegs, buf: &'a mut BlockAsmBuf) -> Self {
58+
pub fn new(thread_regs: &ThreadRegs, host_sp_addr: usize, buf: &'a mut BlockAsmBuf) -> Self {
5959
buf.insts.clear();
6060
buf.guest_branches_mapping.clear();
6161
let thread_regs_addr_reg = BlockReg::Any(Reg::SPSR as u16 + 1);
@@ -82,9 +82,18 @@ impl<'a> BlockAsm<'a> {
8282
block_start: 0,
8383
inst_insert_index: None,
8484
};
85-
instance.transfer_push(BlockReg::Fixed(Reg::SP), reg_reserve!(Reg::LR));
85+
86+
instance.buf.insts.push(BlockInst::Prologue);
87+
88+
let host_sp_addr_reg = thread_regs_addr_reg;
89+
instance.mov(host_sp_addr_reg, host_sp_addr as u32);
90+
instance.transfer_write(BlockReg::Fixed(Reg::SP), host_sp_addr_reg, 0, false, MemoryAmount::Word);
91+
8692
instance.sub(BlockReg::Fixed(Reg::SP), BlockReg::Fixed(Reg::SP), ANY_REG_LIMIT as u32 * 4); // Reserve for spilled registers
93+
8794
instance.mov(thread_regs_addr_reg, thread_regs.get_reg_start_addr() as *const _ as u32);
95+
instance.restore_reg(Reg::CPSR);
96+
8897
instance.block_start = instance.buf.insts.len();
8998
instance
9099
}
@@ -340,9 +349,9 @@ impl<'a> BlockAsm<'a> {
340349
});
341350
}
342351

343-
pub fn breakout(&mut self) {
344-
self.add(BlockReg::Fixed(Reg::SP), BlockReg::Fixed(Reg::SP), ANY_REG_LIMIT as u32 * 4); // Remove reserve for spilled registers
345-
self.transfer_pop(BlockReg::Fixed(Reg::SP), reg_reserve!(Reg::PC));
352+
pub fn epilogue(&mut self) {
353+
self.add(BlockReg::Fixed(Reg::SP), BlockReg::Fixed(Reg::SP), ANY_REG_LIMIT as u32 * 4);
354+
self.buf.insts.push(BlockInst::Epilogue);
346355
}
347356

348357
pub fn call(&mut self, func: impl Into<BlockOperand>) {
@@ -586,23 +595,13 @@ impl<'a> BlockAsm<'a> {
586595
}
587596
last_label = None;
588597
}
589-
// Breakout command
590-
BlockInst::TransferMultiple {
591-
op: BlockTransferOp::Read,
592-
operand: BlockReg::Fixed(Reg::SP),
593-
regs,
594-
write_back: true,
595-
pre: false,
596-
add_to_base: true,
597-
} => {
598-
if *regs == reg_reserve!(Reg::PC) {
599-
basic_blocks.push(BasicBlock::new(self, basic_block_start, current_node));
600-
basic_block_start = BlockInstList::deref(current_node).next;
601-
if let Some(last_label) = last_label {
602-
basic_block_label_mapping.insert(last_label.0, basic_blocks.len() - 1);
603-
}
604-
last_label = None;
598+
BlockInst::Epilogue => {
599+
basic_blocks.push(BasicBlock::new(self, basic_block_start, current_node));
600+
basic_block_start = BlockInstList::deref(current_node).next;
601+
if let Some(last_label) = last_label {
602+
basic_block_label_mapping.insert(last_label.0, basic_blocks.len() - 1);
605603
}
604+
last_label = None;
606605
}
607606
_ => {}
608607
}
@@ -631,15 +630,8 @@ impl<'a> BlockAsm<'a> {
631630
}
632631
}
633632
// Don't add exit when last command in basic block is a breakout
634-
BlockInst::TransferMultiple {
635-
op: BlockTransferOp::Read,
636-
operand: BlockReg::Fixed(Reg::SP),
637-
regs,
638-
write_back: true,
639-
pre: false,
640-
add_to_base: true,
641-
} => {
642-
if *regs != reg_reserve!(Reg::PC) && i + 1 < basic_blocks_len {
633+
BlockInst::Epilogue => {
634+
if i + 1 < basic_blocks_len {
643635
basic_block.exit_blocks.insert(i + 1);
644636
}
645637
}
@@ -764,14 +756,19 @@ impl<'a> BlockAsm<'a> {
764756
self.buf.reg_allocator.global_mapping.insert(reg, Reg::None);
765757
}
766758

759+
let mut used_host_regs = RegReserve::new();
760+
767761
for (i, basic_block) in basic_blocks.iter_mut().enumerate() {
768762
if i != 0 && basic_block.enter_blocks.is_empty() {
769763
continue;
770764
}
771765
self.buf.reg_allocator.init_inputs(*basic_block.get_required_inputs());
772766
basic_block.allocate_regs(&mut self);
767+
used_host_regs += self.buf.reg_allocator.dirty_regs;
773768
}
774769

770+
used_host_regs &= block_reg_allocator::ALLOCATION_REGS;
771+
775772
let mut opcodes = Vec::new();
776773
let mut branch_placeholders = Vec::new();
777774
let mut opcodes_offset = Vec::with_capacity(basic_blocks.len());
@@ -780,7 +777,7 @@ impl<'a> BlockAsm<'a> {
780777
continue;
781778
}
782779
opcodes_offset.push(opcodes.len());
783-
opcodes.extend(basic_block.emit_opcodes(&mut self, &mut branch_placeholders, opcodes.len()));
780+
opcodes.extend(basic_block.emit_opcodes(&mut self, &mut branch_placeholders, opcodes.len(), used_host_regs));
784781
}
785782

786783
for branch_placeholder in branch_placeholders {

src/jit/assembler/block_inst.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::jit::assembler::arm::branch_assembler::Bx;
33
use crate::jit::assembler::arm::transfer_assembler::{LdmStm, LdrStrImm, LdrStrImmSBHD, LdrStrReg, LdrStrRegSBHD, Mrs, Msr};
44
use crate::jit::assembler::arm::Bkpt;
55
use crate::jit::assembler::block_reg_set::{block_reg_set, BlockRegSet};
6-
use crate::jit::assembler::{BlockLabel, BlockOperand, BlockOperandShift, BlockReg, BlockShift};
6+
use crate::jit::assembler::{block_reg_allocator, BlockLabel, BlockOperand, BlockOperandShift, BlockReg, BlockShift};
77
use crate::jit::inst_info::{InstInfo, Operand, Shift, ShiftValue};
88
use crate::jit::reg::{Reg, RegReserve};
99
use crate::jit::{Cond, MemoryAmount, ShiftType};
@@ -194,6 +194,16 @@ impl BlockInst {
194194
}
195195
(inputs, outputs)
196196
}
197+
198+
BlockInst::Prologue => (
199+
block_reg_set!(Some(BlockReg::Fixed(Reg::SP)), Some(BlockReg::Fixed(Reg::LR))),
200+
block_reg_set!(Some(BlockReg::Fixed(Reg::SP))),
201+
),
202+
BlockInst::Epilogue => (
203+
block_reg_set!(Some(BlockReg::Fixed(Reg::SP))),
204+
block_reg_set!(Some(BlockReg::Fixed(Reg::SP)), Some(BlockReg::Fixed(Reg::PC))),
205+
),
206+
197207
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) => (block_reg_set!(), block_reg_set!()),
198208
}
199209
}
@@ -261,7 +271,7 @@ impl BlockInst {
261271
Self::replace_reg(&mut regs_mapping[reg as usize], old, new);
262272
}
263273
}
264-
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) => {}
274+
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) | BlockInst::Prologue | BlockInst::Epilogue => {}
265275
}
266276
}
267277

@@ -315,7 +325,7 @@ impl BlockInst {
315325
Self::replace_reg(&mut regs_mapping[reg as usize], old, new);
316326
}
317327
}
318-
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) => {}
328+
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) | BlockInst::Prologue | BlockInst::Epilogue => {}
319329
}
320330
}
321331

@@ -355,7 +365,7 @@ impl BlockInst {
355365
Self::replace_reg(reg_mapping, old, new);
356366
}
357367
}
358-
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) => {}
368+
BlockInst::Label { .. } | BlockInst::Branch { .. } | BlockInst::GuestPc(_) | BlockInst::Bkpt(_) | BlockInst::Prologue | BlockInst::Epilogue => {}
359369
}
360370
}
361371

@@ -381,7 +391,7 @@ impl BlockInst {
381391
opcodes.push(LdrStrImm::str_offset_al(guest_reg, thread_regs_addr_reg, Reg::CPSR as u16 * 4));
382392
}
383393

384-
pub fn emit_opcode(&mut self, opcodes: &mut Vec<u32>, opcode_index: usize, branch_placeholders: &mut Vec<usize>, opcodes_offset: usize) {
394+
pub fn emit_opcode(&mut self, opcodes: &mut Vec<u32>, opcode_index: usize, branch_placeholders: &mut Vec<usize>, opcodes_offset: usize, used_host_regs: RegReserve) {
385395
let alu_reg = |op: BlockAluOp, op0: BlockReg, op1: BlockReg, op2: BlockReg, shift: BlockShift, set_cond: bool| match shift.value {
386396
BlockOperand::Reg(shift_reg) => AluReg::generic(op as u8, op0.as_fixed(), op1.as_fixed(), op2.as_fixed(), shift.shift_type, shift_reg.as_fixed(), set_cond, Cond::AL),
387397
BlockOperand::Imm(shift_imm) => {
@@ -590,6 +600,11 @@ impl BlockInst {
590600
opcodes.push(inst_info.assemble());
591601
}
592602

603+
// BlockInst::Prologue => opcodes.push(LdmStm::generic(Reg::SP, used_host_regs + Reg::LR, false, true, false, true, Cond::AL)),
604+
// BlockInst::Epilogue => opcodes.push(LdmStm::generic(Reg::SP, used_host_regs + Reg::PC, true, true, true, false, Cond::AL)),
605+
BlockInst::Prologue => opcodes.push(LdmStm::generic(Reg::SP, block_reg_allocator::ALLOCATION_REGS + Reg::LR, false, true, false, true, Cond::AL)),
606+
BlockInst::Epilogue => opcodes.push(LdmStm::generic(Reg::SP, block_reg_allocator::ALLOCATION_REGS + Reg::PC, true, true, true, false, Cond::AL)),
607+
593608
BlockInst::Label { .. } | BlockInst::GuestPc(_) => {}
594609
}
595610
}
@@ -713,6 +728,9 @@ pub enum BlockInst {
713728
inst: GuestInstInfo,
714729
regs_mapping: [BlockReg; Reg::None as usize],
715730
},
731+
732+
Prologue,
733+
Epilogue,
716734
}
717735

718736
impl Debug for BlockInst {
@@ -783,6 +801,8 @@ impl Debug for BlockInst {
783801
BlockInst::Bkpt(id) => write!(f, "Bkpt {id}"),
784802
BlockInst::GuestPc(pc) => write!(f, "GuestPc {pc:x}"),
785803
BlockInst::GenericGuestInst { inst, .. } => write!(f, "{inst:?}"),
804+
BlockInst::Prologue => write!(f, "Prologue"),
805+
BlockInst::Epilogue => write!(f, "Epilogue"),
786806
}
787807
}
788808
}

0 commit comments

Comments
 (0)