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() {