mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-12-23 06:29:38 +00:00
Merge branch 'master' of https://github.com/dingusdev/dingusppc
This commit is contained in:
commit
ea7c34f0d9
@ -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;
|
||||
@ -241,7 +260,8 @@ void ppc_changecrf0(uint32_t set_result);
|
||||
void ppc_fp_changecrf1();
|
||||
|
||||
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
90
cpu/ppc/ppcexceptions.cpp
Normal 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. */
|
||||
}
|
@ -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 */
|
||||
|
||||
@ -395,7 +395,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(){
|
||||
@ -430,7 +429,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]();
|
||||
@ -447,7 +446,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]();
|
||||
@ -464,7 +463,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]();
|
||||
@ -481,7 +480,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]();
|
||||
@ -553,7 +552,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);
|
||||
@ -561,9 +571,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) {
|
||||
@ -574,7 +585,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;
|
||||
@ -609,11 +620,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;
|
||||
}
|
||||
@ -654,7 +673,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);
|
||||
@ -662,9 +692,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) {
|
||||
@ -675,7 +706,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;
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
69
main.cpp
69
main.cpp
@ -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++){
|
||||
|
Loading…
Reference in New Issue
Block a user