diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 74b46cc..c25b7ee 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -196,14 +196,12 @@ extern uint64_t ppc_result64_b; extern uint64_t ppc_result64_c; extern uint64_t ppc_result64_d; - -/* The precise end of a basic block. */ -enum class BB_end_kind { - BB_NONE = 0, /* no basic block end is reached */ - BB_BRANCH = 1, /* a branch instruction is encountered */ - BB_EXCEPTION, /* an exception is occured */ - BB_RFI, /* the rfi instruction is encountered */ - BB_TIMER, /* timer queue changed */ +/* Flags for controlling interpreter execution. */ +enum { + EXEF_BRANCH = 1 << 0, + EXEF_EXCEPTION = 1 << 1, + EXEF_RFI = 1 << 2, + EXEF_TIMER = 1 << 7 }; enum CR_select : int32_t { @@ -293,8 +291,7 @@ enum Exc_Cause : uint32_t { TRAP = 1 << (31 - 14), }; -// extern bool bb_end; -extern BB_end_kind bb_kind; +extern unsigned exec_flags; extern jmp_buf exc_env; diff --git a/cpu/ppc/ppcexceptions.cpp b/cpu/ppc/ppcexceptions.cpp index 24a1a4e..17825e3 100644 --- a/cpu/ppc/ppcexceptions.cpp +++ b/cpu/ppc/ppcexceptions.cpp @@ -21,8 +21,10 @@ along with this program. If not, see . /** @file Handling of low-level PPC exceptions. */ +#include #include "ppcemu.h" #include "ppcmmu.h" + #include #include #include @@ -59,7 +61,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) { break; case Except_Type::EXC_EXT_INT: - if (bb_kind != BB_end_kind::BB_NONE) { + if (exec_flags & ~EXEF_TIMER) { ppc_state.spr[SPR::SRR0] = ppc_next_instruction_address; } else { ppc_state.spr[SPR::SRR0] = (ppc_state.pc & 0xFFFFFFFCUL) + 4; @@ -98,8 +100,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) { break; default: - // printf("Unknown exception occured: %X\n", exception_type); - // exit(-1); + ABORT_F("Unknown exception occured: %X\n", exception_type); break; } @@ -112,7 +113,7 @@ void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits) { ppc_next_instruction_address |= 0xFFF00000; } - bb_kind = BB_end_kind::BB_EXCEPTION; + exec_flags = EXEF_EXCEPTION; // perform context synchronization for recoverable exceptions if (exception_type != Except_Type::EXC_MACHINE_CHECK && diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index a530304..afdbe09 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -55,7 +55,7 @@ uint32_t ppc_cur_instruction; // Current instruction for the PPC uint32_t ppc_effective_address; uint32_t ppc_next_instruction_address; // Used for branching, setting up the NIA -BB_end_kind bb_kind; /* basic block end */ +unsigned exec_flags; /* copy of local variable bb_start_la. Need for correct calculation of CPU cycles after setjmp that clobbers @@ -319,11 +319,7 @@ uint64_t process_events() void force_cycle_counter_reload() { // tell the interpreter loop to reload cycle counter - if (bb_kind == BB_end_kind::BB_NONE || bb_kind == BB_end_kind::BB_TIMER) { - bb_kind = BB_end_kind::BB_TIMER; - } else { - ABORT_F("PPCEXEC: attempt to override basic block type %d", bb_kind); - } + exec_flags |= EXEF_TIMER; } /** Execute PPC code as long as power is on. */ @@ -401,10 +397,9 @@ static void ppc_exec_inner() while (power_on) { // define boundaries of the next execution block // max execution block length = one memory page - eb_start = ppc_state.pc; - eb_end = (eb_start + PAGE_SIZE) & PAGE_MASK; - //eb_last = false; - bb_kind = BB_end_kind::BB_NONE; + eb_start = ppc_state.pc; + eb_end = (eb_start + PAGE_SIZE) & PAGE_MASK; + exec_flags = 0; page_start = eb_start & PAGE_MASK; pc_real = mmu_translate_imem(eb_start); @@ -416,17 +411,19 @@ static void ppc_exec_inner() max_cycles = process_events(); } - if (bb_kind != BB_end_kind::BB_NONE) { // execution block ended ? + if (exec_flags) { if (!power_on) break; // reload cycle counter if requested - if (bb_kind == BB_end_kind::BB_TIMER) { + if (exec_flags & EXEF_TIMER) { max_cycles = process_events(); - ppc_state.pc += 4; - pc_real += 4; - ppc_set_cur_instruction(pc_real); - bb_kind = BB_end_kind::BB_NONE; - continue; + if (!(exec_flags & ~EXEF_TIMER)) { + ppc_state.pc += 4; + pc_real += 4; + ppc_set_cur_instruction(pc_real); + exec_flags = 0; + continue; + } } // define next execution block eb_start = ppc_next_instruction_address; @@ -439,7 +436,7 @@ static void ppc_exec_inner() pc_real = mmu_translate_imem(eb_start); } ppc_state.pc = eb_start; - bb_kind = BB_end_kind::BB_NONE; + exec_flags = 0; } else { ppc_state.pc += 4; pc_real += 4; @@ -506,19 +503,19 @@ void ppc_exec_single() // process low-level exceptions //LOG_F(9, "PPC-EXEC: low_level exception raised!"); ppc_state.pc = ppc_next_instruction_address; - bb_kind = BB_end_kind::BB_NONE; + exec_flags = 0; return; } mmu_translate_imem(ppc_state.pc); ppc_main_opcode(); - if (bb_kind != BB_end_kind::BB_NONE) { - if (bb_kind == BB_end_kind::BB_TIMER) { + if (exec_flags) { + if (exec_flags & EXEF_TIMER) { ppc_state.pc += 4; } else { ppc_state.pc = ppc_next_instruction_address; } - bb_kind = BB_end_kind::BB_NONE; + exec_flags = 0; } else { ppc_state.pc += 4; } @@ -599,10 +596,9 @@ static void ppc_exec_until_inner(const uint32_t goal_addr) while (ppc_state.pc != goal_addr) { // define boundaries of the next execution block // max execution block length = one memory page - eb_start = ppc_state.pc; - eb_end = (eb_start + PAGE_SIZE) & PAGE_MASK; - //eb_last = false; - bb_kind = BB_end_kind::BB_NONE; + eb_start = ppc_state.pc; + eb_end = (eb_start + PAGE_SIZE) & PAGE_MASK; + exec_flags = 0; page_start = eb_start & PAGE_MASK; pc_real = mmu_translate_imem(eb_start); @@ -614,15 +610,17 @@ static void ppc_exec_until_inner(const uint32_t goal_addr) max_cycles = process_events(); } - if (bb_kind != BB_end_kind::BB_NONE) { // execution block ended ? + if (exec_flags) { // reload cycle counter if requested - if (bb_kind == BB_end_kind::BB_TIMER) { + if (exec_flags & EXEF_TIMER) { max_cycles = process_events(); - ppc_state.pc += 4; - pc_real += 4; - ppc_set_cur_instruction(pc_real); - bb_kind = BB_end_kind::BB_NONE; - continue; + if (!(exec_flags & ~EXEF_TIMER)) { + ppc_state.pc += 4; + pc_real += 4; + ppc_set_cur_instruction(pc_real); + exec_flags = 0; + continue; + } } // define next execution block eb_start = ppc_next_instruction_address; @@ -635,7 +633,7 @@ static void ppc_exec_until_inner(const uint32_t goal_addr) pc_real = mmu_translate_imem(eb_start); } ppc_state.pc = eb_start; - bb_kind = BB_end_kind::BB_NONE; + exec_flags = 0; } else { ppc_state.pc += 4; pc_real += 4; @@ -737,10 +735,9 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size) while (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size) { // define boundaries of the next execution block // max execution block length = one memory page - eb_start = ppc_state.pc; - eb_end = (eb_start + PAGE_SIZE) & PAGE_MASK; - //eb_last = false; - bb_kind = BB_end_kind::BB_NONE; + eb_start = ppc_state.pc; + eb_end = (eb_start + PAGE_SIZE) & PAGE_MASK; + exec_flags = 0; page_start = eb_start & PAGE_MASK; pc_real = mmu_translate_imem(eb_start); @@ -753,16 +750,17 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size) max_cycles = process_events(); } - //if (eb_last) { - if (bb_kind != BB_end_kind::BB_NONE) { // execution block ended ? + if (exec_flags) { // reload cycle counter if requested - if (bb_kind == BB_end_kind::BB_TIMER) { + if (exec_flags & EXEF_TIMER) { max_cycles = process_events(); - ppc_state.pc += 4; - pc_real += 4; - ppc_set_cur_instruction(pc_real); - bb_kind = BB_end_kind::BB_NONE; - continue; + if (!(exec_flags & ~EXEF_TIMER)) { + ppc_state.pc += 4; + pc_real += 4; + ppc_set_cur_instruction(pc_real); + exec_flags = 0; + continue; + } } // define next execution block eb_start = ppc_next_instruction_address; @@ -775,7 +773,7 @@ static void ppc_exec_dbg_inner(const uint32_t start_addr, const uint32_t size) pc_real = mmu_translate_imem(eb_start); } ppc_state.pc = eb_start; - bb_kind = BB_end_kind::BB_NONE; + exec_flags = 0; } else { ppc_state.pc += 4; pc_real += 4; @@ -1039,6 +1037,8 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t cpu_version) { tbr_wr_value = 0; tbr_freq_hz = 16705000; // FIXME: this should be set properly during machine initialization + exec_flags = 0; + timebase_counter = 0; decr = 0; old_decr_msb = decr >> 31; diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index 49babae..c79d3e2 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -995,7 +995,7 @@ void dppc_interpreter::ppc_b() { uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC); adr_li = (quick_test < 0x2000000) ? quick_test : (0xFC000000UL + quick_test); ppc_next_instruction_address = (uint32_t)(ppc_state.pc + adr_li); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } void dppc_interpreter::ppc_bl() { @@ -1003,14 +1003,14 @@ void dppc_interpreter::ppc_bl() { adr_li = (quick_test < 0x2000000) ? quick_test : (0xFC000000UL + quick_test); ppc_next_instruction_address = (uint32_t)(ppc_state.pc + adr_li); ppc_state.spr[SPR::LR] = (uint32_t)(ppc_state.pc + 4); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } void dppc_interpreter::ppc_ba() { uint32_t quick_test = (ppc_cur_instruction & 0x03FFFFFC); adr_li = (quick_test < 0x2000000) ? quick_test : (0xFC000000UL + quick_test); ppc_next_instruction_address = adr_li; - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } void dppc_interpreter::ppc_bla() { @@ -1018,7 +1018,7 @@ void dppc_interpreter::ppc_bla() { adr_li = (quick_test < 0x2000000) ? quick_test : (0xFC000000UL + quick_test); ppc_next_instruction_address = adr_li; ppc_state.spr[SPR::LR] = ppc_state.pc + 4; - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } void dppc_interpreter::ppc_bc() { @@ -1036,7 +1036,7 @@ void dppc_interpreter::ppc_bc() { if (ctr_ok && cnd_ok) { ppc_next_instruction_address = (ppc_state.pc + br_bd); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } } @@ -1055,7 +1055,7 @@ void dppc_interpreter::ppc_bca() { if (ctr_ok && cnd_ok) { ppc_next_instruction_address = br_bd; - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } } @@ -1074,7 +1074,7 @@ void dppc_interpreter::ppc_bcl() { if (ctr_ok && cnd_ok) { ppc_next_instruction_address = (ppc_state.pc + br_bd); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } ppc_state.spr[SPR::LR] = ppc_state.pc + 4; } @@ -1094,7 +1094,7 @@ void dppc_interpreter::ppc_bcla() { if (ctr_ok && cnd_ok) { ppc_next_instruction_address = br_bd; - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } ppc_state.spr[SPR::LR] = ppc_state.pc + 4; } @@ -1108,7 +1108,7 @@ void dppc_interpreter::ppc_bcctr() { if (cnd_ok) { ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & 0xFFFFFFFCUL); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } } @@ -1121,7 +1121,7 @@ void dppc_interpreter::ppc_bcctrl() { if (cnd_ok) { ppc_next_instruction_address = (ppc_state.spr[SPR::CTR] & 0xFFFFFFFCUL); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } ppc_state.spr[SPR::LR] = ppc_state.pc + 4; } @@ -1140,7 +1140,7 @@ void dppc_interpreter::ppc_bclr() { if (ctr_ok && cnd_ok) { ppc_next_instruction_address = (ppc_state.spr[SPR::LR] & 0xFFFFFFFCUL); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } } @@ -1158,7 +1158,7 @@ void dppc_interpreter::ppc_bclrl() { if (ctr_ok && cnd_ok) { ppc_next_instruction_address = (ppc_state.spr[SPR::LR] & 0xFFFFFFFCUL); - bb_kind = BB_end_kind::BB_BRANCH; + exec_flags = EXEF_BRANCH; } ppc_state.spr[SPR::LR] = ppc_state.pc + 4; } @@ -1332,7 +1332,7 @@ void dppc_interpreter::ppc_rfi() { mmu_change_mode(); grab_return = true; - bb_kind = BB_end_kind::BB_RFI; + exec_flags = EXEF_RFI; } void dppc_interpreter::ppc_sc() {