Skip to content

Commit 56cfdc9

Browse files
committed
Reduce memory size of jit mappings
1 parent 7fb4a00 commit 56cfdc9

File tree

6 files changed

+98
-49
lines changed

6 files changed

+98
-49
lines changed

src/jit/assembler/arm/alu_assembler.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,33 @@ impl Bfi {
590590
}
591591
}
592592

593+
#[bitsize(32)]
594+
#[derive(FromBits)]
595+
pub struct Ubfx {
596+
rn: u4,
597+
id: u3,
598+
lsb: u5,
599+
rd: u4,
600+
widthm1: u5,
601+
id2: u7,
602+
cond: u4,
603+
}
604+
605+
impl Ubfx {
606+
#[inline]
607+
pub fn create(rd: Reg, rn: Reg, lsb: u8, width: u8, cond: Cond) -> u32 {
608+
u32::from(crate::jit::assembler::arm::alu_assembler::Bfi::new(
609+
u4::new(rn as u8),
610+
u3::new(0b101),
611+
u5::new(lsb),
612+
u4::new(rd as u8),
613+
u5::new(width - 1),
614+
u7::new(0b0111111),
615+
u4::new(cond as u8),
616+
))
617+
}
618+
}
619+
593620
// TODO Add const asserts once const features has been added back to rust
594621
// https://github.com/rust-lang/rust/issues/110395
595622
//const_assert_eq!(lookup_opcode(Self::add(0, 0, 0, 0)).0 as u8, And as u8);

src/jit/assembler/block_asm.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,15 @@ impl<'a> BlockAsm<'a> {
350350
operands: [op0.into(), op1.into()],
351351
lsb,
352352
width,
353-
})
353+
});
354+
}
355+
356+
pub fn ubfx(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, lsb: u8, width: u8) {
357+
self.insert_inst(BlockInstKind::Ubfx {
358+
operands: [op0.into(), op1.into()],
359+
lsb,
360+
width,
361+
});
354362
}
355363

