From e76ef61f53b13437f66c4d02f039e866b273aaf7 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Fri, 3 Jan 2020 21:01:02 +0100 Subject: [PATCH] ppcexec: pagewise MMU translation for code. --- cpu/ppc/ppcemu.h | 10 +++++ cpu/ppc/ppcexec.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++ cpu/ppc/ppcmmu.cpp | 2 +- cpu/ppc/ppcmmu.h | 1 + cpu/ppc/ppcopcodes.cpp | 26 +++++++++++ main.cpp | 2 + 6 files changed, 139 insertions(+), 1 deletion(-) diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index ed6a35f..23a366c 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -160,6 +160,16 @@ 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 BB_end_reason { + 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; + extern bool grab_branch; extern bool grab_exception; extern bool grab_return; diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 2aecdf7..95daab8 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -6,6 +6,11 @@ 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 */ + +uint64_t timebase_counter; /* internal timebase counter */ + clock_t clock_test_begin; //Used to make sure the TBR does not increment so quickly. /** Opcode lookup tables. */ @@ -508,6 +513,7 @@ void ppc_tbr_update() } /** Execute PPC code as long as power is on. */ +#if 0 void ppc_exec() { while (power_on){ @@ -531,8 +537,47 @@ void ppc_exec() } } } +#else +void ppc_exec() +{ + uint32_t bb_start_la, page_start; + uint8_t *pc_real; + + /* start new basic block */ + bb_start_la = ppc_state.ppc_pc; + bb_end = false; + + /* initial MMU translation for the current code page. */ + pc_real = quickinstruction_translate(bb_start_la); + + /* set current code page limits */ + page_start = bb_start_la & 0xFFFFF000; + + while (power_on) { + ppc_main_opcode(); + if (bb_end) { + 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) { + page_start = bb_start_la & 0xFFFFF000; + pc_real = quickinstruction_translate(bb_start_la); + } else { + pc_real += (int)bb_start_la - (int)ppc_state.ppc_pc; + ppc_set_cur_instruction(pc_real); + } + ppc_state.ppc_pc = bb_start_la; + bb_end = false; + } else { + ppc_state.ppc_pc += 4; + pc_real += 4; + ppc_set_cur_instruction(pc_real); + } + } +} +#endif /** Execute one PPC instruction. */ +#if 0 void ppc_exec_single() { quickinstruction_translate(ppc_state.ppc_pc); @@ -553,8 +598,23 @@ void ppc_exec_single() ppc_tbr_update(); } } +#else +void ppc_exec_single() +{ + quickinstruction_translate(ppc_state.ppc_pc); + ppc_main_opcode(); + if (bb_end) { + ppc_state.ppc_pc = ppc_next_instruction_address; + bb_end = false; + } else { + ppc_state.ppc_pc += 4; + } + timebase_counter += 1; +} +#endif /** Execute PPC code until goal_addr is reached. */ +#if 0 void ppc_exec_until(uint32_t goal_addr) { while (ppc_state.ppc_pc != goal_addr) { @@ -578,8 +638,47 @@ void ppc_exec_until(uint32_t goal_addr) ppc_cur_instruction = 0; } } +#else +void ppc_exec_until(uint32_t goal_addr) +{ + uint32_t bb_start_la, page_start; + uint8_t *pc_real; + + /* start new basic block */ + bb_start_la = ppc_state.ppc_pc; + bb_end = false; + + /* initial MMU translation for the current code page. */ + pc_real = quickinstruction_translate(bb_start_la); + + /* set current code page limits */ + page_start = bb_start_la & 0xFFFFF000; + + while (ppc_state.ppc_pc != goal_addr) { + ppc_main_opcode(); + if (bb_end) { + 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) { + page_start = bb_start_la & 0xFFFFF000; + pc_real = quickinstruction_translate(bb_start_la); + } else { + pc_real += (int)bb_start_la - (int)ppc_state.ppc_pc; + ppc_set_cur_instruction(pc_real); + } + ppc_state.ppc_pc = bb_start_la; + bb_end = false; + } else { + ppc_state.ppc_pc += 4; + pc_real += 4; + ppc_set_cur_instruction(pc_real); + } + } +} +#endif void ppc_init() { clock_test_begin = clock(); + timebase_counter = 0; } diff --git a/cpu/ppc/ppcmmu.cpp b/cpu/ppc/ppcmmu.cpp index 0de75d0..10275ae 100644 --- a/cpu/ppc/ppcmmu.cpp +++ b/cpu/ppc/ppcmmu.cpp @@ -33,7 +33,7 @@ PPC_BAT_entry ibat_array[4] = {{0}}; PPC_BAT_entry dbat_array[4] = {{0}}; -static inline void ppc_set_cur_instruction(const uint8_t *ptr) +void ppc_set_cur_instruction(const uint8_t *ptr) { ppc_cur_instruction = READ_DWORD_BE(ptr); } diff --git a/cpu/ppc/ppcmmu.h b/cpu/ppc/ppcmmu.h index cdd8569..6ae54b6 100644 --- a/cpu/ppc/ppcmmu.h +++ b/cpu/ppc/ppcmmu.h @@ -29,6 +29,7 @@ typedef struct PPC_BAT_entry { extern void ibat_update(uint32_t bat_reg); extern void dbat_update(uint32_t bat_reg); +extern void ppc_set_cur_instruction(const uint8_t *ptr); extern void address_quickinsert_translate(uint32_t value_insert, uint32_t address_grab, uint8_t num_bytes); extern void address_quickgrab_translate(uint32_t address_grab, uint8_t num_bytes); extern uint8_t *quickinstruction_translate(uint32_t address_grab); diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index abeca16..36f6b13 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -1405,6 +1405,8 @@ 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_BRANCH; } void ppc_bl(){ @@ -1413,6 +1415,8 @@ 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_BRANCH; } void ppc_ba(){ @@ -1420,6 +1424,8 @@ 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_BRANCH; } void ppc_bla(){ @@ -1428,6 +1434,8 @@ 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_BRANCH; } void ppc_bc() @@ -1447,6 +1455,8 @@ 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_BRANCH; } } @@ -1467,6 +1477,8 @@ void ppc_bca() if (ctr_ok && cnd_ok){ ppc_next_instruction_address = br_bd; grab_branch = 1; + bb_end = true; + bb_kind = BB_BRANCH; } } @@ -1487,6 +1499,8 @@ 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_BRANCH; } ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; } @@ -1508,6 +1522,8 @@ void ppc_bcla() if (ctr_ok && cnd_ok){ ppc_next_instruction_address = br_bd; grab_branch = 1; + bb_end = true; + bb_kind = BB_BRANCH; } ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; } @@ -1522,6 +1538,8 @@ 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_BRANCH; } } @@ -1535,6 +1553,8 @@ 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_BRANCH; } ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; } @@ -1555,6 +1575,8 @@ 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_BRANCH; } } @@ -1574,6 +1596,8 @@ 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_BRANCH; } ppc_state.ppc_spr[8] = ppc_state.ppc_pc + 4; } @@ -1726,6 +1750,8 @@ void ppc_rfi(){ ppc_next_instruction_address = ppc_state.ppc_spr[26] & 0xFFFFFFFCUL; grab_return = true; + bb_end = true; + bb_kind = BB_RFI; } void ppc_sc(){ diff --git a/main.cpp b/main.cpp index 6fff221..c95af65 100644 --- a/main.cpp +++ b/main.cpp @@ -129,6 +129,8 @@ uint64_t rev_endian64(uint64_t 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_EXCEPTION; printf("MSR VALUE: %x \n Exception Type: %x", ppc_state.ppc_msr, exception_type);