Refactor PPC exception handling, part 1.

This commit is contained in:
Maxim Poliakovski 2020-01-11 21:48:56 +01:00
parent add0d5877c
commit 2d5e436ad4
6 changed files with 209 additions and 144 deletions

View File

@ -8,6 +8,7 @@
#ifndef PPCEMU_H
#define PPCEMU_H
#include <setjmp.h>
#include "devices/memctrlbase.h"
//Uncomment this to help debug the emulator further
@ -160,15 +161,33 @@ extern int32_t simm_rev_endian16(int32_t insert_int);
extern uint32_t rev_endian32(uint32_t insert_int);
extern uint64_t rev_endian64(uint64_t insert_int);
/* The precise reason for the termination of a basic block. */
enum class BB_end_reason {
/* 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 */
};
extern bool bb_end;
extern BB_end_reason bb_kind;
/** PowerPC exception types. */
enum class Except_Type {
EXC_SYSTEM_RESET = 1,
EXC_MACHINE_CHECK,
EXC_DSI,
EXC_ISI,
EXC_EXT_INT,
EXC_ALIGNMENT,
EXC_PROGRAM,
EXC_NO_FPU,
EXC_DECR,
EXC_SYSCALL = 12,
EXC_TRACE = 13
};
//extern bool bb_end;
extern BB_end_kind bb_kind;
extern jmp_buf exc_env;
extern bool grab_branch;
extern bool grab_exception;
@ -235,7 +254,8 @@ void ppc_setsoov(uint32_t a, uint32_t b);
void ppc_changecrf0(uint32_t set_result);
void ppc_tbr_update();
void ppc_exception_handler(uint32_t exception_type, uint32_t handle_args);
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
uint32_t srr1_bits);
//MEMORY DECLARATIONS
extern MemCtrlBase *mem_ctrl_instance;

90
cpu/ppc/ppcexceptions.cpp Normal file
View File

@ -0,0 +1,90 @@
/** @file Handling of low-level PPC exceptions. */
#include <setjmp.h>
#include "ppcemu.h"
jmp_buf exc_env; /* Global exception environment. */
[[noreturn]] void ppc_exception_handler(Except_Type exception_type,
uint32_t srr1_bits)
{
grab_exception = true;
bb_kind = BB_end_kind::BB_EXCEPTION;
switch(exception_type) {
case Except_Type::EXC_SYSTEM_RESET:
ppc_state.ppc_spr[26] = ppc_cur_instruction & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0100;
break;
case Except_Type::EXC_MACHINE_CHECK:
if (!(ppc_state.ppc_msr & 0x1000)) {
/* TODO: handle internal checkstop */
}
ppc_state.ppc_spr[26] = ppc_cur_instruction & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0200;
break;
case Except_Type::EXC_DSI:
ppc_state.ppc_spr[26] = ppc_cur_instruction & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0300;
break;
case Except_Type::EXC_ISI:
ppc_state.ppc_spr[26] = ppc_next_instruction_address;
ppc_next_instruction_address = 0x0400;
break;
case Except_Type::EXC_EXT_INT:
ppc_state.ppc_spr[26] = ppc_next_instruction_address;
ppc_next_instruction_address = 0x0500;
break;
case Except_Type::EXC_ALIGNMENT:
ppc_state.ppc_spr[26] = ppc_cur_instruction & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0600;
break;
case Except_Type::EXC_PROGRAM:
ppc_state.ppc_spr[26] = ppc_cur_instruction & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0700;
break;
case Except_Type::EXC_NO_FPU:
ppc_state.ppc_spr[26] = ppc_cur_instruction & 0xFFFFFFFC;
ppc_next_instruction_address = 0x0800;
break;
case Except_Type::EXC_DECR:
ppc_state.ppc_spr[26] = (ppc_cur_instruction & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0900;
break;
case Except_Type::EXC_SYSCALL:
ppc_state.ppc_spr[26] = (ppc_cur_instruction & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0C00;
break;
case Except_Type::EXC_TRACE:
ppc_state.ppc_spr[26] = (ppc_cur_instruction & 0xFFFFFFFC) + 4;
ppc_next_instruction_address = 0x0D00;
break;
default:
//printf("Unknown exception occured: %X\n", exception_type);
//exit(-1);
break;
}
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0x0000FF73) | srr1_bits;
ppc_state.ppc_msr &= 0xFFFB1041;
/* copy MSR[ILE] to MSR[LE] */
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFFFFFE) |
((ppc_state.ppc_msr >> 16) & 1);
if (ppc_state.ppc_msr & 0x40) {
ppc_next_instruction_address |= 0xFFF00000;
}
longjmp(exc_env, 2); /* return to the main execution loop. */
}

