Skip to content

Commit 87d9b8b

Browse files
committed
fix: Handle STI instruction near end of page
1 parent d23b02e commit 87d9b8b

File tree

1 file changed

+18
-20
lines changed

1 file changed

+18
-20
lines changed

src/rust/jit.rs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ fn jit_find_basic_blocks(
485485
let mut pages: HashSet<Page> = HashSet::new();
486486
let mut page_blacklist = HashSet::new();
487487

488-
// 16-bit doesn't not work correctly, most likely due to instruction pointer wrap-around
488+
// 16-bit doesn't work correctly, most likely due to instruction pointer wrap-around
489489
let max_pages = if cpu.state_flags.is_32() { unsafe { MAX_PAGES } } else { 1 };
490490

491491
for virt_addr in entry_points {
@@ -539,13 +539,22 @@ fn jit_find_basic_blocks(
539539
..cpu
540540
};
541541
let analysis = analysis::analyze_step(&mut cpu);
542-
current_block.number_of_instructions += 1;
543542
let has_next_instruction = !analysis.no_next_instruction;
544543
current_address = cpu.eip;
545544

546545
dbg_assert!(Page::page_of(current_address) == Page::page_of(addr_before_instruction));
547546
let current_virt_addr = to_visit & !0xFFF | current_address as i32 & 0xFFF;
548547

548+
if analysis.ty == AnalysisType::STI && is_near_end_of_page(current_address) {
549+
// cut off before the STI so that it is handled by interpreted mode
550+
profiler::stat_increment(stat::COMPILE_CUT_OFF_AT_END_OF_PAGE);
551+
break;
552+
}
553+
554+
current_block.number_of_instructions += 1;
555+
current_block.last_instruction_addr = addr_before_instruction;
556+
current_block.end_addr = current_address;
557+
549558
match analysis.ty {
550559
AnalysisType::Normal | AnalysisType::STI => {
551560
dbg_assert!(has_next_instruction);
@@ -557,26 +566,19 @@ fn jit_find_basic_blocks(
557566
marked_as_entry.insert(current_virt_addr);
558567
to_visit_stack.push(current_virt_addr);
559568

560-
current_block.last_instruction_addr = addr_before_instruction;
561-
current_block.end_addr = current_address;
562569
break;
563570
}
564571

565572
if analysis.ty == AnalysisType::STI {
566-
current_block.has_sti = true;
573+
dbg_assert!(!is_near_end_of_page(current_address), "should be handled above");
567574

568-
dbg_assert!(
569-
!is_near_end_of_page(current_address),
570-
"TODO: Handle STI instruction near end of page"
571-
);
575+
current_block.has_sti = true;
572576
}
573577
else {
574578
// Only split non-STI blocks (one instruction needs to run after STI before
575579
// handle_irqs may be called)
576580

577581
if basic_blocks.contains_key(&current_address) {
578-
current_block.last_instruction_addr = addr_before_instruction;
579-
current_block.end_addr = current_address;
580582
dbg_assert!(!is_near_end_of_page(current_address));
581583
current_block.ty = BasicBlockType::Normal {
582584
next_block_addr: Some(current_address),
@@ -629,9 +631,6 @@ fn jit_find_basic_blocks(
629631
jump_offset_is_32: is_32,
630632
};
631633

632-
current_block.last_instruction_addr = addr_before_instruction;
633-
current_block.end_addr = current_address;
634-
635634
break;
636635
},
637636
AnalysisType::Jump {
@@ -669,8 +668,6 @@ fn jit_find_basic_blocks(
669668
jump_offset: offset,
670669
jump_offset_is_32: is_32,
671670
};
672-
current_block.last_instruction_addr = addr_before_instruction;
673-
current_block.end_addr = current_address;
674671

675672
break;
676673
},
@@ -690,20 +687,21 @@ fn jit_find_basic_blocks(
690687
current_block.ty = BasicBlockType::AbsoluteEip;
691688
}
692689

693-
current_block.last_instruction_addr = addr_before_instruction;
694-
current_block.end_addr = current_address;
695690
break;
696691
},
697692
}
698693

699694
if is_near_end_of_page(current_address) {
700-
current_block.last_instruction_addr = addr_before_instruction;
701-
current_block.end_addr = current_address;
702695
profiler::stat_increment(stat::COMPILE_CUT_OFF_AT_END_OF_PAGE);
703696
break;
704697
}
705698
}
706699

700+
if current_block.number_of_instructions == 0 {
701+
// Empty basic block, don't insert (only happens when STI is found near end of page)
702+
continue;
703+
}
704+
707705
let previous_block = basic_blocks
708706
.range(..current_block.addr)
709707
.next_back()

0 commit comments

Comments
 (0)