diff --git a/src/rust/jit.rs b/src/rust/jit.rs index 09f06eec..da3d80bc 100644 --- a/src/rust/jit.rs +++ b/src/rust/jit.rs @@ -485,7 +485,7 @@ fn jit_find_basic_blocks( let mut pages: HashSet = HashSet::new(); let mut page_blacklist = HashSet::new(); - // 16-bit doesn't not work correctly, most likely due to instruction pointer wrap-around + // 16-bit doesn't work correctly, most likely due to instruction pointer wrap-around let max_pages = if cpu.state_flags.is_32() { unsafe { MAX_PAGES } } else { 1 }; for virt_addr in entry_points { @@ -539,13 +539,22 @@ fn jit_find_basic_blocks( ..cpu }; let analysis = analysis::analyze_step(&mut cpu); - current_block.number_of_instructions += 1; let has_next_instruction = !analysis.no_next_instruction; current_address = cpu.eip; dbg_assert!(Page::page_of(current_address) == Page::page_of(addr_before_instruction)); let current_virt_addr = to_visit & !0xFFF | current_address as i32 & 0xFFF; + if analysis.ty == AnalysisType::STI && is_near_end_of_page(current_address) { + // cut off before the STI so that it is handled by interpreted mode + profiler::stat_increment(stat::COMPILE_CUT_OFF_AT_END_OF_PAGE); + break; + } + + current_block.number_of_instructions += 1; + current_block.last_instruction_addr = addr_before_instruction; + current_block.end_addr = current_address; + match analysis.ty { AnalysisType::Normal | AnalysisType::STI => { dbg_assert!(has_next_instruction); @@ -557,26 +566,22 @@ fn jit_find_basic_blocks( marked_as_entry.insert(current_virt_addr); to_visit_stack.push(current_virt_addr); - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; break; } if analysis.ty == AnalysisType::STI { - current_block.has_sti = true; - dbg_assert!( !is_near_end_of_page(current_address), - "TODO: Handle STI instruction near end of page" + "should be handled above" ); + + current_block.has_sti = true; } else { // Only split non-STI blocks (one instruction needs to run after STI before // handle_irqs may be called) if basic_blocks.contains_key(¤t_address) { - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; dbg_assert!(!is_near_end_of_page(current_address)); current_block.ty = BasicBlockType::Normal { next_block_addr: Some(current_address), @@ -629,9 +634,6 @@ fn jit_find_basic_blocks( jump_offset_is_32: is_32, }; - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; - break; }, AnalysisType::Jump { @@ -669,8 +671,6 @@ fn jit_find_basic_blocks( jump_offset: offset, jump_offset_is_32: is_32, }; - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; break; }, @@ -690,20 +690,21 @@ fn jit_find_basic_blocks( current_block.ty = BasicBlockType::AbsoluteEip; } - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; break; }, } if is_near_end_of_page(current_address) { - current_block.last_instruction_addr = addr_before_instruction; - current_block.end_addr = current_address; profiler::stat_increment(stat::COMPILE_CUT_OFF_AT_END_OF_PAGE); break; } } + if current_block.number_of_instructions == 0 { + // Empty basic block, don't insert (only happens when STI is found near end of page) + continue; + } + let previous_block = basic_blocks .range(..current_block.addr) .next_back()