Skip to content

Commit bbb3a00

Browse files
committed
Handle guest regs loading and save in local blocks
1 parent 30124cf commit bbb3a00

File tree

7 files changed

+265
-252
lines changed

7 files changed

+265
-252
lines changed

src/core/rtc.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ impl Rtc {
145145
let min = local_now.minute() as u8;
146146
let sec = local_now.second() as u8;
147147

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;
157+
148158
self.date_time[0] = (((year / 10) << 4) | (year % 10)) as u8;
149159
self.date_time[1] = ((month / 10) << 4) | (month % 10);
150160
self.date_time[2] = ((day / 10) << 4) | (day % 10);

src/jit/assembler/basic_block.rs

Lines changed: 201 additions & 157 deletions
Large diffs are not rendered by default.

src/jit/assembler/block_asm.rs

Lines changed: 28 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ use crate::jit::assembler::arm::branch_assembler::B;
33
use crate::jit::assembler::basic_block::BasicBlock;
44
use crate::jit::assembler::block_inst::{BlockAluOp, BlockAluSetCond, BlockSystemRegOp, BlockTransferOp, GuestInstInfo};
55
use crate::jit::assembler::block_inst_list::BlockInstList;
6-
use crate::jit::assembler::block_reg_set::{block_reg_set, BlockRegSet};
6+
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;
99
use crate::jit::reg::{reg_reserve, Reg, RegReserve};
1010
use crate::jit::{Cond, MemoryAmount, ShiftType};
1111
use crate::utils::{NoHashMap, NoHashSet};
1212

13+
pub static mut BLOCK_LOG: bool = false;
14+
1315
macro_rules! alu3 {
1416
($name:ident, $inst:ident, $set_cond:ident, $thumb_pc_aligned:expr) => {
1517
pub fn $name(&mut self, op0: impl Into<BlockReg>, op1: impl Into<BlockReg>, op2: impl Into<BlockOperandShift>) {
@@ -317,7 +319,6 @@ impl<'a> BlockAsm<'a> {
317319
self.insert_inst(BlockInst::SaveContext {
318320
thread_regs_addr_reg: self.thread_regs_addr_reg,
319321
tmp_guest_cpsr_reg: self.tmp_guest_cpsr_reg,
320-
regs_to_save: RegReserve::new(),
321322
});
322323
}
323324

@@ -507,21 +508,6 @@ impl<'a> BlockAsm<'a> {
507508
}
508509
}
509510

510-
fn resolve_guest_regs(&mut self, basic_blocks: &mut [BasicBlock], input_guest_regs_dirty: RegReserve, block_indices: &[usize]) {
511-
for i in block_indices {
512-
let basic_block = &mut basic_blocks[*i];
513-
let sum_guest_regs_dirty = basic_block.input_guest_regs_dirty + input_guest_regs_dirty;
514-
if sum_guest_regs_dirty != basic_block.input_guest_regs_dirty || !basic_block.guest_regs_resolved {
515-
basic_block.guest_regs_resolved = true;
516-
basic_block.input_guest_regs_dirty = sum_guest_regs_dirty;
517-
basic_block.init_resolve_guest_regs(self);
518-
let exit_blocks = basic_block.exit_blocks.clone().into_iter().collect::<Vec<usize>>();
519-
let output_guest_regs_dirty = basic_block.output_guest_regs_dirty;
520-
self.resolve_guest_regs(basic_blocks, output_guest_regs_dirty, &exit_blocks);
521-
}
522-
}
523-
}
524-
525511
fn resolve_io(&self, basic_blocks: &mut [BasicBlock], required_outputs: BlockRegSet, block_indices: &[usize]) {
526512
for i in block_indices {
527513
let basic_block = &mut basic_blocks[*i];
@@ -560,7 +546,7 @@ impl<'a> BlockAsm<'a> {
560546
}
561547
}
562548

563-
fn assemble_basic_blocks<const THUMB: bool>(&mut self, block_start_pc: u32) -> (Vec<BasicBlock>, Vec<usize>) {
549+
fn assemble_basic_blocks(&mut self, block_start_pc: u32, thumb: bool) -> (Vec<BasicBlock>, Vec<usize>) {
564550
for i in 0..self.buf.insts.len() {
565551
self.insts_link.insert_end(i);
566552
}
@@ -671,8 +657,6 @@ impl<'a> BlockAsm<'a> {
671657
}
672658
}
673659

674-
self.resolve_guest_regs(&mut basic_blocks, RegReserve::new(), &[0]);
675-
676660
for basic_block in &mut basic_blocks {
677661
let mut basic_block_start_pc = block_start_pc;
678662
let mut current_node = basic_block.block_entry_start;
@@ -693,7 +677,7 @@ impl<'a> BlockAsm<'a> {
693677

694678
current_node = BlockInstList::deref(current_node).previous;
695679
}
696-
basic_block.init_insts::<THUMB>(self, basic_block_start_pc);
680+
basic_block.init_insts(self, basic_block_start_pc, thumb);
697681
}
698682

699683
for i in (0..basic_blocks_len).rev() {
@@ -712,45 +696,6 @@ impl<'a> BlockAsm<'a> {
712696
let mut df_ordering_end = basic_blocks_len - 1;
713697
Self::resolve_df_ordering(&mut df_already_processed, &mut basic_blocks, 0, &mut df_ordering, &mut df_ordering_start, &mut df_ordering_end);
714698

715-
// Initialize all guest regs used in block
716-
let first_basic_block = basic_blocks.first_mut().unwrap();
717-
let mut loaded_guest_regs = BlockRegSet::new();
718-
let load_guest_regs_insts_start = self.buf.insts.len();
719-
let mut used_guest_regs = Vec::new();
720-
for guest_reg in first_basic_block.get_required_inputs().get_guests() {
721-
loaded_guest_regs += BlockReg::from(guest_reg);
722-
self.insert_inst(BlockInst::Transfer {
723-
op: BlockTransferOp::Read,
724-
operands: [guest_reg.into(), self.thread_regs_addr_reg.into(), (guest_reg as u32 * 4).into()],
725-
signed: false,
726-
amount: MemoryAmount::Word,
727-
add_to_base: true,
728-
});
729-
used_guest_regs.push(block_reg_set!(Some(BlockReg::from(guest_reg)), Some(self.thread_regs_addr_reg)));
730-
}
731-
732-
let mut initialization_end_node = first_basic_block.insts_link.root;
733-
while !initialization_end_node.is_null() && BlockInstList::deref(initialization_end_node).value != self.block_start {
734-
initialization_end_node = BlockInstList::deref(initialization_end_node).next;
735-
}
736-
737-
for i in load_guest_regs_insts_start..load_guest_regs_insts_start + used_guest_regs.len() {
738-
if initialization_end_node.is_null() {
739-
first_basic_block.insts_link.insert_end(i);
740-
} else {
741-
first_basic_block.insts_link.insert_entry_begin(initialization_end_node, i);
742-
}
743-
}
744-
745-
first_basic_block.regs_live_ranges[self.block_start] += self.thread_regs_addr_reg;
746-
let regs_live_extensions = vec![first_basic_block.regs_live_ranges[self.block_start]; used_guest_regs.len()];
747-
first_basic_block.regs_live_ranges.splice(self.block_start..self.block_start, regs_live_extensions);
748-
first_basic_block.used_regs.splice(self.block_start..self.block_start, used_guest_regs);
749-
750-
for i in 0..self.block_start {
751-
first_basic_block.regs_live_ranges[i] -= loaded_guest_regs;
752-
}
753-
754699
(basic_blocks, df_ordering)
755700
}
756701

@@ -778,8 +723,25 @@ impl<'a> BlockAsm<'a> {
778723
intervals
779724
}
780725

781-
pub fn finalize<const THUMB: bool>(mut self, block_start_pc: u32) -> Vec<u32> {
782-
let (mut basic_blocks, basic_blocks_order) = self.assemble_basic_blocks::<THUMB>(block_start_pc);
726+
pub fn finalize(mut self, block_start_pc: u32, thumb: bool) -> Vec<u32> {
727+
let (mut basic_blocks, basic_blocks_order) = self.assemble_basic_blocks(block_start_pc, thumb);
728+
729+
if unsafe { BLOCK_LOG } {
730+
for (i, basic_block) in basic_blocks.iter().enumerate() {
731+
println!("{i}[{i} {:x}]", basic_block.start_pc);
732+
}
733+
734+
for (i, basic_block) in basic_blocks.iter().enumerate() {
735+
for &exit_i in &basic_block.exit_blocks {
736+
println!("{i} --> {exit_i}");
737+
}
738+
}
739+
740+
for (i, basic_block) in basic_blocks.iter().enumerate() {
741+
println!("{i}: {basic_block:?}");
742+
}
743+
}
744+
783745
let mut reg_intervals = Self::assemble_intervals(&basic_blocks, &basic_blocks_order);
784746

785747
self.buf.reg_allocator.global_mapping.clear();
@@ -802,38 +764,19 @@ impl<'a> BlockAsm<'a> {
802764
self.buf.reg_allocator.global_mapping.insert(reg, Reg::None);
803765
}
804766

805-
for basic_block in &mut basic_blocks {
806-
if !basic_block.guest_regs_resolved {
767+
for (i, basic_block) in basic_blocks.iter_mut().enumerate() {
768+
if i != 0 && basic_block.enter_blocks.is_empty() {
807769
continue;
808770
}
809771
self.buf.reg_allocator.init_inputs(*basic_block.get_required_inputs());
810772
basic_block.allocate_regs(&mut self);
811773
}
812774

813-
// Try to collapse cond blocks into cond opcodes
814-
for i in 1..basic_blocks.len() {
815-
if basic_blocks[i].insts_link.len() == 1 && basic_blocks[i].enter_blocks.len() == 1 && *basic_blocks[i].enter_blocks.iter().next().unwrap() == i - 1 {
816-
let previous_entry_last = BlockInstList::deref(basic_blocks[i - 1].insts_link.end).value;
817-
let override_cond = if let BlockInst::Branch { cond, block_index, skip, .. } = &mut self.buf.insts[previous_entry_last] {
818-
if *block_index == i + 1 {
819-
*skip = true;
820-
!*cond
821-
} else {
822-
Cond::AL
823-
}
824-
} else {
825-
Cond::AL
826-
};
827-
// override_cond != AL when a block can be collapsed
828-
basic_blocks[i].cond_block = override_cond;
829-
}
830-
}
831-
832775
let mut opcodes = Vec::new();
833776
let mut branch_placeholders = Vec::new();
834777
let mut opcodes_offset = Vec::with_capacity(basic_blocks.len());
835-
for basic_block in basic_blocks {
836-
if !basic_block.guest_regs_resolved {
778+
for (i, basic_block) in basic_blocks.iter().enumerate() {
779+
if i != 0 && basic_block.enter_blocks.is_empty() {
837780
continue;
838781
}
839782
opcodes_offset.push(opcodes.len());

src/jit/assembler/block_inst.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@ impl BlockInst {
586586
}
587587
}
588588

589+
inst_info.set_cond(Cond::AL);
589590
opcodes.push(inst_info.assemble());
590591
}
591592

@@ -687,7 +688,6 @@ pub enum BlockInst {
687688
SaveContext {
688689
thread_regs_addr_reg: BlockReg,
689690
tmp_guest_cpsr_reg: BlockReg,
690-
regs_to_save: RegReserve,
691691
},
692692
SaveReg {
693693
guest_reg: Reg,
@@ -776,7 +776,7 @@ impl Debug for BlockInst {
776776
write!(f, "label {label:?} {guest_pc}:")
777777
}
778778
BlockInst::Branch { label, cond, block_index, skip } => write!(f, "B{cond:?} {label:?}, block index: {block_index}, skip: {skip}"),
779-
BlockInst::SaveContext { regs_to_save, .. } => write!(f, "Save {regs_to_save:?}"),
779+
BlockInst::SaveContext { .. } => write!(f, "SaveContext"),
780780
BlockInst::SaveReg { guest_reg, reg_mapped, .. } => write!(f, "SaveReg {guest_reg:?}, mapped: {reg_mapped:?}"),
781781
BlockInst::RestoreReg { guest_reg, reg_mapped, .. } => write!(f, "RestoreReg {guest_reg:?}, mapped: {reg_mapped:?}"),
782782
BlockInst::Call { func_reg, args } => write!(f, "Call {func_reg:?} {args:?}"),

src/jit/assembler/block_reg_set.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl BlockRegSet {
3333

3434
pub const fn new_fixed(reg_reserve: RegReserve) -> Self {
3535
let mut set = BlockRegSet::new();
36-
set.0[0] = (reg_reserve.0 & ((1 << Reg::None as u8) - 1)) << Reg::None as u8;
36+
set.0[0] = reg_reserve.0 & ((1 << Reg::None as u8) - 1);
3737
set
3838
}
3939

src/jit/jit_asm.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::core::emu::{get_jit, get_jit_mut, get_mem_mut, get_regs, get_regs_mut, Emu};
22
use crate::core::thread_regs::ThreadRegs;
33
use crate::core::CpuType;
4+
use crate::jit::assembler::block_asm::BLOCK_LOG;
45
use crate::jit::assembler::BlockAsmBuf;
56
use crate::jit::disassembler::lookup_table::lookup_opcode;
67
use crate::jit::disassembler::thumb::lookup_table_thumb::lookup_thumb_opcode;
@@ -145,7 +146,7 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
145146
assert!(self.jit_buf.insts_cycle_counts.len() <= u16::MAX as usize, "{CPU:?} {guest_pc:x} {inst_info:?}")
146147
}
147148

148-
// let is_unreturnable_branch = !inst_info.out_regs.is_reserved(Reg::LR) && inst_info.is_uncond_branch();
149+
// let is_unreturnable_branch = !inst_info.out_regs.is_reserved(Reg::LR) && inst_info.is_uncond_branch() && !inst_info.op.is_labelled_branch();
149150
let is_uncond_branch = inst_info.is_uncond_branch();
150151
let is_unknown = inst_info.op == Op::UnkArm || inst_info.op == Op::UnkThumb;
151152

@@ -158,6 +159,8 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
158159
}
159160
}
160161

162+
// unsafe { BLOCK_LOG = guest_pc == 0x238015c };
163+
161164
let thread_regs = get_regs!(self.emu, CPU);
162165
let mut block_asm = unsafe { (*self.block_asm_buf.get()).new_asm(thread_regs) };
163166

@@ -172,14 +175,20 @@ impl<'a, const CPU: CpuType> JitAsm<'a, CPU> {
172175
self.emit(&mut block_asm);
173176
}
174177

175-
if DEBUG_LOG {
176-
block_asm.save_context();
177-
block_asm.call2(debug_after_exec_op::<CPU> as *const (), self.jit_buf.current_pc, self.jit_buf.current_inst().opcode);
178-
block_asm.restore_reg(Reg::CPSR);
179-
}
178+
// if DEBUG_LOG {
179+
// block_asm.save_context();
180+
// block_asm.call2(debug_after_exec_op::<CPU> as *const (), self.jit_buf.current_pc, self.jit_buf.current_inst().opcode);
181+
// block_asm.restore_reg(Reg::CPSR);
182+
// }
180183
}
181184

182-
let opcodes = block_asm.finalize::<THUMB>(guest_pc);
185+
let opcodes = block_asm.finalize(guest_pc, THUMB);
186+
if unsafe { BLOCK_LOG } {
187+
for &opcode in &opcodes {
188+
println!("0x{opcode:x},");
189+
}
190+
todo!();
191+
}
183192
get_jit_mut!(self.emu).insert_block::<CPU, THUMB>(&opcodes, JitInsertArgs::new(guest_pc, self.jit_buf.insts_cycle_counts.clone()));
184193

185194
if DEBUG_LOG {

src/jit/op.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,13 @@ impl Op {
646646
matches!(self, Op::Bx | Op::BlxReg | Op::B | Op::Bl | Op::Blx | Op::BxRegT | Op::BlxRegT | Op::BT | Op::BlOffT | Op::BlxOffT)
647647
}
648648

649+
pub fn is_labelled_branch(self) -> bool {
650+
matches!(
651+
self,
652+
Op::B | Op::Bl | Op::Blx | Op::BT | Op::BeqT | Op::BneT | Op::BcsT | Op::BccT | Op::BmiT | Op::BplT | Op::BvsT | Op::BvcT | Op::BhiT | Op::BlsT | Op::BgeT | Op::BltT | Op::BgtT | Op::BleT
653+
)
654+
}
655+
649656
pub const fn is_single_mem_transfer(self) -> bool {
650657
matches!(
651658
self,

0 commit comments

Comments
 (0)