356364
pub fn muls_guest_thumb_pc_aligned(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) {

src/jit/assembler/block_inst.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::jit::assembler::arm::alu_assembler::{AluImm, AluReg, AluShiftImm, Bfc, Bfi, MulReg};
1+
use crate::jit::assembler::arm::alu_assembler::{AluImm, AluReg, AluShiftImm, Bfc, Bfi, MulReg, Ubfx};
22
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;
@@ -168,6 +168,11 @@ pub enum BlockInstKind {
168168
lsb: u8,
169169
width: u8,
170170
},
171+
Ubfx {
172+
operands: [BlockReg; 2],
173+
lsb: u8,
174+
width: u8,
175+
},
171176
Mul {
172177
operands: [BlockOperandShift; 3],
173178
set_cond: BlockAluSetCond,
@@ -287,7 +292,7 @@ impl BlockInstKind {
287292
BlockSystemRegOp::Msr => (block_reg_set!(operand.try_as_reg()), block_reg_set!()),
288293
},
289294
BlockInstKind::Bfc { operand, .. } => (block_reg_set!(Some(*operand)), block_reg_set!(Some(*operand))),
290-
BlockInstKind::Bfi { operands, .. } => (block_reg_set!(Some(operands[0]), Some(operands[1])), block_reg_set!(Some(operands[0]))),
295+
BlockInstKind::Bfi { operands, .. } | BlockInstKind::Ubfx { operands, .. } => (block_reg_set!(Some(operands[0]), Some(operands[1])), block_reg_set!(Some(operands[0]))),
291296

292297
BlockInstKind::SaveContext { .. } => (block_reg_set!(), block_reg_set!()),
293298
BlockInstKind::SaveReg {
@@ -433,6 +438,7 @@ impl BlockInstKind {
433438
Self::replace_reg(&mut operands[0], old, new);
434439
Self::replace_reg(&mut operands[1], old, new);
435440
}
441+
BlockInstKind::Ubfx { operands, .. } => Self::replace_reg(&mut operands[1], old, new),
436442
BlockInstKind::SaveContext { .. } => {
437443
unreachable!()
438444
}
@@ -485,7 +491,7 @@ impl BlockInstKind {
485491
}
486492
}
487493
BlockInstKind::Bfc { operand, .. } => Self::replace_reg(operand, old, new),
488-
BlockInstKind::Bfi { operands, .. } => Self::replace_reg(&mut operands[0], old, new),
494+
BlockInstKind::Bfi { operands, .. } | BlockInstKind::Ubfx { operands, .. } => Self::replace_reg(&mut operands[0], old, new),
489495
BlockInstKind::SaveContext { .. } => {}
490496
BlockInstKind::SaveReg { guest_reg, reg_mapped, .. } => {
491497
if *guest_reg == Reg::CPSR {
@@ -659,6 +665,7 @@ impl BlockInstKind {
659665
},
660666
BlockInstKind::Bfc { operand, lsb, width } => opcodes.push(Bfc::create(operand.as_fixed(), *lsb, *width, Cond::AL)),
661667
BlockInstKind::Bfi { operands, lsb, width } => opcodes.push(Bfi::create(operands[0].as_fixed(), operands[1].as_fixed(), *lsb, *width, Cond::AL)),
668+
BlockInstKind::Ubfx { operands, lsb, width } => opcodes.push(Ubfx::create(operands[0].as_fixed(), operands[1].as_fixed(), *lsb, *width, Cond::AL)),
662669
BlockInstKind::Mul { operands, set_cond, .. } => match operands[2].operand {
663670
BlockOperand::Reg(reg) => opcodes.push(MulReg::mul(
664671
operands[0].as_reg().as_fixed(),
@@ -844,6 +851,7 @@ impl Debug for BlockInstKind {
844851
BlockInstKind::SystemReg { op, operand } => write!(f, "{op:?} {operand:?}"),
845852
BlockInstKind::Bfc { operand, lsb, width } => write!(f, "Bfc {operand:?}, {lsb}, {width}"),
846853
BlockInstKind::Bfi { operands, lsb, width } => write!(f, "Bfi {:?}, {:?}, {lsb}, {width}", operands[0], operands[1]),
854+
BlockInstKind::Ubfx { operands, lsb, width } => write!(f, "Ubfx {:?}, {:?}, {lsb}, {width}", operands[0], operands[1]),
847855
BlockInstKind::Mul { operands, set_cond, thumb_pc_aligned } => write!(f, "Mul{set_cond:?} {operands:?}, align pc: {thumb_pc_aligned}"),
848856
BlockInstKind::Label { label, guest_pc } => {
849857
let guest_pc = match guest_pc {

src/jit/jit_asm_common_funs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ impl<const CPU: CpuType> JitAsmCommonFuns<CPU> {
5151
let map_entry_base_ptr_reg = block_asm.new_reg();
5252

5353
block_asm.mov(map_ptr_reg, map_ptr as u32);
54-
block_asm.mov(map_index_reg, (aligned_target_reg.into(), ShiftType::Lsr, BlockOperand::from(jit_memory_map::BLOCK_SHIFT as u32 + 1)));
54+
const ADDR_SHIFT: u8 = jit_memory_map::BLOCK_SHIFT as u8 + 1;
55+
block_asm.ubfx(map_index_reg, aligned_target_reg, ADDR_SHIFT, 28 - ADDR_SHIFT);
5556
block_asm.load_u32(map_entry_base_ptr_reg, map_ptr_reg, (map_index_reg.into(), ShiftType::Lsl, BlockOperand::from(2)));
5657
let block_size_mask_reg = map_index_reg;
5758
block_asm.mov(block_size_mask_reg, (jit_memory_map::BLOCK_SIZE as u32 - 1) << 2);

src/jit/jit_memory.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::jit::jit_memory_map::JitMemoryMap;
55
use crate::logging::debug_println;
66
use crate::mmap::Mmap;
77
use crate::utils;
8-
use crate::utils::{HeapMem, HeapMemU32};
8+
use crate::utils::{HeapMem, HeapMemU8};
99
use lazy_static::lazy_static;
1010
use paste::paste;
1111
use std::intrinsics::unlikely;
@@ -89,10 +89,10 @@ create_jit_blocks!(
8989

9090
#[derive(Default)]
9191
pub struct JitLiveRanges {
92-
pub itcm: HeapMemU32<{ (regions::INSTRUCTION_TCM_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 32) as usize }>,
93-
pub main: HeapMemU32<{ (regions::MAIN_MEMORY_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 32) as usize }>,
94-
pub wram: HeapMemU32<{ ((regions::SHARED_WRAM_SIZE + regions::ARM7_WRAM_SIZE) / JIT_LIVE_RANGE_PAGE_SIZE / 32) as usize }>,
95-
pub vram_arm7: HeapMemU32<{ (vram::ARM7_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 32) as usize }>,
92+
pub itcm: HeapMemU8<{ (regions::INSTRUCTION_TCM_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
93+
pub main: HeapMemU8<{ (regions::MAIN_MEMORY_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
94+
pub wram: HeapMemU8<{ ((regions::SHARED_WRAM_SIZE + regions::ARM7_WRAM_SIZE) / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
95+
pub vram_arm7: HeapMemU8<{ (vram::ARM7_SIZE / JIT_LIVE_RANGE_PAGE_SIZE / 8) as usize }>,
9696
}
9797

9898
#[cfg(target_os = "linux")]
@@ -191,10 +191,10 @@ impl JitMemory {
191191
$entries[entries_index] = JitEntry(jit_entry_addr);
192192
assert_eq!(ptr::addr_of!($entries[entries_index]), self.jit_memory_map.get_jit_entry::<CPU>(guest_pc));
193193

194-
// >> 5 for u32 (each bit represents a page)
195-
let live_ranges_index = ((guest_pc >> JIT_LIVE_RANGE_PAGE_SIZE_SHIFT) >> 5) as usize;
194+
// >> 3 for u8 (each bit represents a page)
195+
let live_ranges_index = ((guest_pc >> JIT_LIVE_RANGE_PAGE_SIZE_SHIFT) >> 3) as usize;
196196
let live_ranges_index = live_ranges_index % $live_ranges.len();
197-
let live_ranges_bit = (guest_pc >> JIT_LIVE_RANGE_PAGE_SIZE_SHIFT) & 31;
197+
let live_ranges_bit = (guest_pc >> JIT_LIVE_RANGE_PAGE_SIZE_SHIFT) & 0x7;
198198
$live_ranges[live_ranges_index] |= 1 << live_ranges_bit;
199199
assert_eq!(ptr::addr_of!($live_ranges[live_ranges_index]), self.jit_memory_map.get_live_range::<CPU>(guest_pc));
200200

@@ -212,7 +212,7 @@ impl JitMemory {
212212
}};
213213
}
214214

215-
let jit_addr = match CPU {
215+
match CPU {
216216
ARM9 => match guest_pc & 0xFF000000 {
217217
regions::INSTRUCTION_TCM_OFFSET | regions::INSTRUCTION_TCM_MIRROR_OFFSET => insert!(self.jit_entries.itcm, self.jit_live_ranges.itcm),
218218
regions::MAIN_MEMORY_OFFSET => insert!(self.jit_entries.main_arm9, self.jit_live_ranges.main),
@@ -224,9 +224,7 @@ impl JitMemory {
224224
regions::VRAM_OFFSET => insert!(self.jit_entries.vram_arm7, self.jit_live_ranges.vram_arm7),
225225
_ => todo!("{:x}", guest_pc),
226226
},
227-
};
228-
229-
jit_addr
227+
}
230228
}
231229

232230
pub fn get_jit_start_addr<const CPU: CpuType>(&self, guest_pc: u32) -> *const extern "C" fn(bool) {
@@ -237,7 +235,7 @@ impl JitMemory {
237235
macro_rules! invalidate {
238236
($guest_addr:expr, $live_range:ident, $cpu:expr, [$(($cpu_entry:expr, $entries:ident)),+]) => {{
239237
let live_range = unsafe { self.jit_memory_map.get_live_range::<{ $cpu }>($guest_addr).as_mut_unchecked() };
240-
let live_ranges_bit = ($guest_addr >> JIT_LIVE_RANGE_PAGE_SIZE_SHIFT) & 31;
238+
let live_ranges_bit = ($guest_addr >> JIT_LIVE_RANGE_PAGE_SIZE_SHIFT) & 0x7;
241239
if unlikely(*live_range & (1 << live_ranges_bit) != 0) {
242240
*live_range &= !(1 << live_ranges_bit);
243241

src/jit/jit_memory_map.rs

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,23 @@ use crate::jit::jit_memory::{JitEntries, JitEntry, JitLiveRanges, BIOS_UNINTERRU
44
use crate::utils::HeapMemU32;
55
use CpuType::{ARM7, ARM9};
66

7+
// ARM9 Bios starts at 0xFFFF0000, but just treat everything above OAM region as bios
8+
// Also omit 0xF msb to save more memory
9+
const MEMORY_RANGE_ARM9: u32 = 0x10000000;
10+
const MEMORY_RANGE_ARM7: u32 = regions::OAM_OFFSET;
11+
712
pub const BLOCK_SHIFT: usize = 13;
813
pub const BLOCK_SIZE: usize = 1 << BLOCK_SHIFT;
9-
const SIZE: usize = (1 << 31) / BLOCK_SIZE;
10-
const LIVE_RANGES_SIZE: usize = 1 << (32 - JIT_LIVE_RANGE_PAGE_SIZE_SHIFT - 5);
14+
const SIZE_ARM9: usize = (MEMORY_RANGE_ARM9 >> 1) as usize / BLOCK_SIZE;
15+
const SIZE_ARM7: usize = (MEMORY_RANGE_ARM7 >> 1) as usize / BLOCK_SIZE;
16+
const LIVE_RANGES_SIZE: usize = (regions::OAM_OFFSET >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3)) as usize;
1117

1218
const BIOS_UNINTERRUPT_ENTRIES_ARM9: [JitEntry; BLOCK_SIZE] = [BIOS_UNINTERRUPT_ENTRY_ARM9; BLOCK_SIZE];
1319
const BIOS_UNINTERRUPT_ENTRIES_ARM7: [JitEntry; BLOCK_SIZE] = [BIOS_UNINTERRUPT_ENTRY_ARM7; BLOCK_SIZE];
1420

1521
pub struct JitMemoryMap {
16-
map_arm9: HeapMemU32<SIZE>,
17-
map_arm7: HeapMemU32<SIZE>,
22+
map_arm9: HeapMemU32<SIZE_ARM9>,
23+
map_arm7: HeapMemU32<SIZE_ARM7>,
1824
live_ranges_map_arm9: HeapMemU32<LIVE_RANGES_SIZE>,
1925
live_ranges_map_arm7: HeapMemU32<LIVE_RANGES_SIZE>,
2026
}
@@ -28,36 +34,39 @@ impl JitMemoryMap {
2834
live_ranges_map_arm7: HeapMemU32::new(),
2935
};
3036

31-
for i in 0..SIZE {
37+
macro_rules! get_ptr {
38+
($addr:expr, $entries:expr) => {{
39+
(unsafe { $entries.as_ptr().add(($addr >> 1) % $entries.len()) } as u32)
40+
}};
41+
}
42+
43+
for i in 0..SIZE_ARM9 {
3244
let addr = (i << BLOCK_SHIFT) << 1;
3345
let arm9_ptr = &mut instance.map_arm9[i];
34-
let arm7_ptr = &mut instance.map_arm7[i];
3546

36-
macro_rules! get_ptr {
37-
($entries:expr) => {{
38-
(unsafe { $entries.as_ptr().add((addr >> 1) % $entries.len()) } as u32)
39-
}};
47+
match (addr as u32) & 0x0F000000 {
48+
regions::INSTRUCTION_TCM_OFFSET | regions::INSTRUCTION_TCM_MIRROR_OFFSET => *arm9_ptr = get_ptr!(addr, entries.itcm),
49+
regions::MAIN_MEMORY_OFFSET => *arm9_ptr = get_ptr!(addr, entries.main_arm9),
50+
0x0F000000 => *arm9_ptr = BIOS_UNINTERRUPT_ENTRIES_ARM9.as_ptr() as u32,
51+
_ => {}
4052
}
53+
}
4154

42-
match (addr as u32) & 0xFF000000 {
43-
0 => {
44-
*arm9_ptr = get_ptr!(entries.itcm);
45-
*arm7_ptr = BIOS_UNINTERRUPT_ENTRIES_ARM7.as_ptr() as u32;
46-
}
47-
regions::INSTRUCTION_TCM_MIRROR_OFFSET => *arm9_ptr = get_ptr!(entries.itcm),
48-
regions::MAIN_MEMORY_OFFSET => {
49-
*arm9_ptr = get_ptr!(entries.main_arm9);
50-
*arm7_ptr = get_ptr!(entries.main_arm7);
51-
}
52-
regions::SHARED_WRAM_OFFSET => *arm7_ptr = get_ptr!(entries.wram),
53-
regions::VRAM_OFFSET => *arm7_ptr = get_ptr!(entries.vram_arm7),
54-
0xFF000000 => *arm9_ptr = BIOS_UNINTERRUPT_ENTRIES_ARM9.as_ptr() as u32,
55+
for i in 0..SIZE_ARM7 {
56+
let addr = (i << BLOCK_SHIFT) << 1;
57+
let arm7_ptr = &mut instance.map_arm7[i];
58+
59+
match (addr as u32) & 0x0F000000 {
60+
0 => *arm7_ptr = BIOS_UNINTERRUPT_ENTRIES_ARM7.as_ptr() as u32,
61+
regions::MAIN_MEMORY_OFFSET => *arm7_ptr = get_ptr!(addr, entries.main_arm7),
62+
regions::SHARED_WRAM_OFFSET => *arm7_ptr = get_ptr!(addr, entries.wram),
63+
regions::VRAM_OFFSET => *arm7_ptr = get_ptr!(addr, entries.vram_arm7),
5564
_ => {}
5665
}
5766
}
5867

5968
for i in 0..LIVE_RANGES_SIZE {
60-
let addr = i << (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 5);
69+
let addr = i << (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3);
6170
let arm9_ptr = &mut instance.live_ranges_map_arm9[i];
6271
let arm7_ptr = &mut instance.live_ranges_map_arm7[i];
6372

@@ -68,9 +77,7 @@ impl JitMemoryMap {
6877
}
6978

7079
match (addr as u32) & 0xFF000000 {
71-
0 => {
72-
*arm9_ptr = get_ptr!(live_ranges.itcm);
73-
}
80+
0 => *arm9_ptr = get_ptr!(live_ranges.itcm),
7481
regions::INSTRUCTION_TCM_MIRROR_OFFSET => *arm9_ptr = get_ptr!(live_ranges.itcm),
7582
regions::MAIN_MEMORY_OFFSET => {
7683
*arm9_ptr = get_ptr!(live_ranges.main);
@@ -86,7 +93,7 @@ impl JitMemoryMap {
8693
}
8794

8895
pub fn get_jit_entry<const CPU: CpuType>(&self, addr: u32) -> *mut JitEntry {
89-
let addr = addr >> 1;
96+
let addr = (addr & 0x0FFFFFFF) >> 1;
9097
macro_rules! get_jit_entry {
9198
($map:expr) => {{
9299
unsafe { ($map[(addr >> BLOCK_SHIFT) as usize] as *mut JitEntry).add((addr as usize) & (BLOCK_SIZE - 1)) }
@@ -98,10 +105,10 @@ impl JitMemoryMap {
98105
}
99106
}
100107

101-
pub fn get_live_range<const CPU: CpuType>(&self, addr: u32) -> *mut u32 {
108+
pub fn get_live_range<const CPU: CpuType>(&self, addr: u32) -> *mut u8 {
102109
match CPU {
103-
ARM9 => self.live_ranges_map_arm9[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 5)) as usize] as _,
104-
ARM7 => self.live_ranges_map_arm7[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 5)) as usize] as _,
110+
ARM9 => self.live_ranges_map_arm9[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3)) as usize] as _,
111+
ARM7 => self.live_ranges_map_arm7[(addr >> (JIT_LIVE_RANGE_PAGE_SIZE_SHIFT + 3)) as usize] as _,
105112
}
106113
}
107114

0 commit comments

Comments
 (0)