Interpreter loop is now controlled by exec_flags.

This commit is contained in:
Maxim Poliakovski 2022-03-02 16:55:20 +01:00
parent 8d3427c475
commit 646880cbf2
4 changed files with 72 additions and 74 deletions

View File

@ -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;

View File

@ -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 &&

View File

@ -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;

View File

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