mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-22 15:29:58 +00:00
Interpreter loop is now controlled by exec_flags.
This commit is contained in:
parent
8d3427c475
commit
646880cbf2
@ -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;
|
||||
|
||||
|
@ -21,8 +21,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file Handling of low-level PPC exceptions. */
|
||||
|
||||
#include <loguru.hpp>
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@ -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 &&
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user