View File

@ -7,14 +7,14 @@
#include <unordered_map>
#include <chrono>
#include <setjmp.h>
#include "ppcemu.h"
#include "ppcmmu.h"
bool power_on = 1;
bool bb_end = 0; /* "true" means a basic block was terminated */
BB_end_reason bb_kind; /* the reason for the termination of a basic block */
BB_end_kind bb_kind; /* basic block end */
uint64_t timebase_counter; /* internal timebase counter */
@ -394,7 +394,6 @@ void ppc_illegalop(){
uint32_t grab_it = (uint32_t) illegal_code;
printf("Illegal opcode reported: %d Report this! \n", grab_it);
exit(-1);
//ppc_exception_handler(0x0700, 0x80000);
}
void ppc_illegalsubop31(){
@ -429,7 +428,7 @@ void ppc_opcode19(){
}
else{
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(0x0700, 0x80000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
SubOpcode19Grabber[subop_grab]();
@ -446,7 +445,7 @@ void ppc_opcode31(){
}
else{
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(0x0700, 0x80000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
SubOpcode31Grabber[subop_grab]();
@ -463,7 +462,7 @@ void ppc_opcode59(){
}
else{
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(0x0700, 0x80000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
SubOpcode59Grabber[subop_grab]();
@ -480,7 +479,7 @@ void ppc_opcode63(){
}
else{
std::cout << "ILLEGAL SUBOPCODE: " << subop_grab << std::endl;
ppc_exception_handler(0x0700, 0x80000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
}
#else
SubOpcode63Grabber[subop_grab]();
@ -552,7 +551,18 @@ void ppc_exec()
/* start new basic block */
bb_start_la = ppc_state.ppc_pc;
bb_end = false;
bb_kind = BB_end_kind::BB_NONE;
if (setjmp(exc_env)) {
/* reaching here means we got a low-level exception */
timebase_counter += (ppc_state.ppc_pc - bb_start_la) >> 2;
bb_start_la = ppc_next_instruction_address;
pc_real = quickinstruction_translate(bb_start_la);
page_start = bb_start_la & 0xFFFFF000;
ppc_state.ppc_pc = bb_start_la;
bb_kind = BB_end_kind::BB_NONE;
goto again;
}
/* initial MMU translation for the current code page. */
pc_real = quickinstruction_translate(bb_start_la);
@ -560,9 +570,10 @@ void ppc_exec()
/* set current code page limits */
page_start = bb_start_la & 0xFFFFF000;
again:
while (power_on) {
ppc_main_opcode();
if (bb_end) {
if (bb_kind != BB_end_kind::BB_NONE) {
timebase_counter += (ppc_state.ppc_pc - bb_start_la) >> 2;
bb_start_la = ppc_next_instruction_address;
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
@ -573,7 +584,7 @@ void ppc_exec()
ppc_set_cur_instruction(pc_real);
}
ppc_state.ppc_pc = bb_start_la;
bb_end = false;
bb_kind = BB_end_kind::BB_NONE;
} else {
ppc_state.ppc_pc += 4;
pc_real += 4;
@ -608,11 +619,19 @@ void ppc_exec_single()
#else
void ppc_exec_single()
{
if (setjmp(exc_env)) {
/* reaching here means we got a low-level exception */
timebase_counter += 1;
ppc_state.ppc_pc = ppc_next_instruction_address;
bb_kind = BB_end_kind::BB_NONE;
return;
}
quickinstruction_translate(ppc_state.ppc_pc);
ppc_main_opcode();
if (bb_end) {
if (bb_kind != BB_end_kind::BB_NONE) {
ppc_state.ppc_pc = ppc_next_instruction_address;
bb_end = false;
bb_kind = BB_end_kind::BB_NONE;
} else {
ppc_state.ppc_pc += 4;
}
@ -653,7 +672,18 @@ void ppc_exec_until(uint32_t goal_addr)
/* start new basic block */
bb_start_la = ppc_state.ppc_pc;
bb_end = false;
bb_kind = BB_end_kind::BB_NONE;
if (setjmp(exc_env)) {
/* reaching here means we got a low-level exception */
timebase_counter += (ppc_state.ppc_pc - bb_start_la) >> 2;
bb_start_la = ppc_next_instruction_address;
pc_real = quickinstruction_translate(bb_start_la);
page_start = bb_start_la & 0xFFFFF000;
ppc_state.ppc_pc = bb_start_la;
bb_kind = BB_end_kind::BB_NONE;
goto again;
}
/* initial MMU translation for the current code page. */
pc_real = quickinstruction_translate(bb_start_la);
@ -661,9 +691,10 @@ void ppc_exec_until(uint32_t goal_addr)
/* set current code page limits */
page_start = bb_start_la & 0xFFFFF000;
again:
while (ppc_state.ppc_pc != goal_addr) {
ppc_main_opcode();
if (bb_end) {
if (bb_kind != BB_end_kind::BB_NONE) {
timebase_counter += (ppc_state.ppc_pc - bb_start_la) >> 2;
bb_start_la = ppc_next_instruction_address;
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
@ -674,7 +705,7 @@ void ppc_exec_until(uint32_t goal_addr)
ppc_set_cur_instruction(pc_real);
}
ppc_state.ppc_pc = bb_start_la;
bb_end = false;
bb_kind = BB_end_kind::BB_NONE;
} else {
ppc_state.ppc_pc += 4;
pc_real += 4;

View File

@ -209,7 +209,7 @@ static bool search_pteg(uint8_t *pteg_addr, uint8_t **ret_pte_addr,
}
static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
unsigned msr_pr, bool is_write)
unsigned msr_pr, int is_write)
{
uint32_t sr_val, page_index, pteg_hash1, vsid, pte_word2;
unsigned key, pp;
@ -223,7 +223,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
/* instruction fetch from a no-execute segment will cause ISI exception */
if ((sr_val & 0x10000000) && is_instr_fetch) {
ppc_exception_handler(0x400, 0); // FIXME: proper exception handling!
ppc_exception_handler(Except_Type::EXC_ISI, 0x10000000);
}
page_index = (la >> 12) & 0xFFFF;
@ -233,9 +233,11 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
if (!search_pteg(calc_pteg_addr(pteg_hash1), &pte_addr, vsid, page_index, 0)) {
if (!search_pteg(calc_pteg_addr(~pteg_hash1), &pte_addr, vsid, page_index, 1)) {
if (is_instr_fetch) {
ppc_exception_handler(0x400, 0);
ppc_exception_handler(Except_Type::EXC_ISI, 0x40000000);
} else {
ppc_exception_handler(0x300, 0);
ppc_state.ppc_spr[18] = 0x40000000 | (is_write << 25);
ppc_state.ppc_spr[19] = la;
ppc_exception_handler(Except_Type::EXC_DSI, 0);
}
}
}
@ -253,9 +255,11 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
// write access with PP = %11
if ((key && (!pp || (pp == 1 && is_write))) || (pp == 3 && is_write)) {
if (is_instr_fetch) {
ppc_exception_handler(0x400, 0);
ppc_exception_handler(Except_Type::EXC_ISI, 0x08000000);
} else {
ppc_exception_handler(0x300, 0);
ppc_state.ppc_spr[18] = 0x08000000 | (is_write << 25);
ppc_state.ppc_spr[19] = la;
ppc_exception_handler(Except_Type::EXC_DSI, 0);
}
}
@ -271,7 +275,7 @@ static uint32_t page_address_translate(uint32_t la, bool is_instr_fetch,
}
/** PowerPC-style MMU instruction address translation. */
uint32_t ppc_mmu_instr_translate(uint32_t la)
static uint32_t ppc_mmu_instr_translate(uint32_t la)
{
uint32_t pa; /* translated physical address */
@ -299,14 +303,14 @@ uint32_t ppc_mmu_instr_translate(uint32_t la)
/* page address translation */
if (!bat_hit) {
pa = page_address_translate(la, true, msr_pr, false);
pa = page_address_translate(la, true, msr_pr, 0);
}
return pa;
}
/** PowerPC-style MMU data address translation. */
uint32_t ppc_mmu_addr_translate(uint32_t la, bool is_write)
static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write)
{
uint32_t pa; /* translated physical address */
@ -349,7 +353,7 @@ void address_quickinsert_translate(uint32_t value, uint32_t addr, uint8_t num_by
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, true);
addr = ppc_mmu_addr_translate(addr, 1);
}
if (addr >= write_last_pa_start && addr <= write_last_pa_end) {
@ -383,7 +387,7 @@ void address_quickgrab_translate(uint32_t addr, uint8_t num_bytes)
{
/* data address translation if enabled */
if (ppc_state.ppc_msr & 0x10) {
addr = ppc_mmu_addr_translate(addr, false);
addr = ppc_mmu_addr_translate(addr, 0);
}
if (addr >= read_last_pa_start && addr <= read_last_pa_end) {

View File

@ -1273,17 +1273,19 @@ void ppc_mfsrin(){
}
void ppc_mfmsr(){
if ((ppc_state.ppc_msr & 0x4000) == 0){
reg_d = (ppc_cur_instruction >> 21) & 31;
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_msr;
if (ppc_state.ppc_msr & 0x4000) {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x00040000);
}
reg_d = (ppc_cur_instruction >> 21) & 31;
ppc_state.ppc_gpr[reg_d] = ppc_state.ppc_msr;
}
void ppc_mtmsr(){
//if ((ppc_state.ppc_msr && 0x4000) == 0){
reg_s = (ppc_cur_instruction >> 21) & 31;
ppc_state.ppc_msr = ppc_state.ppc_gpr[reg_s];
//}
if (ppc_state.ppc_msr & 0x4000) {
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x00040000);
}
reg_s = (ppc_cur_instruction >> 21) & 31;
ppc_state.ppc_msr = ppc_state.ppc_gpr[reg_s];
}
void ppc_mfspr(){
@ -1405,8 +1407,7 @@ void ppc_b(){
adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000UL + quick_test);
ppc_next_instruction_address = (uint32_t)(ppc_state.ppc_pc + adr_li);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
void ppc_bl(){
@ -1415,8 +1416,7 @@ void ppc_bl(){
ppc_next_instruction_address = (uint32_t)(ppc_state.ppc_pc + adr_li);
ppc_state.ppc_spr[8] = (uint32_t)(ppc_state.ppc_pc + 4);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
void ppc_ba(){
@ -1424,8 +1424,7 @@ void ppc_ba(){
adr_li = (quick_test < 0x2000000)? quick_test: (0xFC000000UL + quick_test);
ppc_next_instruction_address = adr_li;
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
void ppc_bla(){
@ -1434,8 +1433,7 @@ void ppc_bla(){
ppc_next_instruction_address = adr_li;
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
void ppc_bc()
@ -1455,8 +1453,7 @@ void ppc_bc()
if (ctr_ok && cnd_ok){
ppc_next_instruction_address = (ppc_state.ppc_pc + br_bd);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
}
@ -1477,8 +1474,7 @@ void ppc_bca()
if (ctr_ok && cnd_ok){
ppc_next_instruction_address = br_bd;
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
}
@ -1499,8 +1495,7 @@ void ppc_bcl()
if (ctr_ok && cnd_ok){
ppc_next_instruction_address = (ppc_state.ppc_pc + br_bd);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
}
@ -1522,8 +1517,7 @@ void ppc_bcla()
if (ctr_ok && cnd_ok){
ppc_next_instruction_address = br_bd;
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
}
@ -1538,8 +1532,7 @@ void ppc_bcctr()
if (cnd_ok){
ppc_next_instruction_address = (ppc_state.ppc_spr[9] & 0xFFFFFFFCUL);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
}
@ -1553,8 +1546,7 @@ void ppc_bcctrl()
if (cnd_ok){
ppc_next_instruction_address = (ppc_state.ppc_spr[9] & 0xFFFFFFFCUL);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
}
@ -1575,8 +1567,7 @@ void ppc_bclr()
if (ctr_ok && cnd_ok){
ppc_next_instruction_address = (ppc_state.ppc_spr[8] & 0xFFFFFFFCUL);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
}
@ -1596,8 +1587,7 @@ void ppc_bclrl()
if (ctr_ok && cnd_ok){
ppc_next_instruction_address = (ppc_state.ppc_spr[8] & 0xFFFFFFFCUL);
grab_branch = 1;
bb_end = true;
bb_kind = BB_end_reason::BB_BRANCH;
bb_kind = BB_end_kind::BB_BRANCH;
}
ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4;
}
@ -1750,12 +1740,11 @@ void ppc_rfi(){
ppc_next_instruction_address = ppc_state.ppc_spr[26] & 0xFFFFFFFCUL;
grab_return = true;
bb_end = true;
bb_kind = BB_end_reason::BB_RFI;
bb_kind = BB_end_kind::BB_RFI;
}
void ppc_sc(){
ppc_exception_handler(0x0C00, 0x20000);
ppc_exception_handler(Except_Type::EXC_SYSCALL, 0x20000);
}
void ppc_tw(){
@ -1767,7 +1756,7 @@ void ppc_tw(){
(((int32_t)ppc_state.ppc_gpr[reg_a] == (int32_t)ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x04)) || \
((ppc_state.ppc_gpr[reg_a] < ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x02)) || \
((ppc_state.ppc_gpr[reg_a] > ppc_state.ppc_gpr[reg_b]) & (ppc_to & 0x01))){
ppc_exception_handler(0x0700, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1780,7 +1769,7 @@ void ppc_twi(){
(((int32_t)ppc_state.ppc_gpr[reg_a] == simm) & (ppc_to & 0x04)) || \
((ppc_state.ppc_gpr[reg_a] < (uint32_t)simm) & (ppc_to & 0x02)) || \
((ppc_state.ppc_gpr[reg_a] > (uint32_t)simm) & (ppc_to & 0x01))){
ppc_exception_handler(0x0700, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
}
@ -1838,7 +1827,7 @@ void ppc_dcbz(){
address_quickinsert_translate(0, (ppc_effective_address + 28), 4);
}
else{
ppc_exception_handler(0x0600, 0x00000);
ppc_exception_handler(Except_Type::EXC_ALIGNMENT, 0x00000);
}
}
@ -1873,7 +1862,7 @@ void ppc_stbux(){
address_quickinsert_translate(ppc_result_d, ppc_effective_address, 1);
}
else{
ppc_exception_handler(0x07000, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
ppc_result_a = ppc_effective_address;
ppc_store_result_rega();
@ -1996,7 +1985,7 @@ void ppc_lbzu(){
ppc_effective_address = ppc_result_a + grab_d;
}
else{
ppc_exception_handler(0x0700, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
address_quickgrab_translate(ppc_effective_address, 1);
ppc_result_d = return_value;
@ -2021,7 +2010,7 @@ void ppc_lbzux(){
ppc_effective_address = ppc_result_a + ppc_result_b;
}
else{
ppc_exception_handler(0x0700, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
address_quickgrab_translate(ppc_effective_address, 1);
ppc_result_d = return_value;
@ -2179,7 +2168,7 @@ void ppc_lwzu(){
ppc_effective_address = ppc_result_a + grab_d;
}
else{
ppc_exception_handler(0x0700, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
address_quickgrab_translate(ppc_effective_address, 4);
ppc_result_d = return_value;
@ -2204,7 +2193,7 @@ void ppc_lwzux(){
ppc_effective_address = ppc_result_a + ppc_result_b;
}
else{
ppc_exception_handler(0x0700, 0x20000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
}
address_quickgrab_translate(ppc_effective_address, 4);
ppc_result_d = return_value;
@ -2293,10 +2282,10 @@ void ppc_lswx(){
ppc_grab_regsdab();
//Invalid instruction forms
if ((ppc_result_d == 0) && (ppc_result_a == 0)){
ppc_exception_handler(0x0700, 0x100000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x100000);
}
if ((ppc_result_d == ppc_result_a) || (ppc_result_a == ppc_result_b)){
ppc_exception_handler(0x0700, 0x100000);
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x100000);
}
ppc_effective_address = (reg_a == 0)?ppc_result_b:(ppc_result_a + ppc_result_b);
grab_inb = ppc_state.ppc_spr[1] & 127;

View File

@ -126,75 +126,6 @@ uint64_t rev_endian64(uint64_t insert_int){
return ENDIAN_REVERSE64(insert_int);
}
void ppc_exception_handler(uint32_t exception_type, uint32_t handle_args){
ppc_next_instruction_address = 0x0; //used to construct a new address
grab_exception = true;
bb_end = 0;
bb_kind = BB_end_reason::BB_EXCEPTION;
printf("MSR VALUE: %x \n Exception Type: %x", ppc_state.ppc_msr, exception_type);
//Check ROM Exception Prefix
if (ppc_state.ppc_msr & 0x40){
ppc_next_instruction_address |= 0xFFF00000;
}
else{
ppc_next_instruction_address &= 0x0000FFFF;
}
switch(exception_type){
case 0x0100: //System Reset
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = ppc_state.ppc_msr;
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0100;
break;
/**
case 0x0200: //Machine Check
break;
case 0x0300: //DSI
break;
case 0x0400: //ISI
break;
**/
case 0x0500: //External Interrupt
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0500;
break;
case 0x0600: //Alignment Exception
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_state.ppc_spr[19] = ppc_cur_instruction;
ppc_next_instruction_address += 0x0600;
case 0x0700: //Program;
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
handle_args += 0x10000;
ppc_state.ppc_spr[27] = handle_args + (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0700;
break;
case 0x0C00: //Sys Call
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += 0x0C00;
break;
/**
case 0x0d: //Trace
break
**/
default:
ppc_state.ppc_spr[26] = ((ppc_cur_instruction + 4) & 0xFFFFFFFC);
ppc_state.ppc_spr[27] = (ppc_state.ppc_msr & 0xFFFF);
ppc_state.ppc_msr = (ppc_state.ppc_msr & 0xFFFD0041);
ppc_next_instruction_address += exception_type;
}
}
//Initialize the PPC's registers.
void reg_init(){
for (uint32_t i = 0; i < 32; i++){