mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-09-30 09:55:05 +00:00
ppcexec: new TBR/DEC updating code.
This commit is contained in:
parent
07340d82dd
commit
f204caa907
@ -33,6 +33,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
#include "ppcemu.h"
|
#include "ppcemu.h"
|
||||||
#include "ppcmmu.h"
|
#include "ppcmmu.h"
|
||||||
|
|
||||||
|
#define NEW_TBR_UPDATE_ALGO
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
MemCtrlBase *mem_ctrl_instance = 0;
|
MemCtrlBase *mem_ctrl_instance = 0;
|
||||||
@ -52,7 +54,13 @@ uint32_t ppc_next_instruction_address; //Used for branching, setting up the NIA
|
|||||||
|
|
||||||
BB_end_kind bb_kind; /* basic block end */
|
BB_end_kind bb_kind; /* basic block end */
|
||||||
|
|
||||||
uint64_t timebase_counter; /* internal timebase counter */
|
/* variables related to virtual time */
|
||||||
|
uint64_t cycles_count; /* contains number of cycles executed so far */
|
||||||
|
uint64_t old_cycles_count; /* previous value for cycles_count */
|
||||||
|
uint64_t timebase_counter; /* internal timebase counter */
|
||||||
|
uint32_t decr; /* current value of PPC DEC register */
|
||||||
|
uint8_t old_decr_msb; /* MSB value for previous DEC value */
|
||||||
|
uint8_t tbr_factor; /* cycles_count to TBR freq ratio in 2^x units */
|
||||||
|
|
||||||
clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly.
|
clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly.
|
||||||
|
|
||||||
@ -426,6 +434,18 @@ static std::unordered_map<uint16_t, PPCOpcode> SubOpcode63Grabber = {
|
|||||||
{2045, &ppc_fnmsubdot}, {2046, &ppc_fnmadd}, {2047, &ppc_fnmadddot}
|
{2045, &ppc_fnmsubdot}, {2046, &ppc_fnmadd}, {2047, &ppc_fnmadddot}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define UPDATE_TBR_DEC \
|
||||||
|
if ((delta = (cycles_count - old_cycles_count) >> tbr_factor)) { \
|
||||||
|
timebase_counter += delta; \
|
||||||
|
decr -= delta; \
|
||||||
|
if ((decr & 0x80000000) && !old_decr_msb) { \
|
||||||
|
old_decr_msb = decr >> 31; \
|
||||||
|
/* signal_decr_int(); */ \
|
||||||
|
} \
|
||||||
|
old_cycles_count += delta << tbr_factor; \
|
||||||
|
}
|
||||||
|
|
||||||
/** Opcode decoding functions. */
|
/** Opcode decoding functions. */
|
||||||
|
|
||||||
void ppc_illegalop() {
|
void ppc_illegalop() {
|
||||||
@ -532,61 +552,11 @@ void ppc_main_opcode() {
|
|||||||
OpcodeGrabber[ppc_mainop]();
|
OpcodeGrabber[ppc_mainop]();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Old time base register (TBR) update code. */
|
|
||||||
void tbr_update()
|
|
||||||
{
|
|
||||||
clock_t clock_test_current = clock();
|
|
||||||
uint32_t test_clock = ((uint32_t)(clock_test_current - clock_test_begin)) / CLOCKS_PER_SEC;
|
|
||||||
if (test_clock) {
|
|
||||||
if (ppc_state.tbr[0] != 0xFFFFFFFF) {
|
|
||||||
ppc_state.tbr[0]++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ppc_state.tbr[0] = 0;
|
|
||||||
if (ppc_state.tbr[1] != 0xFFFFFFFF) {
|
|
||||||
ppc_state.tbr[1]++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ppc_state.tbr[1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
clock_test_begin = clock();
|
|
||||||
//Placeholder Decrementing Code
|
|
||||||
if (ppc_state.spr[22] > 0) {
|
|
||||||
ppc_state.spr[22]--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Execute PPC code as long as power is on. */
|
/** Execute PPC code as long as power is on. */
|
||||||
#if 0
|
|
||||||
void ppc_exec()
|
void ppc_exec()
|
||||||
{
|
{
|
||||||
while (power_on) {
|
uint32_t bb_start_la, page_start, delta;
|
||||||
//printf("PowerPC Address: %x \n", ppc_state.pc);
|
|
||||||
quickinstruction_translate(ppc_state.pc);
|
|
||||||
ppc_main_opcode();
|
|
||||||
if (grab_branch & !grab_exception) {
|
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
|
||||||
grab_branch = 0;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
else if (grab_return | grab_exception) {
|
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
|
||||||
grab_exception = 0;
|
|
||||||
grab_return = 0;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ppc_state.pc += 4;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void ppc_exec()
|
|
||||||
{
|
|
||||||
uint32_t bb_start_la, page_start;
|
|
||||||
uint8_t* pc_real;
|
uint8_t* pc_real;
|
||||||
|
|
||||||
/* start new basic block */
|
/* start new basic block */
|
||||||
@ -595,7 +565,12 @@ void ppc_exec()
|
|||||||
|
|
||||||
if (setjmp(exc_env)) {
|
if (setjmp(exc_env)) {
|
||||||
/* reaching here means we got a low-level exception */
|
/* reaching here means we got a low-level exception */
|
||||||
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
|
cycles_count += ((ppc_state.pc - bb_start_la) >> 2) + 1;
|
||||||
|
UPDATE_TBR_DEC
|
||||||
|
#else
|
||||||
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
||||||
|
#endif
|
||||||
bb_start_la = ppc_next_instruction_address;
|
bb_start_la = ppc_next_instruction_address;
|
||||||
pc_real = quickinstruction_translate(bb_start_la);
|
pc_real = quickinstruction_translate(bb_start_la);
|
||||||
page_start = bb_start_la & 0xFFFFF000;
|
page_start = bb_start_la & 0xFFFFF000;
|
||||||
@ -614,7 +589,12 @@ again:
|
|||||||
while (power_on) {
|
while (power_on) {
|
||||||
ppc_main_opcode();
|
ppc_main_opcode();
|
||||||
if (bb_kind != BB_end_kind::BB_NONE) {
|
if (bb_kind != BB_end_kind::BB_NONE) {
|
||||||
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
|
cycles_count += ((ppc_state.pc - bb_start_la) >> 2) + 1;
|
||||||
|
UPDATE_TBR_DEC
|
||||||
|
#else
|
||||||
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
||||||
|
#endif
|
||||||
bb_start_la = ppc_next_instruction_address;
|
bb_start_la = ppc_next_instruction_address;
|
||||||
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
|
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
|
||||||
page_start = bb_start_la & 0xFFFFF000;
|
page_start = bb_start_la & 0xFFFFF000;
|
||||||
@ -634,36 +614,20 @@ again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Execute one PPC instruction. */
|
/** Execute one PPC instruction. */
|
||||||
#if 0
|
|
||||||
void ppc_exec_single()
|
|
||||||
{
|
|
||||||
quickinstruction_translate(ppc_state.pc);
|
|
||||||
ppc_main_opcode();
|
|
||||||
if (grab_branch && !grab_exception) {
|
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
|
||||||
grab_branch = 0;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
else if (grab_return || grab_exception) {
|
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
|
||||||
grab_exception = 0;
|
|
||||||
grab_return = 0;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ppc_state.pc += 4;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void ppc_exec_single()
|
void ppc_exec_single()
|
||||||
{
|
{
|
||||||
|
uint32_t delta;
|
||||||
|
|
||||||
if (setjmp(exc_env)) {
|
if (setjmp(exc_env)) {
|
||||||
/* reaching here means we got a low-level exception */
|
/* reaching here means we got a low-level exception */
|
||||||
timebase_counter += 1;
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
|
cycles_count++;
|
||||||
|
UPDATE_TBR_DEC
|
||||||
|
#else
|
||||||
|
timebase_counter++;
|
||||||
|
#endif
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
ppc_state.pc = ppc_next_instruction_address;
|
||||||
bb_kind = BB_end_kind::BB_NONE;
|
bb_kind = BB_end_kind::BB_NONE;
|
||||||
return;
|
return;
|
||||||
@ -678,39 +642,18 @@ void ppc_exec_single()
|
|||||||
else {
|
else {
|
||||||
ppc_state.pc += 4;
|
ppc_state.pc += 4;
|
||||||
}
|
}
|
||||||
timebase_counter += 1;
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
}
|
cycles_count++;
|
||||||
|
UPDATE_TBR_DEC
|
||||||
|
#else
|
||||||
|
timebase_counter++;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/** Execute PPC code until goal_addr is reached. */
|
/** Execute PPC code until goal_addr is reached. */
|
||||||
#if 0
|
|
||||||
void ppc_exec_until(uint32_t goal_addr)
|
void ppc_exec_until(uint32_t goal_addr)
|
||||||
{
|
{
|
||||||
while (ppc_state.pc != goal_addr) {
|
uint32_t bb_start_la, page_start, delta;
|
||||||
quickinstruction_translate(ppc_state.pc);
|
|
||||||
ppc_main_opcode();
|
|
||||||
if (grab_branch && !grab_exception) {
|
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
|
||||||
grab_branch = 0;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
else if (grab_return || grab_exception) {
|
|
||||||
ppc_state.pc = ppc_next_instruction_address;
|
|
||||||
grab_exception = 0;
|
|
||||||
grab_return = 0;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ppc_state.pc += 4;
|
|
||||||
tbr_update();
|
|
||||||
}
|
|
||||||
ppc_cur_instruction = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
void ppc_exec_until(uint32_t goal_addr)
|
|
||||||
{
|
|
||||||
uint32_t bb_start_la, page_start;
|
|
||||||
uint8_t* pc_real;
|
uint8_t* pc_real;
|
||||||
|
|
||||||
/* start new basic block */
|
/* start new basic block */
|
||||||
@ -719,7 +662,12 @@ void ppc_exec_until(uint32_t goal_addr)
|
|||||||
|
|
||||||
if (setjmp(exc_env)) {
|
if (setjmp(exc_env)) {
|
||||||
/* reaching here means we got a low-level exception */
|
/* reaching here means we got a low-level exception */
|
||||||
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
|
cycles_count += ((ppc_state.pc - bb_start_la) >> 2) + 1;
|
||||||
|
UPDATE_TBR_DEC
|
||||||
|
#else
|
||||||
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
||||||
|
#endif
|
||||||
bb_start_la = ppc_next_instruction_address;
|
bb_start_la = ppc_next_instruction_address;
|
||||||
pc_real = quickinstruction_translate(bb_start_la);
|
pc_real = quickinstruction_translate(bb_start_la);
|
||||||
page_start = bb_start_la & 0xFFFFF000;
|
page_start = bb_start_la & 0xFFFFF000;
|
||||||
@ -738,7 +686,12 @@ again:
|
|||||||
while (ppc_state.pc != goal_addr) {
|
while (ppc_state.pc != goal_addr) {
|
||||||
ppc_main_opcode();
|
ppc_main_opcode();
|
||||||
if (bb_kind != BB_end_kind::BB_NONE) {
|
if (bb_kind != BB_end_kind::BB_NONE) {
|
||||||
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
|
cycles_count += ((ppc_state.pc - bb_start_la) >> 2) + 1;
|
||||||
|
UPDATE_TBR_DEC
|
||||||
|
#else
|
||||||
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
timebase_counter += (ppc_state.pc - bb_start_la) >> 2;
|
||||||
|
#endif
|
||||||
bb_start_la = ppc_next_instruction_address;
|
bb_start_la = ppc_next_instruction_address;
|
||||||
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
|
if ((ppc_next_instruction_address & 0xFFFFF000) != page_start) {
|
||||||
page_start = bb_start_la & 0xFFFFF000;
|
page_start = bb_start_la & 0xFFFFF000;
|
||||||
@ -758,7 +711,41 @@ again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
uint64_t instr_count, old_instr_count;
|
||||||
|
|
||||||
|
void test_timebase_update()
|
||||||
|
{
|
||||||
|
uint32_t delta, factor;
|
||||||
|
uint8_t old_decr_msb;
|
||||||
|
uint8_t intervals[10] = {4, 7, 10, 2, 16, 6, 3, 20, 12, 8};
|
||||||
|
|
||||||
|
timebase_counter = 0;
|
||||||
|
decr = 0x00000003;
|
||||||
|
old_decr_msb = decr >> 31;
|
||||||
|
|
||||||
|
old_instr_count = 0xFFFFFFFFFFFFFF80UL;//0xFFFFFFFFFFFFFFD0UL;
|
||||||
|
instr_count = 0xFFFFFFFFFFFFFF80UL;//0xFFFFFFFFFFFFFFD0UL;
|
||||||
|
|
||||||
|
factor = 4;
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
cycles_count += intervals[i];
|
||||||
|
if ((delta = (cycles_count - old_cycles_count) >> factor)) {
|
||||||
|
timebase_counter += delta;
|
||||||
|
decr -= delta;
|
||||||
|
if ((decr & 0x80000000) && !old_decr_msb) {
|
||||||
|
old_decr_msb = decr >> 31;
|
||||||
|
LOG_F(ERROR, "DEC exception signaled!\n");
|
||||||
|
}
|
||||||
|
old_instr_count += delta << factor;
|
||||||
|
LOG_F(INFO, "Iteration %d, TBR=0x%llX, DEC=0x%X", i, timebase_counter, decr);
|
||||||
|
LOG_F(INFO, " icount=0x%llX, old_icount=0x%llX\n", cycles_count, old_cycles_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version)
|
void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version)
|
||||||
{
|
{
|
||||||
@ -766,8 +753,18 @@ void ppc_cpu_init(MemCtrlBase *mem_ctrl, uint32_t proc_version)
|
|||||||
|
|
||||||
mem_ctrl_instance = mem_ctrl;
|
mem_ctrl_instance = mem_ctrl;
|
||||||
|
|
||||||
clock_test_begin = clock();
|
//test_timebase_update();
|
||||||
|
|
||||||
|
/* initialize timer variables */
|
||||||
|
#ifdef NEW_TBR_UPDATE_ALGO
|
||||||
|
cycles_count = 0;
|
||||||
|
old_cycles_count = 0;
|
||||||
|
tbr_factor = 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
timebase_counter = 0;
|
timebase_counter = 0;
|
||||||
|
decr = 0;
|
||||||
|
old_decr_msb = decr >> 31;
|
||||||
|
|
||||||
/* zero all GPRs as prescribed for MPC601 */
|
/* zero all GPRs as prescribed for MPC601 */
|
||||||
/* For later PPC CPUs, GPR content is undefined */
|
/* For later PPC CPUs, GPR content is undefined */
|
||||||
|
Loading…
Reference in New Issue
Block a user