Merge branch 'cpu-refactor'
This commit is contained in:
commit
5cba9c1dae
|
@ -1,3 +1,7 @@
|
|||
[submodule "thirdparty/cubeb"]
|
||||
path = thirdparty/cubeb
|
||||
url = https://github.com/DingusDevOrg/cubeb.git
|
||||
[submodule "thirdparty/capstone"]
|
||||
path = thirdparty/capstone
|
||||
url = https://github.com/maximumspatium/capstone.git
|
||||
branch = next
|
||||
|
|
|
@ -16,9 +16,45 @@ if (UNIX AND NOT APPLE)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
option(ENABLE_68K_DEBUGGER "Enable 68k debugging" OFF)
|
||||
|
||||
if (ENABLE_68K_DEBUGGER)
|
||||
# Build capstone as static library.
|
||||
set(CAPSTONE_BUILD_STATIC ON CACHE BOOL "")
|
||||
|
||||
# Turn off anything unnecessary.
|
||||
set(CAPSTONE_BUILD_SHARED OFF CACHE BOOL "")
|
||||
set(CAPSTONE_BUILD_TESTS OFF CACHE BOOL "")
|
||||
set(CAPSTONE_BUILD_CSTOOL OFF CACHE BOOL "")
|
||||
set(CAPSTONE_BUILD_DIET OFF CACHE BOOL "")
|
||||
set(CAPSTONE_OSXKERNEL_SUPPORT OFF CACHE BOOL "")
|
||||
|
||||
# Disable unused Capstone architectures.
|
||||
set(CAPSTONE_ARM_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_ARM64_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_MIPS_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_PPC_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_SPARC_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_SYSZ_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_XCORE_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_X86_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_TMS320C64X_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_M680X_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_EVM_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_MOS65XX_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_WASM_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_BPF_SUPPORT OFF CACHE BOOL "")
|
||||
set(CAPSTONE_RISCV_SUPPORT OFF CACHE BOOL "")
|
||||
|
||||
ADD_DEFINITIONS(-DENABLE_68K_DEBUGGER)
|
||||
|
||||
add_subdirectory(thirdparty/capstone EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/cpu/ppc/")
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/debugger/")
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/devices/")
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/execution")
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/machines/")
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/thirdparty/loguru/")
|
||||
|
||||
|
@ -57,6 +93,7 @@ file(GLOB TEST_SOURCES "${PROJECT_SOURCE_DIR}/cpu/ppc/test/*.cpp")
|
|||
add_executable(dingusppc ${SOURCES} $<TARGET_OBJECTS:debugger>
|
||||
$<TARGET_OBJECTS:cpu_ppc>
|
||||
$<TARGET_OBJECTS:devices>
|
||||
$<TARGET_OBJECTS:execution>
|
||||
$<TARGET_OBJECTS:machines>
|
||||
$<TARGET_OBJECTS:loguru>)
|
||||
|
||||
|
@ -70,10 +107,15 @@ target_link_libraries(dingusppc cubeb ${SDL2_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE
|
|||
target_include_directories(dingusppc PRIVATE ${CLI11_ROOT})
|
||||
endif()
|
||||
|
||||
if (ENABLE_68K_DEBUGGER)
|
||||
target_link_libraries(dingusppc capstone-static)
|
||||
endif()
|
||||
|
||||
|
||||
add_executable(testppc ${TEST_SOURCES} $<TARGET_OBJECTS:debugger>
|
||||
$<TARGET_OBJECTS:cpu_ppc>
|
||||
$<TARGET_OBJECTS:devices>
|
||||
$<TARGET_OBJECTS:execution>
|
||||
$<TARGET_OBJECTS:machines>
|
||||
$<TARGET_OBJECTS:loguru>)
|
||||
|
||||
|
@ -86,6 +128,24 @@ else()
|
|||
target_link_libraries(testppc cubeb ${SDL2_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
if (ENABLE_68K_DEBUGGER)
|
||||
target_link_libraries(testppc capstone-static)
|
||||
endif()
|
||||
|
||||
file(GLOB BENCH_SOURCES "${PROJECT_SOURCE_DIR}/benchmark/*.cpp")
|
||||
add_executable(bench1 ${BENCH_SOURCES} $<TARGET_OBJECTS:debugger>
|
||||
$<TARGET_OBJECTS:cpu_ppc>
|
||||
$<TARGET_OBJECTS:devices>
|
||||
$<TARGET_OBJECTS:execution>
|
||||
$<TARGET_OBJECTS:machines>
|
||||
$<TARGET_OBJECTS:loguru>)
|
||||
|
||||
target_link_libraries(bench1 cubeb ${SDL2_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
if (ENABLE_68K_DEBUGGER)
|
||||
target_link_libraries(bench1 capstone-static)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET testppc POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
#include <stdlib.h>
|
||||
#include <chrono>
|
||||
#include "cpu/ppc/ppcemu.h"
|
||||
#include "cpu/ppc/ppcmmu.h"
|
||||
#include "devices/mpc106.h"
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
uint32_t cs_code[] = {
|
||||
0x3863FFFC, 0x7C861671, 0x41820090, 0x70600002, 0x41E2001C, 0xA0030004,
|
||||
0x3884FFFE, 0x38630002, 0x5486F0BF, 0x7CA50114, 0x41820070, 0x70C60003,
|
||||
0x41820014, 0x7CC903A6, 0x84030004, 0x7CA50114, 0x4200FFF8, 0x5486E13F,
|
||||
0x41820050, 0x80030004, 0x7CC903A6, 0x80C30008, 0x7CA50114, 0x80E3000C,
|
||||
0x7CA53114, 0x85030010, 0x7CA53914, 0x42400028, 0x80030004, 0x7CA54114,
|
||||
0x80C30008, 0x7CA50114, 0x80E3000C, 0x7CA53114, 0x85030010, 0x7CA53914,
|
||||
0x4200FFE0, 0x7CA54114, 0x70800002, 0x41E20010, 0xA0030004, 0x38630002,
|
||||
0x7CA50114, 0x70800001, 0x41E20010, 0x88030004, 0x5400402E, 0x7CA50114,
|
||||
0x7C650194, 0x4E800020
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int i;
|
||||
|
||||
/* initialize logging */
|
||||
loguru::g_preamble_date = false;
|
||||
loguru::g_preamble_time = false;
|
||||
loguru::g_preamble_thread = false;
|
||||
|
||||
loguru::g_stderr_verbosity = 0;
|
||||
loguru::init(argc, argv);
|
||||
|
||||
MPC106* grackle_obj = new MPC106;
|
||||
|
||||
/* we need some RAM */
|
||||
if (!grackle_obj->add_ram_region(0, 0x9000)) {
|
||||
LOG_F(ERROR, "Could not create RAM region");
|
||||
delete(grackle_obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ppc_cpu_init(grackle_obj, PPC_VER::MPC750);
|
||||
|
||||
/* load executable code into RAM at address 0 */
|
||||
for (i = 0; i < sizeof(cs_code); i++) {
|
||||
mem_write_dword(i*4, cs_code[i]);
|
||||
}
|
||||
|
||||
srand(0xCAFEBABE);
|
||||
|
||||
for (i = 0; i < 32768; i++) {
|
||||
mem_write_byte(0x1000+i, rand() % 256);
|
||||
}
|
||||
|
||||
/* prepare benchmark code execution */
|
||||
ppc_state.pc = 0;
|
||||
ppc_state.gpr[3] = 0x1000; // buf
|
||||
ppc_state.gpr[4] = 0x8000; // len
|
||||
ppc_state.gpr[5] = 0; // sum
|
||||
|
||||
ppc_exec_until(0xC4);
|
||||
|
||||
LOG_F(INFO, "Checksum: 0x%08X", ppc_state.gpr[3]);
|
||||
|
||||
// run the clock once for cache fill etc.
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
auto end_time = std::chrono::steady_clock::now();
|
||||
auto time_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
|
||||
LOG_F(INFO, "Time elapsed (dry run): %lld ns", time_elapsed.count());
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ppc_state.pc = 0;
|
||||
ppc_state.gpr[3] = 0x1000; // buf
|
||||
ppc_state.gpr[4] = 0x8000; // len
|
||||
ppc_state.gpr[5] = 0; // sum
|
||||
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
|
||||
ppc_exec_until(0xC4);
|
||||
|
||||
auto end_time = std::chrono::steady_clock::now();
|
||||
|
||||
LOG_F(INFO, "Checksum: 0x%08X", ppc_state.gpr[3]);
|
||||
|
||||
auto time_elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time);
|
||||
LOG_F(INFO, "Time elapsed (run #%d): %lld ns", i, time_elapsed.count());
|
||||
}
|
||||
|
||||
delete(grackle_obj);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -24,62 +24,42 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
#include "ppcemu.h"
|
||||
#include "ppcmmu.h"
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
|
||||
void power_abs() {
|
||||
// Affects the XER register's SO and OV Bits
|
||||
|
||||
inline void power_setsoov(uint32_t a, uint32_t b, uint32_t d) {
|
||||
if ((a ^ b) & (a ^ d) & 0x80000000UL) {
|
||||
ppc_state.spr[SPR::XER] |= 0xC0000000UL;
|
||||
} else {
|
||||
ppc_state.spr[SPR::XER] &= 0xBFFFFFFFUL;
|
||||
}
|
||||
}
|
||||
|
||||
void dppc_interpreter::power_abs() {
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
if (oe_flag)
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
|
||||
void power_absdot() {
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_abso() {
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_absodot() {
|
||||
ppc_grab_regsda();
|
||||
if (ppc_result_a == 0x80000000) {
|
||||
ppc_result_d = ppc_result_a;
|
||||
ppc_state.spr[SPR::XER] |= 0x40000000;
|
||||
|
||||
} else {
|
||||
ppc_result_d = ppc_result_a & 0x7FFFFFFF;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_clcs() {
|
||||
void dppc_interpreter::power_clcs() {
|
||||
ppc_grab_regsda();
|
||||
switch (reg_a) {
|
||||
case 12:
|
||||
|
@ -91,107 +71,56 @@ void power_clcs() {
|
|||
default:
|
||||
ppc_result_d = 0;
|
||||
}
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_clcsdot() {
|
||||
switch (reg_a) {
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
ppc_result_d = 65535;
|
||||
break;
|
||||
default:
|
||||
ppc_result_d = 0;
|
||||
if (rc_flag) {
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
printf("Does RC do anything here? (TODO) \n");
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
printf("Does RC do anything here? (TODO) \n");
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_div() {
|
||||
void dppc_interpreter::power_div() {
|
||||
ppc_grab_regsdab();
|
||||
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
|
||||
|
||||
if (oe_flag)
|
||||
power_setsoov(ppc_result_b, ppc_result_a, ppc_result_d);
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_divdot() {
|
||||
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
|
||||
}
|
||||
|
||||
void power_divo() {
|
||||
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
|
||||
}
|
||||
|
||||
void power_divodot() {
|
||||
ppc_result_d = (ppc_result_a | ppc_state.spr[SPR::MQ]) / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a | ppc_state.spr[SPR::MQ]) % ppc_result_b;
|
||||
}
|
||||
|
||||
void power_divs() {
|
||||
void dppc_interpreter::power_divs() {
|
||||
ppc_grab_regsdab();
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
|
||||
|
||||
if (oe_flag)
|
||||
power_setsoov(ppc_result_b, ppc_result_a, ppc_result_d);
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_divsdot() {
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
|
||||
}
|
||||
|
||||
void power_divso() {
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
|
||||
}
|
||||
|
||||
void power_divsodot() {
|
||||
ppc_result_d = ppc_result_a / ppc_result_b;
|
||||
ppc_state.spr[SPR::MQ] = (ppc_result_a % ppc_result_b);
|
||||
}
|
||||
|
||||
void power_doz() {
|
||||
void dppc_interpreter::power_doz() {
|
||||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_dozdot() {
|
||||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_dozo() {
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void power_dozodot() {
|
||||
if (((int32_t)ppc_result_a) > ((int32_t)ppc_result_b)) {
|
||||
ppc_result_d = 0;
|
||||
} else {
|
||||
ppc_result_d = ~ppc_result_a + ppc_result_b + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void power_dozi() {
|
||||
void dppc_interpreter::power_dozi() {
|
||||
ppc_grab_regsdab();
|
||||
if (((int32_t)ppc_result_a) > simm) {
|
||||
ppc_result_d = 0;
|
||||
|
@ -201,7 +130,7 @@ void power_dozi() {
|
|||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_lscbx() {
|
||||
void dppc_interpreter::power_lscbx() {
|
||||
ppc_grab_regsdab();
|
||||
uint32_t bytes_copied = 0;
|
||||
bool match_found = false;
|
||||
|
@ -254,14 +183,15 @@ void power_lscbx() {
|
|||
}
|
||||
} while (bytes_to_load > 0);
|
||||
ppc_state.spr[SPR::XER] = (ppc_state.spr[SPR::XER] & 0xFFFFFF80) | bytes_copied;
|
||||
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_lscbxdot() {
|
||||
printf("OOPS! Placeholder!!! \n");
|
||||
}
|
||||
|
||||
void power_maskg() {
|
||||
void dppc_interpreter::power_maskg() {
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_start = ppc_result_d & 31;
|
||||
uint32_t mask_end = ppc_result_b & 31;
|
||||
|
@ -281,33 +211,14 @@ void power_maskg() {
|
|||
}
|
||||
|
||||
ppc_result_a = insert_mask;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_maskgdot() {
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_start = ppc_result_d & 31;
|
||||
uint32_t mask_end = ppc_result_b & 31;
|
||||
uint32_t insert_mask = 0;
|
||||
|
||||
if (mask_start < (mask_end + 1)) {
|
||||
for (uint32_t i = mask_start; i < mask_end; i++) {
|
||||
insert_mask |= (0x80000000 >> i);
|
||||
}
|
||||
} else if (mask_start == (mask_end + 1)) {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
} else {
|
||||
insert_mask = 0xFFFFFFFF;
|
||||
for (uint32_t i = (mask_end + 1); i < (mask_start - 1); i++) {
|
||||
insert_mask &= (~(0x80000000 >> i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_mask;
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_maskir() {
|
||||
void dppc_interpreter::power_maskir() {
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_insert = ppc_result_a;
|
||||
uint32_t insert_rot = 0x80000000;
|
||||
|
@ -320,82 +231,38 @@ void power_maskir() {
|
|||
} while (insert_rot > 0);
|
||||
|
||||
ppc_result_a = (ppc_result_d & ppc_result_b);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_maskirdot() {
|
||||
ppc_grab_regssab();
|
||||
uint32_t mask_insert = ppc_result_a;
|
||||
uint32_t insert_rot = 0x80000000;
|
||||
do {
|
||||
if (ppc_result_b & insert_rot) {
|
||||
mask_insert &= ~insert_rot;
|
||||
mask_insert |= (ppc_result_d & insert_rot);
|
||||
}
|
||||
insert_rot = insert_rot >> 1;
|
||||
} while (insert_rot > 0);
|
||||
|
||||
ppc_result_a = (ppc_result_d & ppc_result_b);
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_mul() {
|
||||
void dppc_interpreter::power_mul() {
|
||||
ppc_grab_regsdab();
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_muldot() {
|
||||
ppc_grab_regsdab();
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_mulo() {
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
}
|
||||
|
||||
void power_mulodot() {
|
||||
uint64_t product;
|
||||
|
||||
product = ((uint64_t)ppc_result_a) * ((uint64_t)ppc_result_b);
|
||||
ppc_result_d = ((uint32_t)(product >> 32));
|
||||
ppc_state.spr[SPR::MQ] = ((uint32_t)(product));
|
||||
}
|
||||
|
||||
void power_nabs() {
|
||||
void dppc_interpreter::power_nabs() {
|
||||
ppc_grab_regsda();
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_d);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void power_nabsdot() {
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
}
|
||||
|
||||
void power_nabso() {
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
}
|
||||
|
||||
void power_nabsodot() {
|
||||
ppc_result_d = (0x80000000 | ppc_result_a);
|
||||
}
|
||||
|
||||
void power_rlmi() {
|
||||
void dppc_interpreter::power_rlmi() {
|
||||
ppc_grab_regssab();
|
||||
unsigned rot_mb = (ppc_cur_instruction >> 6) & 31;
|
||||
unsigned rot_me = (ppc_cur_instruction >> 1) & 31;
|
||||
|
@ -420,28 +287,22 @@ void power_rlmi() {
|
|||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_rrib() {
|
||||
void dppc_interpreter::power_rrib() {
|
||||
ppc_grab_regssab();
|
||||
|
||||
if (ppc_result_d & 0x80000000) {
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_rribdot() {
|
||||
ppc_grab_regssab();
|
||||
if (ppc_result_d & 0x80000000) {
|
||||
ppc_result_a |= (0x80000000 >> ppc_result_b);
|
||||
} else {
|
||||
ppc_result_a &= ~(0x80000000 >> ppc_result_b);
|
||||
}
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sle() {
|
||||
void dppc_interpreter::power_sle() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
|
@ -451,24 +312,14 @@ void power_sle() {
|
|||
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
|
||||
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final & insert_mask;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sledot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_final = ((ppc_result_d << rot_amt) | (ppc_result_d >> (32 - rot_amt)));
|
||||
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final & insert_mask;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sleq() {
|
||||
void dppc_interpreter::power_sleq() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
|
@ -487,33 +338,14 @@ void power_sleq() {
|
|||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sleqdot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start = ((ppc_result_d << rot_amt) | (ppc_result_d >> (rot_amt - 31)));
|
||||
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (insert_mask & (1 << i)) {
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sliq() {
|
||||
void dppc_interpreter::power_sliq() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
|
@ -532,33 +364,14 @@ void power_sliq() {
|
|||
|
||||
ppc_result_a = insert_end & insert_mask;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sliqdot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (rot_sh - 31)));
|
||||
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (insert_mask & (1 << i)) {
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end & insert_mask;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_slliq() {
|
||||
void dppc_interpreter::power_slliq() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
|
@ -577,65 +390,30 @@ void power_slliq() {
|
|||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_slliqdot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start = ((ppc_result_d << rot_sh) | (ppc_result_d >> (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (insert_mask & (1 << i)) {
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sllq() {
|
||||
void dppc_interpreter::power_sllq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for sllq!!! \n");
|
||||
}
|
||||
|
||||
void power_sllqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for sllq.!!! \n");
|
||||
}
|
||||
|
||||
void power_slq() {
|
||||
void dppc_interpreter::power_slq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for slq!!! \n");
|
||||
}
|
||||
|
||||
void power_slqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for slq.!!! \n");
|
||||
}
|
||||
|
||||
void power_sraiq() {
|
||||
void dppc_interpreter::power_sraiq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for sraiq!!! \n");
|
||||
}
|
||||
|
||||
void power_sraiqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for sraiq.!!! \n");
|
||||
}
|
||||
|
||||
void power_sraq() {
|
||||
void dppc_interpreter::power_sraq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for sraq!!! \n");
|
||||
}
|
||||
|
||||
void power_sraqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for sraq.!!! \n");
|
||||
}
|
||||
|
||||
void power_sre() {
|
||||
void dppc_interpreter::power_sre() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
|
@ -645,32 +423,16 @@ void power_sre() {
|
|||
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
|
||||
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final;
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sredot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
uint32_t rot_amt = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_amt; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_final = ((ppc_result_d >> rot_amt) | (ppc_result_d << (32 - rot_amt)));
|
||||
ppc_state.spr[SPR::MQ] = insert_final & insert_mask;
|
||||
ppc_result_a = insert_final;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_srea() {
|
||||
void dppc_interpreter::power_srea() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for srea!!! \n");
|
||||
}
|
||||
|
||||
void power_sreadot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for srea.!!! \n");
|
||||
}
|
||||
|
||||
void power_sreq() {
|
||||
void dppc_interpreter::power_sreq() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = ppc_result_b & 31;
|
||||
|
@ -689,33 +451,14 @@ void power_sreq() {
|
|||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sreqdot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = ppc_result_b & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (insert_mask & (1 << i)) {
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sriq() {
|
||||
void dppc_interpreter::power_sriq() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
|
@ -734,52 +477,21 @@ void power_sriq() {
|
|||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_sriqdot() {
|
||||
ppc_grab_regssa();
|
||||
uint32_t insert_mask = 0;
|
||||
unsigned rot_sh = (ppc_cur_instruction >> 11) & 31;
|
||||
for (uint32_t i = 31; i > rot_sh; i--) {
|
||||
insert_mask |= (1 << i);
|
||||
}
|
||||
uint32_t insert_start = ((ppc_result_d >> rot_sh) | (ppc_result_d << (32 - rot_sh)));
|
||||
uint32_t insert_end = ppc_state.spr[SPR::MQ];
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (insert_mask & (1 << i)) {
|
||||
insert_end &= ~(1 << i);
|
||||
insert_end |= (insert_start & (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
ppc_result_a = insert_end;
|
||||
ppc_state.spr[SPR::MQ] = insert_start;
|
||||
ppc_changecrf0(ppc_result_a);
|
||||
ppc_store_result_rega();
|
||||
}
|
||||
|
||||
void power_srliq() {
|
||||
void dppc_interpreter::power_srliq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for slriq!!! \n");
|
||||
}
|
||||
|
||||
void power_srliqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for slriq.!!! \n");
|
||||
}
|
||||
|
||||
void power_srlq() {
|
||||
void dppc_interpreter::power_srlq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for slrq!!! \n");
|
||||
}
|
||||
|
||||
void power_srlqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for slrq.!!! \n");
|
||||
}
|
||||
|
||||
void power_srq() {
|
||||
void dppc_interpreter::power_srq() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for srq!!! \n");
|
||||
}
|
||||
|
||||
void power_srqdot() {
|
||||
LOG_F(WARNING, "OOPS! Placeholder for srq.!!! \n");
|
||||
}
|
||||
}
|
159
cpu/ppc/ppcemu.h
159
cpu/ppc/ppcemu.h
|
@ -215,6 +215,14 @@ enum class Except_Type {
|
|||
EXC_TRACE = 13
|
||||
};
|
||||
|
||||
/** Programm Exception subclasses. */
|
||||
enum Exc_Cause : uint32_t {
|
||||
FPU_OFF = 1 << (31 - 11),
|
||||
ILLEGAL_OP = 1 << (31 - 12),
|
||||
NOT_ALLOWED = 1 << (31 - 13),
|
||||
TRAP = 1 << (31 - 14),
|
||||
};
|
||||
|
||||
// extern bool bb_end;
|
||||
extern BB_end_kind bb_kind;
|
||||
|
||||
|
@ -226,10 +234,12 @@ extern bool grab_return;
|
|||
extern bool power_on;
|
||||
|
||||
extern bool is_601; // For PowerPC 601 Emulation
|
||||
extern bool is_gekko; // For GameCube Emulation
|
||||
extern bool is_altivec; // For Altivec Emulation
|
||||
extern bool is_64bit; // For PowerPC G5 Emulation
|
||||
|
||||
extern bool rc_flag; // Record flag
|
||||
extern bool oe_flag; // Overflow flag
|
||||
|
||||
// Important Addressing Integers
|
||||
extern uint32_t ppc_cur_instruction;
|
||||
extern uint32_t ppc_effective_address;
|
||||
|
@ -244,7 +254,13 @@ extern uint32_t supervisor_inst_num;
|
|||
extern void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t proc_version);
|
||||
extern void ppc_mmu_init();
|
||||
|
||||
void ppc_illegalop();
|
||||
[[noreturn]] void ppc_illegalop();
|
||||
[[noreturn]] void ppc_fpu_off();
|
||||
void ppc_illegalsubop19();
|
||||
void ppc_illegalsubop31();
|
||||
void ppc_illegalsubop59();
|
||||
void ppc_illegalsubop63();
|
||||
|
||||
void ppc_opcode4();
|
||||
void ppc_opcode16();
|
||||
void ppc_opcode18();
|
||||
|
@ -253,6 +269,8 @@ void ppc_opcode31();
|
|||
void ppc_opcode59();
|
||||
void ppc_opcode63();
|
||||
|
||||
void initialize_ppc_opcode_tables();
|
||||
|
||||
extern bool ppc_confirm_inf_nan(uint64_t input_a, uint64_t input_b, bool is_single, uint32_t op);
|
||||
extern double fp_return_double(uint32_t reg);
|
||||
extern uint64_t fp_return_uint64(uint32_t reg);
|
||||
|
@ -286,8 +304,6 @@ extern void ppc_store_dfpresult(bool int_rep);
|
|||
void ppc_changecrf0(uint32_t set_result);
|
||||
void ppc_fp_changecrf1();
|
||||
|
||||
void ppc_tbr_update();
|
||||
|
||||
/* Exception handlers. */
|
||||
[[noreturn]] void ppc_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
|
||||
[[noreturn]] void dbg_exception_handler(Except_Type exception_type, uint32_t srr1_bits);
|
||||
|
@ -296,6 +312,7 @@ void ppc_tbr_update();
|
|||
extern MemCtrlBase* mem_ctrl_instance;
|
||||
|
||||
// The functions used by the PowerPC processor
|
||||
namespace dppc_interpreter {
|
||||
extern void ppc_bcctr();
|
||||
extern void ppc_bcctrl();
|
||||
extern void ppc_bclr();
|
||||
|
@ -311,33 +328,15 @@ extern void ppc_crxor();
|
|||
extern void ppc_isync();
|
||||
|
||||
extern void ppc_add();
|
||||
extern void ppc_adddot();
|
||||
extern void ppc_addo();
|
||||
extern void ppc_addodot();
|
||||
extern void ppc_addc();
|
||||
extern void ppc_addcdot();
|
||||
extern void ppc_addco();
|
||||
extern void ppc_addcodot();
|
||||
extern void ppc_adde();
|
||||
extern void ppc_addedot();
|
||||
extern void ppc_addeo();
|
||||
extern void ppc_addeodot();
|
||||
extern void ppc_addme();
|
||||
extern void ppc_addmedot();
|
||||
extern void ppc_addmeo();
|
||||
extern void ppc_addmeodot();
|
||||
extern void ppc_addze();
|
||||
extern void ppc_addzedot();
|
||||
extern void ppc_addzeo();
|
||||
extern void ppc_addzeodot();
|
||||
extern void ppc_and();
|
||||
extern void ppc_anddot();
|
||||
extern void ppc_andc();
|
||||
extern void ppc_andcdot();
|
||||
extern void ppc_cmp();
|
||||
extern void ppc_cmpl();
|
||||
extern void ppc_cntlzw();
|
||||
extern void ppc_cntlzwdot();
|
||||
extern void ppc_dcbf();
|
||||
extern void ppc_dcbi();
|
||||
extern void ppc_dcbst();
|
||||
|
@ -345,20 +344,11 @@ extern void ppc_dcbt();
|
|||
extern void ppc_dcbtst();
|
||||
extern void ppc_dcbz();
|
||||
extern void ppc_divw();
|
||||
extern void ppc_divwdot();
|
||||
extern void ppc_divwo();
|
||||
extern void ppc_divwodot();
|
||||
extern void ppc_divwu();
|
||||
extern void ppc_divwudot();
|
||||
extern void ppc_divwuo();
|
||||
extern void ppc_divwuodot();
|
||||
extern void ppc_eieio();
|
||||
extern void ppc_eqv();
|
||||
extern void ppc_eqvdot();
|
||||
extern void ppc_extsb();
|
||||
extern void ppc_extsbdot();
|
||||
extern void ppc_extsh();
|
||||
extern void ppc_extshdot();
|
||||
extern void ppc_icbi();
|
||||
extern void ppc_mftb();
|
||||
extern void ppc_lhzux();
|
||||
|
@ -375,33 +365,17 @@ extern void ppc_lwzx();
|
|||
extern void ppc_mcrxr();
|
||||
extern void ppc_mfcr();
|
||||
extern void ppc_mulhwu();
|
||||
extern void ppc_mulhwudot();
|
||||
extern void ppc_mulhw();
|
||||
extern void ppc_mulhwdot();
|
||||
extern void ppc_mullw();
|
||||
extern void ppc_mullwdot();
|
||||
extern void ppc_mullwo();
|
||||
extern void ppc_mullwodot();
|
||||
extern void ppc_nand();
|
||||
extern void ppc_nanddot();
|
||||
extern void ppc_neg();
|
||||
extern void ppc_negdot();
|
||||
extern void ppc_nego();
|
||||
extern void ppc_negodot();
|
||||
extern void ppc_nor();
|
||||
extern void ppc_nordot();
|
||||
extern void ppc_or();
|
||||
extern void ppc_ordot();
|
||||
extern void ppc_orc();
|
||||
extern void ppc_orcdot();
|
||||
extern void ppc_slw();
|
||||
extern void ppc_slwdot();
|
||||
extern void ppc_srw();
|
||||
extern void ppc_srwdot();
|
||||
extern void ppc_sraw();
|
||||
extern void ppc_srawdot();
|
||||
extern void ppc_srawi();
|
||||
extern void ppc_srawidot();
|
||||
extern void ppc_stbx();
|
||||
extern void ppc_stbux();
|
||||
extern void ppc_stfiwx();
|
||||
|
@ -413,25 +387,10 @@ extern void ppc_stwcx();
|
|||
extern void ppc_stwux();
|
||||
extern void ppc_stwbrx();
|
||||
extern void ppc_subf();
|
||||
extern void ppc_subfdot();
|
||||
extern void ppc_subfo();
|
||||
extern void ppc_subfodot();
|
||||
extern void ppc_subfc();
|
||||
extern void ppc_subfcdot();
|
||||
extern void ppc_subfco();
|
||||
extern void ppc_subfcodot();
|
||||
extern void ppc_subfe();
|
||||
extern void ppc_subfedot();
|
||||
extern void ppc_subfeo();
|
||||
extern void ppc_subfeodot();
|
||||
extern void ppc_subfme();
|
||||
extern void ppc_subfmedot();
|
||||
extern void ppc_subfmeo();
|
||||
extern void ppc_subfmeodot();
|
||||
extern void ppc_subfze();
|
||||
extern void ppc_subfzedot();
|
||||
extern void ppc_subfzeo();
|
||||
extern void ppc_subfzeodot();
|
||||
extern void ppc_sync();
|
||||
extern void ppc_tlbia();
|
||||
extern void ppc_tlbie();
|
||||
|
@ -440,7 +399,6 @@ extern void ppc_tlbld();
|
|||
extern void ppc_tlbsync();
|
||||
extern void ppc_tw();
|
||||
extern void ppc_xor();
|
||||
extern void ppc_xordot();
|
||||
|
||||
extern void ppc_lswi();
|
||||
extern void ppc_lswx();
|
||||
|
@ -561,111 +519,39 @@ extern void ppc_frsp();
|
|||
extern void ppc_fctiw();
|
||||
extern void ppc_fctiwz();
|
||||
|
||||
extern void ppc_fadddot();
|
||||
extern void ppc_fsubdot();
|
||||
extern void ppc_fmultdot();
|
||||
extern void ppc_fdivdot();
|
||||
extern void ppc_fmadddot();
|
||||
extern void ppc_fmsubdot();
|
||||
extern void ppc_fnmadddot();
|
||||
extern void ppc_fnmsubdot();
|
||||
extern void ppc_fabsdot();
|
||||
extern void ppc_fnabsdot();
|
||||
extern void ppc_fnegdot();
|
||||
extern void ppc_fseldot();
|
||||
extern void ppc_fsqrtdot();
|
||||
extern void ppc_frsqrtedot();
|
||||
extern void ppc_frspdot();
|
||||
extern void ppc_fctiwdot();
|
||||
extern void ppc_fctiwzdot();
|
||||
|
||||
extern void ppc_fresdot();
|
||||
extern void ppc_faddsdot();
|
||||
extern void ppc_fsubsdot();
|
||||
extern void ppc_fmultsdot();
|
||||
extern void ppc_fdivsdot();
|
||||
extern void ppc_fmaddsdot();
|
||||
extern void ppc_fmsubsdot();
|
||||
extern void ppc_fnmaddsdot();
|
||||
extern void ppc_fnmsubsdot();
|
||||
extern void ppc_fsqrtsdot();
|
||||
|
||||
extern void ppc_fcmpo();
|
||||
extern void ppc_fcmpu();
|
||||
|
||||
// Power-specific instructions
|
||||
extern void power_abs();
|
||||
extern void power_absdot();
|
||||
extern void power_abso();
|
||||
extern void power_absodot();
|
||||
extern void power_clcs();
|
||||
extern void power_clcsdot();
|
||||
extern void power_div();
|
||||
extern void power_divdot();
|
||||
extern void power_divo();
|
||||
extern void power_divodot();
|
||||
extern void power_divs();
|
||||
extern void power_divsdot();
|
||||
extern void power_divso();
|
||||
extern void power_divsodot();
|
||||
extern void power_doz();
|
||||
extern void power_dozdot();
|
||||
extern void power_dozo();
|
||||
extern void power_dozodot();
|
||||
extern void power_dozi();
|
||||
extern void power_lscbx();
|
||||
extern void power_lscbxdot();
|
||||
extern void power_maskg();
|
||||
extern void power_maskgdot();
|
||||
extern void power_maskir();
|
||||
extern void power_maskirdot();
|
||||
extern void power_mul();
|
||||
extern void power_muldot();
|
||||
extern void power_mulo();
|
||||
extern void power_mulodot();
|
||||
extern void power_nabs();
|
||||
extern void power_nabsdot();
|
||||
extern void power_nabso();
|
||||
extern void power_nabsodot();
|
||||
extern void power_rlmi();
|
||||
extern void power_rrib();
|
||||
extern void power_rribdot();
|
||||
extern void power_sle();
|
||||
extern void power_sledot();
|
||||
extern void power_sleq();
|
||||
extern void power_sleqdot();
|
||||
extern void power_sliq();
|
||||
extern void power_sliqdot();
|
||||
extern void power_slliq();
|
||||
extern void power_slliqdot();
|
||||
extern void power_sllq();
|
||||
extern void power_sllqdot();
|
||||
extern void power_slq();
|
||||
extern void power_slqdot();
|
||||
extern void power_sraiq();
|
||||
extern void power_sraiqdot();
|
||||
extern void power_sraq();
|
||||
extern void power_sraqdot();
|
||||
extern void power_sre();
|
||||
extern void power_sredot();
|
||||
extern void power_srea();
|
||||
extern void power_sreadot();
|
||||
extern void power_sreq();
|
||||
extern void power_sreqdot();
|
||||
extern void power_sriq();
|
||||
extern void power_sriqdot();
|
||||
extern void power_srliq();
|
||||
extern void power_srliqdot();
|
||||
extern void power_srlq();
|
||||
extern void power_srlqdot();
|
||||
extern void power_srq();
|
||||
extern void power_srqdot();
|
||||
|
||||
// Gekko instructions
|
||||
extern void ppc_psq_l();
|
||||
extern void ppc_psq_lu();
|
||||
extern void ppc_psq_st();
|
||||
extern void ppc_psq_stu();
|
||||
} // namespace dppc_interpreter
|
||||
|
||||
// AltiVec instructions
|
||||
|
||||
|
@ -677,6 +563,7 @@ extern void ppc_main_opcode(void);
|
|||
extern void ppc_exec(void);
|
||||
extern void ppc_exec_single(void);
|
||||
extern void ppc_exec_until(uint32_t goal_addr);
|
||||
extern void ppc_exec_dbg(uint32_t start_addr, uint32_t size);
|
||||
|
||||
/* debugging support API */
|
||||
void print_gprs(void); /* print content of the general purpose registers */
|
||||
|
|
|
@ -35,6 +35,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#define NEW_TBR_UPDATE_ALGO
|
||||
|
||||
using namespace std;
|
||||
using namespace dppc_interpreter;
|
||||
|
||||
MemCtrlBase* mem_ctrl_instance = 0;
|
||||
|
||||
|
@ -42,6 +43,9 @@ bool power_on = 1;
|
|||
|
||||
SetPRS ppc_state;
|
||||
|
||||
bool rc_flag = 0; // Record flag
|
||||
bool oe_flag = 0; // Overflow flag
|
||||
|
||||
bool grab_exception;
|
||||
bool grab_return;
|
||||
bool grab_breakpoint;
|
||||
|
@ -69,344 +73,37 @@ uint8_t tbr_factor; /* cycles_count to TBR freq ratio in 2^x units */
|
|||
|
||||
/** Primary opcode (bits 0...5) lookup table. */
|
||||
static PPCOpcode OpcodeGrabber[] = {
|
||||
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_opcode4, ppc_illegalop,
|
||||
ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi, ppc_cmpli, ppc_cmpi,
|
||||
ppc_addic, ppc_addicdot, ppc_addi, ppc_addis, ppc_opcode16, ppc_sc,
|
||||
ppc_opcode18, ppc_opcode19, ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm,
|
||||
ppc_ori, ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot,
|
||||
ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz, ppc_lbzu,
|
||||
ppc_stw, ppc_stwu, ppc_stb, ppc_stbu, ppc_lhz, ppc_lhzu,
|
||||
ppc_lha, ppc_lhau, ppc_sth, ppc_sthu, ppc_lmw, ppc_stmw,
|
||||
ppc_lfs, ppc_lfsu, ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu,
|
||||
ppc_stfd, ppc_stfdu, ppc_psq_l, ppc_psq_lu, ppc_illegalop, ppc_illegalop,
|
||||
ppc_psq_st, ppc_psq_stu, ppc_illegalop, ppc_opcode63};
|
||||
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_twi, ppc_illegalop, ppc_illegalop,
|
||||
ppc_illegalop, ppc_mulli, ppc_subfic, power_dozi, ppc_cmpli, ppc_cmpi,
|
||||
ppc_addic, ppc_addicdot, ppc_addi, ppc_addis, ppc_opcode16, ppc_sc,
|
||||
ppc_opcode18, ppc_opcode19, ppc_rlwimi, ppc_rlwinm, power_rlmi, ppc_rlwnm,
|
||||
ppc_ori, ppc_oris, ppc_xori, ppc_xoris, ppc_andidot, ppc_andisdot,
|
||||
ppc_illegalop, ppc_opcode31, ppc_lwz, ppc_lwzu, ppc_lbz, ppc_lbzu,
|
||||
ppc_stw, ppc_stwu, ppc_stb, ppc_stbu, ppc_lhz, ppc_lhzu,
|
||||
ppc_lha, ppc_lhau, ppc_sth, ppc_sthu, ppc_lmw, ppc_stmw,
|
||||
ppc_lfs, ppc_lfsu, ppc_lfd, ppc_lfdu, ppc_stfs, ppc_stfsu,
|
||||
ppc_stfd, ppc_stfdu, ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_illegalop,
|
||||
ppc_illegalop, ppc_illegalop, ppc_illegalop, ppc_opcode63};
|
||||
|
||||
/** Lookup tables for branch instructions. */
|
||||
static PPCOpcode SubOpcode16Grabber[] = {ppc_bc, ppc_bcl, ppc_bca, ppc_bcla};
|
||||
static PPCOpcode SubOpcode16Grabber[] = {
|
||||
dppc_interpreter::ppc_bc,
|
||||
dppc_interpreter::ppc_bcl,
|
||||
dppc_interpreter::ppc_bca,
|
||||
dppc_interpreter::ppc_bcla};
|
||||
|
||||
static PPCOpcode SubOpcode18Grabber[] = {ppc_b, ppc_bl, ppc_ba, ppc_bla};
|
||||
static PPCOpcode SubOpcode18Grabber[] = {
|
||||
dppc_interpreter::ppc_b,
|
||||
dppc_interpreter::ppc_bl,
|
||||
dppc_interpreter::ppc_ba,
|
||||
dppc_interpreter::ppc_bla};
|
||||
|
||||
/** General conditional register instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode19Grabber = {
|
||||
{32, &ppc_bclr},
|
||||
{33, &ppc_bclrl},
|
||||
{66, &ppc_crnor},
|
||||
{100, &ppc_rfi},
|
||||
{258, &ppc_crandc},
|
||||
{300, &ppc_isync},
|
||||
{386, &ppc_crxor},
|
||||
{450, &ppc_crnand},
|
||||
{514, &ppc_crand},
|
||||
{578, &ppc_creqv},
|
||||
{834, &ppc_crorc},
|
||||
{898, &ppc_cror},
|
||||
{1056, &ppc_bcctr},
|
||||
{1057, &ppc_bcctrl}};
|
||||
/** Instructions decoding tables for integer,
|
||||
single floating-point, and double-floating point ops respectively */
|
||||
|
||||
/** General integer instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode31Grabber = {
|
||||
{0, &ppc_cmp}, {8, &ppc_tw},
|
||||
{16, &ppc_subfc}, {17, &ppc_subfcdot},
|
||||
{20, &ppc_addc}, {21, &ppc_addcdot},
|
||||
{22, &ppc_mulhwu}, {23, &ppc_mulhwudot},
|
||||
{38, &ppc_mfcr}, {40, &ppc_lwarx},
|
||||
{46, &ppc_lwzx}, {48, &ppc_slw},
|
||||
{49, &ppc_slwdot}, {52, &ppc_cntlzw},
|
||||
{53, &ppc_cntlzwdot}, {56, &ppc_and},
|
||||
{57, &ppc_anddot}, {58, &power_maskg},
|
||||
{59, &power_maskgdot}, {64, &ppc_cmpl},
|
||||
{80, &ppc_subf}, {81, &ppc_subfdot},
|
||||
{108, &ppc_dcbst}, {110, &ppc_lwzux},
|
||||
{120, &ppc_andc}, {121, &ppc_andcdot},
|
||||
{150, &ppc_mulhw}, {151, &ppc_mulhwdot},
|
||||
{166, &ppc_mfmsr}, {172, &ppc_dcbf},
|
||||
{174, &ppc_lbzx}, {208, &ppc_neg},
|
||||
{209, &ppc_negdot}, {214, &power_mul},
|
||||
{215, &power_muldot}, {238, &ppc_lbzux},
|
||||
{248, &ppc_nor}, {249, &ppc_nordot},
|
||||
{272, &ppc_subfe}, {273, &ppc_subfedot},
|
||||
{276, &ppc_adde}, {277, &ppc_addedot},
|
||||
{288, &ppc_mtcrf}, {292, &ppc_mtmsr},
|
||||
{301, &ppc_stwcx}, {302, &ppc_stwx},
|
||||
{304, &power_slq}, {305, &power_slqdot},
|
||||
{306, &power_sle}, {307, &power_sledot},
|
||||
{366, &ppc_stwux}, {368, &power_sliq},
|
||||
{400, &ppc_subfze}, {401, &ppc_subfzedot},
|
||||
{404, &ppc_addze}, {405, &ppc_addzedot},
|
||||
{420, &ppc_mtsr}, {430, &ppc_stbx},
|
||||
{432, &power_sllq}, {433, &power_sllqdot},
|
||||
{434, &power_sleq}, {436, &power_sleqdot},
|
||||
{464, &ppc_subfme}, {465, &ppc_subfmedot},
|
||||
{468, &ppc_addme}, {469, &ppc_addmedot},
|
||||
{470, &ppc_mullw}, {471, &ppc_mullwdot},
|
||||
{484, &ppc_mtsrin}, {492, &ppc_dcbtst},
|
||||
{494, &ppc_stbux}, {496, &power_slliq},
|
||||
{497, &power_slliqdot}, {528, &power_doz},
|
||||
{529, &power_dozdot}, {532, &ppc_add},
|
||||
{533, &ppc_adddot}, {554, &power_lscbx},
|
||||
{555, &power_lscbxdot}, {556, &ppc_dcbt},
|
||||
{558, &ppc_lhzx}, {568, &ppc_eqv},
|
||||
{569, &ppc_eqvdot}, {612, &ppc_tlbie},
|
||||
{622, &ppc_lhzux}, {632, &ppc_xor},
|
||||
{633, &ppc_xordot}, {662, &power_div},
|
||||
{663, &power_divdot}, {678, &ppc_mfspr},
|
||||
{686, &ppc_lhax}, {720, &power_abs},
|
||||
{721, &power_absdot}, {726, &power_divs},
|
||||
{727, &power_divsdot}, {740, &ppc_tlbia},
|
||||
{742, &ppc_mftb}, {750, &ppc_lhaux},
|
||||
{814, &ppc_sthx}, {824, &ppc_orc},
|
||||
{825, &ppc_orcdot}, {878, &ppc_sthx},
|
||||
{888, &ppc_or}, {889, &ppc_ordot},
|
||||
{918, &ppc_divwu}, {919, &ppc_divwudot},
|
||||
{934, &ppc_mtspr}, {940, &ppc_dcbi},
|
||||
{952, &ppc_nand}, {953, &ppc_nanddot},
|
||||
{976, &power_nabs}, {977, &power_nabsdot},
|
||||
{982, &ppc_divw}, {983, &ppc_divwdot},
|
||||
{1024, &ppc_mcrxr}, {1040, &ppc_subfco},
|
||||
{1041, &ppc_subfcodot}, {1044, &ppc_addco},
|
||||
{1045, &ppc_addcodot}, {1062, &power_clcs},
|
||||
{1063, &power_clcsdot}, {1066, &ppc_lswx},
|
||||
{1068, &ppc_lwbrx}, {1070, &ppc_lfsx},
|
||||
{1072, &ppc_srw}, {1073, &ppc_srwdot},
|
||||
{1074, &power_rrib}, {1075, &power_rribdot},
|
||||
{1082, &power_maskir}, {1083, &power_maskirdot},
|
||||
{1104, &ppc_subfo}, {1105, &ppc_subfodot},
|
||||
{1132, &ppc_tlbsync}, {1134, &ppc_lfsux},
|
||||
{1190, &ppc_mfsr}, {1194, &ppc_lswi},
|
||||
{1196, &ppc_sync}, {1198, &ppc_lfdx},
|
||||
{1232, &ppc_nego}, {1233, &ppc_negodot},
|
||||
{1238, &power_mulo}, {1239, &power_mulodot},
|
||||
{1262, &ppc_lfdux}, {1296, &ppc_subfeo},
|
||||
{1297, &ppc_subfeodot}, {1300, &ppc_addeo},
|
||||
{1301, &ppc_addeodot}, {1318, &ppc_mfsrin},
|
||||
{1322, &ppc_stswx}, {1324, &ppc_stwbrx},
|
||||
{1326, &ppc_stfsx}, {1328, &power_srq},
|
||||
{1329, &power_srqdot}, {1330, &power_sre},
|
||||
{1331, &power_sredot}, {1390, &ppc_stfsux},
|
||||
{1392, &power_sriq}, {1393, &power_sriqdot},
|
||||
{1424, &ppc_subfzeo}, {1425, &ppc_subfzeodot},
|
||||
{1428, &ppc_addzeo}, {1429, &ppc_addzeodot},
|
||||
{1450, &ppc_stswi}, {1454, &ppc_stfdx},
|
||||
{1456, &power_srlq}, {1457, &power_srlqdot},
|
||||
{1458, &power_sreq}, {1459, &power_sreqdot},
|
||||
{1488, &ppc_subfmeo}, {1489, &ppc_subfmeodot},
|
||||
{1492, &ppc_addmeo}, {1493, &ppc_addmeodot},
|
||||
{1494, &ppc_mullwo}, {1495, &ppc_mullwodot},
|
||||
{1518, &ppc_stfdux}, {1520, &power_srliq},
|
||||
{1521, &power_srliqdot}, {1552, &power_dozo},
|
||||
{1553, &power_dozodot}, {1556, &ppc_addo},
|
||||
{1557, &ppc_addodot}, {1580, &ppc_lhbrx},
|
||||
{1584, &ppc_sraw}, {1585, &ppc_srawdot},
|
||||
{1648, &ppc_srawi}, {1649, &ppc_srawidot},
|
||||
{1686, &power_divo}, {1687, &power_divodot},
|
||||
{1708, &ppc_eieio}, {1744, &power_abso},
|
||||
{1745, &power_absodot}, {1750, &power_divso},
|
||||
{1751, &power_divsodot}, {1836, &ppc_sthbrx},
|
||||
{1840, &power_sraq}, {1841, &power_sraqdot},
|
||||
{1842, &power_srea}, {1843, &power_sreadot},
|
||||
{1844, &ppc_extsh}, {1845, &ppc_extshdot},
|
||||
{1904, &power_sraiq}, {1905, &power_sraiqdot},
|
||||
{1908, &ppc_extsb}, {1909, &ppc_extsbdot},
|
||||
{1942, &ppc_divwuo}, {1943, &ppc_divwuodot},
|
||||
{1956, &ppc_tlbld}, {1964, &ppc_icbi},
|
||||
{1966, &ppc_stfiwx}, {2000, &power_nabso},
|
||||
{2001, &power_nabsodot}, {2006, &ppc_divwo},
|
||||
{2007, &ppc_divwodot}, {2020, &ppc_tlbli},
|
||||
{2028, &ppc_dcbz}};
|
||||
|
||||
/** Single-precision floating-point instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode59Grabber = {
|
||||
{36, &ppc_fdivs}, {37, &ppc_fdivsdot}, {40, &ppc_fsubs}, {41, &ppc_fsubsdot},
|
||||
{42, &ppc_fadds}, {43, &ppc_faddsdot}, {44, &ppc_fsqrts}, {45, &ppc_fsqrtsdot},
|
||||
{48, &ppc_fres}, {49, &ppc_fresdot}, {50, &ppc_fmults}, {51, &ppc_fmultsdot},
|
||||
{56, &ppc_fmsubs}, {57, &ppc_fmsubsdot}, {58, &ppc_fmadds}, {59, &ppc_fmaddsdot},
|
||||
{60, &ppc_fnmsubs}, {61, &ppc_fnmsubsdot}, {62, &ppc_fnmadds}, {63, &ppc_fnmaddsdot},
|
||||
{114, &ppc_fmults}, {115, &ppc_fmultsdot}, {120, &ppc_fmsubs}, {121, &ppc_fmsubsdot},
|
||||
{122, &ppc_fmadds}, {123, &ppc_fmadds}, {124, &ppc_fnmsubs}, {125, &ppc_fnmsubsdot},
|
||||
{126, &ppc_fnmadds}, {127, &ppc_fnmaddsdot}, {178, &ppc_fmults}, {179, &ppc_fmultsdot},
|
||||
{184, &ppc_fmsubs}, {185, &ppc_fmsubsdot}, {186, &ppc_fmadds}, {187, &ppc_fmaddsdot},
|
||||
{188, &ppc_fnmsubs}, {189, &ppc_fnmsubsdot}, {190, &ppc_fnmadds}, {191, &ppc_fnmaddsdot},
|
||||
{242, &ppc_fmults}, {243, &ppc_fmultsdot}, {248, &ppc_fmsubs}, {249, &ppc_fmsubsdot},
|
||||
{250, &ppc_fmadds}, {251, &ppc_fmaddsdot}, {252, &ppc_fnmsubs}, {253, &ppc_fnmsubsdot},
|
||||
{254, &ppc_fnmadds}, {255, &ppc_fnmaddsdot}, {306, &ppc_fmults}, {307, &ppc_fmultsdot},
|
||||
{312, &ppc_fmsubs}, {313, &ppc_fmsubsdot}, {314, &ppc_fmadds}, {315, &ppc_fmaddsdot},
|
||||
{316, &ppc_fnmsubs}, {317, &ppc_fnmsubsdot}, {318, &ppc_fnmadds}, {319, &ppc_fnmaddsdot},
|
||||
{370, &ppc_fmults}, {371, &ppc_fmultsdot}, {376, &ppc_fmsubs}, {377, &ppc_fmsubsdot},
|
||||
{378, &ppc_fmadds}, {379, &ppc_fmaddsdot}, {380, &ppc_fnmsubs}, {381, &ppc_fnmsubsdot},
|
||||
{382, &ppc_fnmadds}, {383, &ppc_fnmaddsdot}, {434, &ppc_fmults}, {435, &ppc_fmultsdot},
|
||||
{440, &ppc_fmsubs}, {441, &ppc_fmsubsdot}, {442, &ppc_fmadds}, {443, &ppc_fmaddsdot},
|
||||
{444, &ppc_fnmsubs}, {445, &ppc_fnmsubsdot}, {446, &ppc_fnmadds}, {447, &ppc_fnmaddsdot},
|
||||
{498, &ppc_fmults}, {499, &ppc_fmultsdot}, {504, &ppc_fmsubs}, {505, &ppc_fmsubsdot},
|
||||
{506, &ppc_fmadds}, {507, &ppc_fmaddsdot}, {508, &ppc_fnmsubs}, {509, &ppc_fnmsubsdot},
|
||||
{510, &ppc_fnmadds}, {511, &ppc_fnmaddsdot}, {562, &ppc_fmults}, {563, &ppc_fmultsdot},
|
||||
{568, &ppc_fmsubs}, {569, &ppc_fmsubsdot}, {570, &ppc_fmadds}, {571, &ppc_fmaddsdot},
|
||||
{572, &ppc_fnmsubs}, {573, &ppc_fnmsubsdot}, {574, &ppc_fnmadds}, {575, &ppc_fnmaddsdot},
|
||||
{626, &ppc_fmults}, {627, &ppc_fmultsdot}, {632, &ppc_fmsubs}, {633, &ppc_fmsubsdot},
|
||||
{634, &ppc_fmadds}, {635, &ppc_fmaddsdot}, {636, &ppc_fnmsubs}, {637, &ppc_fnmsubsdot},
|
||||
{638, &ppc_fnmadds}, {639, &ppc_fnmaddsdot}, {690, &ppc_fmults}, {691, &ppc_fmultsdot},
|
||||
{696, &ppc_fmsubs}, {697, &ppc_fmsubsdot}, {698, &ppc_fmadds}, {699, &ppc_fmaddsdot},
|
||||
{700, &ppc_fnmsubs}, {701, &ppc_fnmsubsdot}, {702, &ppc_fnmadds}, {703, &ppc_fnmaddsdot},
|
||||
{754, &ppc_fmults}, {755, &ppc_fmultsdot}, {760, &ppc_fmsubs}, {761, &ppc_fmsubsdot},
|
||||
{762, &ppc_fmadds}, {763, &ppc_fmaddsdot}, {764, &ppc_fnmsubs}, {765, &ppc_fnmsubsdot},
|
||||
{766, &ppc_fnmadds}, {767, &ppc_fnmaddsdot}, {818, &ppc_fmults}, {819, &ppc_fmultsdot},
|
||||
{824, &ppc_fmsubs}, {825, &ppc_fmsubsdot}, {826, &ppc_fmadds}, {827, &ppc_fmaddsdot},
|
||||
{828, &ppc_fnmsubs}, {829, &ppc_fnmsubsdot}, {830, &ppc_fnmadds}, {831, &ppc_fnmaddsdot},
|
||||
{882, &ppc_fmults}, {883, &ppc_fmultsdot}, {888, &ppc_fmsubs}, {889, &ppc_fmsubsdot},
|
||||
{890, &ppc_fmadds}, {891, &ppc_fmaddsdot}, {892, &ppc_fnmsubs}, {893, &ppc_fnmsubsdot},
|
||||
{894, &ppc_fnmadds}, {895, &ppc_fnmaddsdot}, {946, &ppc_fmults}, {947, &ppc_fmultsdot},
|
||||
{952, &ppc_fmsubs}, {953, &ppc_fmsubsdot}, {954, &ppc_fmadds}, {955, &ppc_fmaddsdot},
|
||||
{957, &ppc_fnmsubs}, {958, &ppc_fnmsubsdot}, {958, &ppc_fnmadds}, {959, &ppc_fnmaddsdot},
|
||||
{1010, &ppc_fmults}, {1011, &ppc_fmultsdot}, {1016, &ppc_fmsubs}, {1017, &ppc_fmsubsdot},
|
||||
{1018, &ppc_fmadds}, {1019, &ppc_fmaddsdot}, {1020, &ppc_fnmsubs}, {1021, &ppc_fnmsubsdot},
|
||||
{1022, &ppc_fnmadds}, {1023, &ppc_fnmaddsdot}, {1074, &ppc_fmults}, {1075, &ppc_fmultsdot},
|
||||
{1080, &ppc_fmsubs}, {1081, &ppc_fmsubsdot}, {1082, &ppc_fmadds}, {1083, &ppc_fmaddsdot},
|
||||
{1084, &ppc_fnmsubs}, {1085, &ppc_fnmsubsdot}, {1086, &ppc_fnmadds}, {1087, &ppc_fnmaddsdot},
|
||||
{1138, &ppc_fmults}, {1139, &ppc_fmultsdot}, {1144, &ppc_fmsubs}, {1145, &ppc_fmsubsdot},
|
||||
{1146, &ppc_fmadds}, {1147, &ppc_fmaddsdot}, {1148, &ppc_fnmsubs}, {1149, &ppc_fnmsubsdot},
|
||||
{1150, &ppc_fnmadds}, {1151, &ppc_fnmaddsdot}, {1202, &ppc_fmults}, {1203, &ppc_fmultsdot},
|
||||
{1208, &ppc_fmsubs}, {1209, &ppc_fmsubsdot}, {1210, &ppc_fmadds}, {1211, &ppc_fmaddsdot},
|
||||
{1212, &ppc_fnmsubs}, {1213, &ppc_fnmsubsdot}, {1214, &ppc_fnmadds}, {1215, &ppc_fnmaddsdot},
|
||||
{1266, &ppc_fmults}, {1267, &ppc_fmultsdot}, {1272, &ppc_fmsubs}, {1273, &ppc_fmsubsdot},
|
||||
{1274, &ppc_fmadds}, {1275, &ppc_fmaddsdot}, {1276, &ppc_fnmsubs}, {1277, &ppc_fnmsubsdot},
|
||||
{1278, &ppc_fnmadds}, {1279, &ppc_fnmaddsdot}, {1330, &ppc_fmults}, {1331, &ppc_fmultsdot},
|
||||
{1336, &ppc_fmsubs}, {1337, &ppc_fmsubsdot}, {1338, &ppc_fmadds}, {1339, &ppc_fmaddsdot},
|
||||
{1340, &ppc_fnmsubs}, {1341, &ppc_fnmsubsdot}, {1342, &ppc_fnmadds}, {1343, &ppc_fnmaddsdot},
|
||||
{1394, &ppc_fmults}, {1395, &ppc_fmultsdot}, {1400, &ppc_fmsubs}, {1401, &ppc_fmsubsdot},
|
||||
{1402, &ppc_fmadds}, {1403, &ppc_fmaddsdot}, {1404, &ppc_fnmsubs}, {1405, &ppc_fnmsubsdot},
|
||||
{1406, &ppc_fnmadds}, {1407, &ppc_fnmaddsdot}, {1458, &ppc_fmults}, {1459, &ppc_fmultsdot},
|
||||
{1464, &ppc_fmsubs}, {1465, &ppc_fmsubsdot}, {1466, &ppc_fmadds}, {1467, &ppc_fmaddsdot},
|
||||
{1468, &ppc_fnmsubs}, {1469, &ppc_fnmsubsdot}, {1470, &ppc_fnmadds}, {1471, &ppc_fnmaddsdot},
|
||||
{1522, &ppc_fmults}, {1523, &ppc_fmultsdot}, {1528, &ppc_fmsubs}, {1529, &ppc_fmsubsdot},
|
||||
{1530, &ppc_fmadds}, {1531, &ppc_fmaddsdot}, {1532, &ppc_fnmsubs}, {1533, &ppc_fnmsubsdot},
|
||||
{1534, &ppc_fnmadds}, {1535, &ppc_fnmaddsdot}, {1586, &ppc_fmults}, {1587, &ppc_fmultsdot},
|
||||
{1592, &ppc_fmsubs}, {1593, &ppc_fmsubsdot}, {1594, &ppc_fmadds}, {1595, &ppc_fmaddsdot},
|
||||
{1596, &ppc_fnmsubs}, {1597, &ppc_fnmsubsdot}, {1598, &ppc_fnmadds}, {1599, &ppc_fnmaddsdot},
|
||||
{1650, &ppc_fmults}, {1651, &ppc_fmultsdot}, {1656, &ppc_fmsubs}, {1657, &ppc_fmsubsdot},
|
||||
{1658, &ppc_fmadds}, {1659, &ppc_fmaddsdot}, {1660, &ppc_fnmsubs}, {1661, &ppc_fnmsubsdot},
|
||||
{1662, &ppc_fnmadds}, {1663, &ppc_fnmaddsdot}, {1714, &ppc_fmults}, {1715, &ppc_fmultsdot},
|
||||
{1720, &ppc_fmsubs}, {1721, &ppc_fmsubsdot}, {1722, &ppc_fmadds}, {1723, &ppc_fmaddsdot},
|
||||
{1724, &ppc_fnmsubs}, {1725, &ppc_fnmsubsdot}, {1726, &ppc_fnmadds}, {1727, &ppc_fnmaddsdot},
|
||||
{1778, &ppc_fmults}, {1779, &ppc_fmultsdot}, {1784, &ppc_fmsubs}, {1785, &ppc_fmsubsdot},
|
||||
{1786, &ppc_fmadds}, {1787, &ppc_fmaddsdot}, {1788, &ppc_fnmsubs}, {1789, &ppc_fnmsubsdot},
|
||||
{1790, &ppc_fnmadds}, {1791, &ppc_fnmaddsdot}, {1842, &ppc_fmults}, {1843, &ppc_fmultsdot},
|
||||
{1848, &ppc_fmsubs}, {1849, &ppc_fmsubsdot}, {1850, &ppc_fmadds}, {1851, &ppc_fmaddsdot},
|
||||
{1852, &ppc_fnmsubs}, {1853, &ppc_fnmsubsdot}, {1854, &ppc_fnmadds}, {1855, &ppc_fnmaddsdot},
|
||||
{1906, &ppc_fmults}, {1907, &ppc_fmultsdot}, {1912, &ppc_fmsubs}, {1913, &ppc_fmsubsdot},
|
||||
{1914, &ppc_fmadds}, {1915, &ppc_fmaddsdot}, {1916, &ppc_fnmsubs}, {1917, &ppc_fnmsubsdot},
|
||||
{1918, &ppc_fnmadds}, {1919, &ppc_fnmaddsdot}, {1970, &ppc_fmults}, {1971, &ppc_fmultsdot},
|
||||
{1976, &ppc_fmsubs}, {1977, &ppc_fmsubsdot}, {1978, &ppc_fmadds}, {1979, &ppc_fmaddsdot},
|
||||
{1980, &ppc_fnmsubs}, {1981, &ppc_fnmsubsdot}, {1982, &ppc_fnmadds}, {1983, &ppc_fnmaddsdot},
|
||||
{2034, &ppc_fmults}, {2035, &ppc_fmultsdot}, {2040, &ppc_fmsubs}, {2041, &ppc_fmsubsdot},
|
||||
{2042, &ppc_fmadds}, {2043, &ppc_fmaddsdot}, {2044, &ppc_fnmsubs}, {2045, &ppc_fnmsubsdot},
|
||||
{2046, &ppc_fnmadds}, {2047, &ppc_fnmaddsdot}};
|
||||
|
||||
/** Double-precision floating-point instructions decoding table. */
|
||||
static std::unordered_map<uint16_t, PPCOpcode> SubOpcode63Grabber = {
|
||||
{0, &ppc_fcmpu}, {24, &ppc_frsp}, {25, &ppc_frspdot}, {28, &ppc_fctiw},
|
||||
{29, &ppc_fctiwdot}, {30, &ppc_fctiwz}, {31, &ppc_fctiwzdot}, {36, &ppc_fdiv},
|
||||
{37, &ppc_fdivdot}, {40, &ppc_fsub}, {41, &ppc_fsubdot}, {42, &ppc_fadd},
|
||||
{43, &ppc_fadddot}, {44, &ppc_fsqrt}, {45, &ppc_fsqrtdot}, {46, &ppc_fsel},
|
||||
{47, &ppc_fseldot}, {50, &ppc_fmult}, {51, &ppc_fmultdot}, {52, &ppc_frsqrte},
|
||||
{53, &ppc_frsqrtedot}, {56, &ppc_fmsub}, {57, &ppc_fmsubdot}, {58, &ppc_fmadd},
|
||||
{59, &ppc_fmadddot}, {60, &ppc_fnmsub}, {61, &ppc_fnmsubdot}, {62, &ppc_fnmadd},
|
||||
{63, &ppc_fnmadddot}, {64, &ppc_fcmpo}, {76, &ppc_mtfsb1}, {77, &ppc_mtfsb1dot},
|
||||
{80, &ppc_fneg}, {81, &ppc_fnegdot}, {110, &ppc_fsel}, {111, &ppc_fseldot},
|
||||
{114, &ppc_fmult}, {115, &ppc_fmultdot}, {120, &ppc_fmsub}, {121, &ppc_fmsubdot},
|
||||
{122, &ppc_fmadd}, {123, &ppc_fmadd}, {124, &ppc_fnmsub}, {125, &ppc_fnmsubdot},
|
||||
{126, &ppc_fnmadd}, {127, &ppc_fnmadddot}, {128, &ppc_mcrfs}, {140, &ppc_mtfsb0},
|
||||
{141, &ppc_mtfsb0dot}, {144, &ppc_fmr}, {174, &ppc_fsel}, {175, &ppc_fseldot},
|
||||
{178, &ppc_fmult}, {179, &ppc_fmultdot}, {184, &ppc_fmsub}, {185, &ppc_fmsubdot},
|
||||
{186, &ppc_fmadd}, {187, &ppc_fmadddot}, {188, &ppc_fnmsub}, {189, &ppc_fnmsubdot},
|
||||
{190, &ppc_fnmadd}, {191, &ppc_fnmadddot}, {238, &ppc_fsel}, {239, &ppc_fseldot},
|
||||
{242, &ppc_fmult}, {243, &ppc_fmultdot}, {248, &ppc_fmsub}, {249, &ppc_fmsubdot},
|
||||
{250, &ppc_fmadd}, {251, &ppc_fmadddot}, {252, &ppc_fnmsub}, {253, &ppc_fnmsubdot},
|
||||
{254, &ppc_fnmadd}, {255, &ppc_fnmadddot}, {268, &ppc_mtfsfi}, {272, &ppc_fnabs},
|
||||
{273, &ppc_fnabsdot}, {302, &ppc_fsel}, {303, &ppc_fseldot}, {306, &ppc_fmult},
|
||||
{307, &ppc_fmultdot}, {312, &ppc_fmsub}, {313, &ppc_fmsubdot}, {314, &ppc_fmadd},
|
||||
{315, &ppc_fmadddot}, {316, &ppc_fnmsub}, {317, &ppc_fnmsubdot}, {318, &ppc_fnmadd},
|
||||
{319, &ppc_fnmadddot}, {366, &ppc_fsel}, {367, &ppc_fseldot}, {370, &ppc_fmult},
|
||||
{371, &ppc_fmultdot}, {376, &ppc_fmsub}, {377, &ppc_fmsubdot}, {378, &ppc_fmadd},
|
||||
{379, &ppc_fmadddot}, {380, &ppc_fnmsub}, {381, &ppc_fnmsubdot}, {382, &ppc_fnmadd},
|
||||
{383, &ppc_fnmadddot}, {430, &ppc_fsel}, {431, &ppc_fseldot}, {434, &ppc_fmult},
|
||||
{435, &ppc_fmultdot}, {440, &ppc_fmsub}, {441, &ppc_fmsubdot}, {442, &ppc_fmadd},
|
||||
{443, &ppc_fmadddot}, {444, &ppc_fnmsub}, {445, &ppc_fnmsubdot}, {446, &ppc_fnmadd},
|
||||
{447, &ppc_fnmadddot}, {494, &ppc_fsel}, {495, &ppc_fseldot}, {498, &ppc_fmult},
|
||||
{499, &ppc_fmultdot}, {504, &ppc_fmsub}, {505, &ppc_fmsubdot}, {506, &ppc_fmadd},
|
||||
{507, &ppc_fmadddot}, {508, &ppc_fnmsub}, {509, &ppc_fnmsubdot}, {510, &ppc_fnmadd},
|
||||
{511, &ppc_fnmadddot}, {528, &ppc_fabs}, {529, &ppc_fabsdot}, {536, &ppc_mtfsfidot},
|
||||
{558, &ppc_fsel}, {559, &ppc_fseldot}, {562, &ppc_fmult}, {563, &ppc_fmultdot},
|
||||
{568, &ppc_fmsub}, {569, &ppc_fmsubdot}, {570, &ppc_fmadd}, {571, &ppc_fmadddot},
|
||||
{572, &ppc_fnmsub}, {573, &ppc_fnmsubdot}, {574, &ppc_fnmadd}, {575, &ppc_fnmadddot},
|
||||
{622, &ppc_fsel}, {623, &ppc_fseldot}, {626, &ppc_fmult}, {627, &ppc_fmultdot},
|
||||
{632, &ppc_fmsub}, {633, &ppc_fmsubdot}, {634, &ppc_fmadd}, {635, &ppc_fmadddot},
|
||||
{636, &ppc_fnmsub}, {637, &ppc_fnmsubdot}, {638, &ppc_fnmadd}, {639, &ppc_fnmadddot},
|
||||
{686, &ppc_fsel}, {687, &ppc_fseldot}, {690, &ppc_fmult}, {691, &ppc_fmultdot},
|
||||
{696, &ppc_fmsub}, {697, &ppc_fmsubdot}, {698, &ppc_fmadd}, {699, &ppc_fmadddot},
|
||||
{700, &ppc_fnmsub}, {701, &ppc_fnmsubdot}, {702, &ppc_fnmadd}, {703, &ppc_fnmadddot},
|
||||
{750, &ppc_fsel}, {751, &ppc_fseldot}, {754, &ppc_fmult}, {755, &ppc_fmultdot},
|
||||
{760, &ppc_fmsub}, {761, &ppc_fmsubdot}, {762, &ppc_fmadd}, {763, &ppc_fmadddot},
|
||||
{764, &ppc_fnmsub}, {765, &ppc_fnmsubdot}, {766, &ppc_fnmadd}, {767, &ppc_fnmadddot},
|
||||
{814, &ppc_fsel}, {815, &ppc_fseldot}, {818, &ppc_fmult}, {819, &ppc_fmultdot},
|
||||
{824, &ppc_fmsub}, {825, &ppc_fmsubdot}, {826, &ppc_fmadd}, {827, &ppc_fmadddot},
|
||||
{828, &ppc_fnmsub}, {829, &ppc_fnmsubdot}, {830, &ppc_fnmadd}, {831, &ppc_fnmadddot},
|
||||
{878, &ppc_fsel}, {879, &ppc_fseldot}, {882, &ppc_fmult}, {883, &ppc_fmultdot},
|
||||
{888, &ppc_fmsub}, {889, &ppc_fmsubdot}, {890, &ppc_fmadd}, {891, &ppc_fmadddot},
|
||||
{892, &ppc_fnmsub}, {893, &ppc_fnmsubdot}, {894, &ppc_fnmadd}, {895, &ppc_fnmadddot},
|
||||
{942, &ppc_fsel}, {943, &ppc_fseldot}, {946, &ppc_fmult}, {947, &ppc_fmultdot},
|
||||
{952, &ppc_fmsub}, {953, &ppc_fmsubdot}, {954, &ppc_fmadd}, {955, &ppc_fmadddot},
|
||||
{957, &ppc_fnmsub}, {958, &ppc_fnmsubdot}, {958, &ppc_fnmadd}, {959, &ppc_fnmadddot},
|
||||
{1006, &ppc_fsel}, {1007, &ppc_fseldot}, {1010, &ppc_fmult}, {1011, &ppc_fmultdot},
|
||||
{1016, &ppc_fmsub}, {1017, &ppc_fmsubdot}, {1018, &ppc_fmadd}, {1019, &ppc_fmadddot},
|
||||
{1020, &ppc_fnmsub}, {1021, &ppc_fnmsubdot}, {1022, &ppc_fnmadd}, {1023, &ppc_fnmadddot},
|
||||
{1070, &ppc_fsel}, {1071, &ppc_fseldot}, {1074, &ppc_fmult}, {1075, &ppc_fmultdot},
|
||||
{1080, &ppc_fmsub}, {1081, &ppc_fmsubdot}, {1082, &ppc_fmadd}, {1083, &ppc_fmadddot},
|
||||
{1084, &ppc_fnmsub}, {1085, &ppc_fnmsubdot}, {1086, &ppc_fnmadd}, {1087, &ppc_fnmadddot},
|
||||
{1134, &ppc_fsel}, {1135, &ppc_fseldot}, {1138, &ppc_fmult}, {1139, &ppc_fmultdot},
|
||||
{1144, &ppc_fmsub}, {1145, &ppc_fmsubdot}, {1146, &ppc_fmadd}, {1147, &ppc_fmadddot},
|
||||
{1148, &ppc_fnmsub}, {1149, &ppc_fnmsubdot}, {1150, &ppc_fnmadd}, {1151, &ppc_fnmadddot},
|
||||
{1166, &ppc_mffs}, {1167, &ppc_mffsdot}, {1198, &ppc_fsel}, {1199, &ppc_fseldot},
|
||||
{1202, &ppc_fmult}, {1203, &ppc_fmultdot}, {1208, &ppc_fmsub}, {1209, &ppc_fmsubdot},
|
||||
{1210, &ppc_fmadd}, {1211, &ppc_fmadddot}, {1212, &ppc_fnmsub}, {1213, &ppc_fnmsubdot},
|
||||
{1214, &ppc_fnmadd}, {1215, &ppc_fnmadddot}, {1262, &ppc_fsel}, {1263, &ppc_fseldot},
|
||||
{1266, &ppc_fmult}, {1267, &ppc_fmultdot}, {1272, &ppc_fmsub}, {1273, &ppc_fmsubdot},
|
||||
{1274, &ppc_fmadd}, {1275, &ppc_fmadddot}, {1276, &ppc_fnmsub}, {1277, &ppc_fnmsubdot},
|
||||
{1278, &ppc_fnmadd}, {1279, &ppc_fnmadddot}, {1326, &ppc_fsel}, {1327, &ppc_fseldot},
|
||||
{1330, &ppc_fmult}, {1331, &ppc_fmultdot}, {1336, &ppc_fmsub}, {1337, &ppc_fmsubdot},
|
||||
{1338, &ppc_fmadd}, {1339, &ppc_fmadddot}, {1340, &ppc_fnmsub}, {1341, &ppc_fnmsubdot},
|
||||
{1342, &ppc_fnmadd}, {1343, &ppc_fnmadddot}, {1390, &ppc_fsel}, {1391, &ppc_fseldot},
|
||||
{1394, &ppc_fmult}, {1395, &ppc_fmultdot}, {1400, &ppc_fmsub}, {1401, &ppc_fmsubdot},
|
||||
{1402, &ppc_fmadd}, {1403, &ppc_fmadddot}, {1404, &ppc_fnmsub}, {1405, &ppc_fnmsubdot},
|
||||
{1406, &ppc_fnmadd}, {1407, &ppc_fnmadddot}, {1422, &ppc_mtfsf}, {1423, &ppc_mtfsfdot},
|
||||
{1454, &ppc_fsel}, {1455, &ppc_fseldot}, {1458, &ppc_fmult}, {1459, &ppc_fmultdot},
|
||||
{1464, &ppc_fmsub}, {1465, &ppc_fmsubdot}, {1466, &ppc_fmadd}, {1467, &ppc_fmadddot},
|
||||
{1468, &ppc_fnmsub}, {1469, &ppc_fnmsubdot}, {1470, &ppc_fnmadd}, {1471, &ppc_fnmadddot},
|
||||
{1518, &ppc_fsel}, {1519, &ppc_fseldot}, {1522, &ppc_fmult}, {1523, &ppc_fmultdot},
|
||||
{1528, &ppc_fmsub}, {1529, &ppc_fmsubdot}, {1530, &ppc_fmadd}, {1531, &ppc_fmadddot},
|
||||
{1532, &ppc_fnmsub}, {1533, &ppc_fnmsubdot}, {1534, &ppc_fnmadd}, {1535, &ppc_fnmadddot},
|
||||
{1582, &ppc_fsel}, {1583, &ppc_fseldot}, {1586, &ppc_fmult}, {1587, &ppc_fmultdot},
|
||||
{1592, &ppc_fmsub}, {1593, &ppc_fmsubdot}, {1594, &ppc_fmadd}, {1595, &ppc_fmadddot},
|
||||
{1596, &ppc_fnmsub}, {1597, &ppc_fnmsubdot}, {1598, &ppc_fnmadd}, {1599, &ppc_fnmadddot},
|
||||
{1646, &ppc_fsel}, {1647, &ppc_fseldot}, {1650, &ppc_fmult}, {1651, &ppc_fmultdot},
|
||||
{1656, &ppc_fmsub}, {1657, &ppc_fmsubdot}, {1658, &ppc_fmadd}, {1659, &ppc_fmadddot},
|
||||
{1660, &ppc_fnmsub}, {1661, &ppc_fnmsubdot}, {1662, &ppc_fnmadd}, {1663, &ppc_fnmadddot},
|
||||
{1710, &ppc_fsel}, {1711, &ppc_fseldot}, {1714, &ppc_fmult}, {1715, &ppc_fmultdot},
|
||||
{1720, &ppc_fmsub}, {1721, &ppc_fmsubdot}, {1722, &ppc_fmadd}, {1723, &ppc_fmadddot},
|
||||
{1724, &ppc_fnmsub}, {1725, &ppc_fnmsubdot}, {1726, &ppc_fnmadd}, {1727, &ppc_fnmadddot},
|
||||
{1774, &ppc_fsel}, {1775, &ppc_fseldot}, {1778, &ppc_fmult}, {1779, &ppc_fmultdot},
|
||||
{1784, &ppc_fmsub}, {1785, &ppc_fmsubdot}, {1786, &ppc_fmadd}, {1787, &ppc_fmadddot},
|
||||
{1788, &ppc_fnmsub}, {1789, &ppc_fnmsubdot}, {1790, &ppc_fnmadd}, {1791, &ppc_fnmadddot},
|
||||
{1838, &ppc_fsel}, {1839, &ppc_fseldot}, {1842, &ppc_fmult}, {1843, &ppc_fmultdot},
|
||||
{1848, &ppc_fmsub}, {1849, &ppc_fmsubdot}, {1850, &ppc_fmadd}, {1851, &ppc_fmadddot},
|
||||
{1852, &ppc_fnmsub}, {1853, &ppc_fnmsubdot}, {1854, &ppc_fnmadd}, {1855, &ppc_fnmadddot},
|
||||
{1902, &ppc_fsel}, {1903, &ppc_fseldot}, {1906, &ppc_fmult}, {1907, &ppc_fmultdot},
|
||||
{1912, &ppc_fmsub}, {1913, &ppc_fmsubdot}, {1914, &ppc_fmadd}, {1915, &ppc_fmadddot},
|
||||
{1916, &ppc_fnmsub}, {1917, &ppc_fnmsubdot}, {1918, &ppc_fnmadd}, {1919, &ppc_fnmadddot},
|
||||
{1966, &ppc_fsel}, {1967, &ppc_fseldot}, {1970, &ppc_fmult}, {1971, &ppc_fmultdot},
|
||||
{1976, &ppc_fmsub}, {1977, &ppc_fmsubdot}, {1978, &ppc_fmadd}, {1979, &ppc_fmadddot},
|
||||
{1980, &ppc_fnmsub}, {1981, &ppc_fnmsubdot}, {1982, &ppc_fnmadd}, {1983, &ppc_fnmadddot},
|
||||
{2030, &ppc_fsel}, {2031, &ppc_fseldot}, {2034, &ppc_fmult}, {2035, &ppc_fmultdot},
|
||||
{2040, &ppc_fmsub}, {2041, &ppc_fmsubdot}, {2042, &ppc_fmadd}, {2043, &ppc_fmadddot},
|
||||
{2044, &ppc_fnmsub}, {2045, &ppc_fnmsubdot}, {2046, &ppc_fnmadd}, {2047, &ppc_fnmadddot}};
|
||||
PPCOpcode SubOpcode31Grabber[1024] = { ppc_illegalop };
|
||||
PPCOpcode SubOpcode59Grabber[1024] = { ppc_fpu_off };
|
||||
PPCOpcode SubOpcode63Grabber[1024] = { ppc_fpu_off };
|
||||
|
||||
|
||||
#define UPDATE_TBR_DEC \
|
||||
|
@ -420,22 +117,18 @@ static std::unordered_map<uint16_t, PPCOpcode> SubOpcode63Grabber = {
|
|||
old_cycles_count += delta << tbr_factor; \
|
||||
}
|
||||
|
||||
/** Exception helpers. */
|
||||
|
||||
[[noreturn]] void ppc_illegalop() {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
|
||||
[[noreturn]] void ppc_fpu_off() {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::FPU_OFF);
|
||||
}
|
||||
|
||||
/** Opcode decoding functions. */
|
||||
|
||||
void ppc_illegalop() {
|
||||
LOG_F(ERROR, "Illegal opcode reported: 0x%X Report this! \n", ppc_cur_instruction);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void ppc_opcode4() {
|
||||
LOG_F(INFO, "Reading from Opcode 4 table \n");
|
||||
uint8_t subop_grab = ppc_cur_instruction & 3;
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(ERROR, "Executing subopcode entry %d \n"
|
||||
".. or would if I bothered to implement it. SORRY!", regrab);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void ppc_opcode16() {
|
||||
SubOpcode16Grabber[ppc_cur_instruction & 3]();
|
||||
}
|
||||
|
@ -445,67 +138,92 @@ void ppc_opcode18() {
|
|||
}
|
||||
|
||||
void ppc_opcode19() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
||||
uint16_t subop_grab = ppc_cur_instruction & 0x7FF;
|
||||
|
||||
#ifdef EXHAUSTIVE_DEBUG
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(INFO, "Executing Opcode 19 table subopcode entry \n", regrab);
|
||||
if (SubOpcode19Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode19Grabber[subop_grab]();
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
#else
|
||||
SubOpcode19Grabber[subop_grab]();
|
||||
#endif // EXHAUSTIVE_DEBUG
|
||||
|
||||
if (subop_grab == 32) {
|
||||
ppc_bclr();
|
||||
} else if (subop_grab == 33) {
|
||||
ppc_bclrl();
|
||||
} else if (subop_grab == 1056) {
|
||||
ppc_bcctr();
|
||||
} else if (subop_grab == 1057) {
|
||||
ppc_bcctrl();
|
||||
|
||||
} else {
|
||||
switch (subop_grab) {
|
||||
case 66:
|
||||
ppc_crnor();
|
||||
break;
|
||||
case 100:
|
||||
ppc_rfi();
|
||||
break;
|
||||
case 258:
|
||||
ppc_crandc();
|
||||
break;
|
||||
case 300:
|
||||
ppc_isync();
|
||||
break;
|
||||
case 386:
|
||||
ppc_crxor();
|
||||
break;
|
||||
case 450:
|
||||
ppc_crnand();
|
||||
break;
|
||||
case 514:
|
||||
ppc_crand();
|
||||
break;
|
||||
case 578:
|
||||
ppc_creqv();
|
||||
break;
|
||||
case 834:
|
||||
ppc_crorc();
|
||||
break;
|
||||
case 898:
|
||||
ppc_cror();
|
||||
break;
|
||||
default:
|
||||
ppc_illegalop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_opcode31() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
||||
#ifdef EXHAUSTIVE_DEBUG
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(INFO, "Executing Opcode 31 table subopcode entry \n", regrab);
|
||||
if (SubOpcode31Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode31Grabber[subop_grab]();
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
#else
|
||||
SubOpcode31Grabber[subop_grab]();
|
||||
#endif // EXHAUSTIVE_DEBUG
|
||||
}
|
||||
uint16_t subop_grab = (ppc_cur_instruction & 0x7FF) >> 1;
|
||||
|
||||
void ppc_opcode59() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
||||
#ifdef EXHAUSTIVE_DEBUG
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(INFO, "Executing Opcode 59 table subopcode entry \n", regrab);
|
||||
if (SubOpcode59Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode59Grabber[subop_grab]();
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
#else
|
||||
SubOpcode59Grabber[subop_grab]();
|
||||
#endif // EXHAUSTIVE_DEBUG
|
||||
}
|
||||
rc_flag = ppc_cur_instruction & 0x1;
|
||||
oe_flag = ppc_cur_instruction & 0x400;
|
||||
|
||||
void ppc_opcode63() {
|
||||
uint16_t subop_grab = ppc_cur_instruction & 2047;
|
||||
#ifdef EXHAUSTIVE_DEBUG
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
|
||||
if (SubOpcode63Grabber.count(subop_grab) == 1) {
|
||||
SubOpcode63Grabber[subop_grab]();
|
||||
} else {
|
||||
LOG_F(ERROR, "ILLEGAL SUBOPCODE: %d \n", subop_grab);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x80000);
|
||||
}
|
||||
#else
|
||||
SubOpcode63Grabber[subop_grab]();
|
||||
#endif // EXHAUSTIVE_DEBUG
|
||||
|
||||
SubOpcode31Grabber[subop_grab]();
|
||||
}
|
||||
|
||||
void ppc_opcode59() {
|
||||
uint16_t subop_grab = (ppc_cur_instruction & 0x7FF) >> 1;
|
||||
rc_flag = subop_grab & 1;
|
||||
#ifdef EXHAUSTIVE_DEBUG
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(INFO, "Executing Opcode 59 table subopcode entry \n", regrab);
|
||||
#endif // EXHAUSTIVE_DEBUG
|
||||
SubOpcode59Grabber[subop_grab]();
|
||||
}
|
||||
|
||||
void ppc_opcode63() {
|
||||
uint16_t subop_grab = (ppc_cur_instruction & 0x7FF) >> 1;
|
||||
rc_flag = subop_grab & 1;
|
||||
#ifdef EXHAUSTIVE_DEBUG
|
||||
uint32_t regrab = (uint32_t)subop_grab;
|
||||
LOG_F(INFO, "Executing Opcode 63 table subopcode entry \n", regrab);
|
||||
#endif // EXHAUSTIVE_DEBUG
|
||||
SubOpcode63Grabber[subop_grab]();
|
||||
}
|
||||
|
||||
/* Dispatch using main opcode */
|
||||
|
@ -610,7 +328,7 @@ void ppc_exec_single()
|
|||
}
|
||||
|
||||
/** Execute PPC code until goal_addr is reached. */
|
||||
void ppc_exec_until(uint32_t goal_addr)
|
||||
void ppc_exec_until(volatile uint32_t goal_addr)
|
||||
{
|
||||
uint32_t bb_start_la, page_start, delta;
|
||||
uint8_t* pc_real;
|
||||
|
@ -669,6 +387,68 @@ again:
|
|||
}
|
||||
}
|
||||
|
||||
/** Execute PPC code until control is reached the specified region. */
|
||||
void ppc_exec_dbg(volatile uint32_t start_addr, volatile uint32_t size)
|
||||
{
|
||||
uint32_t bb_start_la, page_start, delta;
|
||||
uint8_t* pc_real;
|
||||
|
||||
/* start new basic block */
|
||||
glob_bb_start_la = bb_start_la = ppc_state.pc;
|
||||
bb_kind = BB_end_kind::BB_NONE;
|
||||
|
||||
if (setjmp(exc_env)) {
|
||||
/* reaching here means we got a low-level exception */
|
||||
#ifdef NEW_TBR_UPDATE_ALGO
|
||||
cycles_count += ((ppc_state.pc - glob_bb_start_la) >> 2) + 1;
|
||||
UPDATE_TBR_DEC
|
||||
#else
|
||||
timebase_counter += ((ppc_state.pc - glob_bb_start_la) >> 2) + 1;
|
||||
#endif
|
||||
glob_bb_start_la = bb_start_la = ppc_next_instruction_address;
|
||||
pc_real = quickinstruction_translate(bb_start_la);
|
||||
page_start = bb_start_la & 0xFFFFF000;
|
||||
ppc_state.pc = bb_start_la;
|
||||
bb_kind = BB_end_kind::BB_NONE;
|
||||
//printf("DBG Exec: got exception, continue at %X\n", ppc_state.pc);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
again:
|
||||
while (ppc_state.pc < start_addr || ppc_state.pc >= start_addr + size) {
|
||||
ppc_main_opcode();
|
||||
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) + 1;
|
||||
#endif
|
||||
glob_bb_start_la = 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.pc;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
}
|
||||
ppc_state.pc = bb_start_la;
|
||||
bb_kind = BB_end_kind::BB_NONE;
|
||||
//printf("DBG Exec: new basic block at %X, start_addr=%X\n", ppc_state.pc, start_addr);
|
||||
} else {
|
||||
ppc_state.pc += 4;
|
||||
pc_real += 4;
|
||||
ppc_set_cur_instruction(pc_real);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64_t instr_count, old_instr_count;
|
||||
|
||||
|
@ -704,6 +484,209 @@ void test_timebase_update()
|
|||
|
||||
}
|
||||
|
||||
void initialize_ppc_opcode_tables() {
|
||||
SubOpcode31Grabber[0] = ppc_cmp;
|
||||
SubOpcode31Grabber[4] = ppc_tw;
|
||||
SubOpcode31Grabber[32] = ppc_cmpl;
|
||||
|
||||
SubOpcode31Grabber[8] = SubOpcode31Grabber[520] = ppc_subfc;
|
||||
SubOpcode31Grabber[40] = SubOpcode31Grabber[552] = ppc_subf;
|
||||
SubOpcode31Grabber[104] = SubOpcode31Grabber[616] = ppc_neg;
|
||||
SubOpcode31Grabber[136] = SubOpcode31Grabber[648] = ppc_subfe;
|
||||
SubOpcode31Grabber[200] = SubOpcode31Grabber[712] = ppc_subfze;
|
||||
SubOpcode31Grabber[232] = SubOpcode31Grabber[744] = ppc_subfme;
|
||||
|
||||
SubOpcode31Grabber[10] = SubOpcode31Grabber[522] = ppc_addc;
|
||||
SubOpcode31Grabber[138] = SubOpcode31Grabber[650] = ppc_adde;
|
||||
SubOpcode31Grabber[202] = SubOpcode31Grabber[714] = ppc_addze;
|
||||
SubOpcode31Grabber[234] = SubOpcode31Grabber[746] = ppc_addme;
|
||||
SubOpcode31Grabber[266] = SubOpcode31Grabber[778] = ppc_add;
|
||||
|
||||
SubOpcode31Grabber[11] = ppc_mulhwu;
|
||||
SubOpcode31Grabber[75] = ppc_mulhw;
|
||||
SubOpcode31Grabber[235] = SubOpcode31Grabber[747] = ppc_mullw;
|
||||
SubOpcode31Grabber[459] = SubOpcode31Grabber[971] = ppc_divwu;
|
||||
SubOpcode31Grabber[491] = SubOpcode31Grabber[1003] = ppc_divw;
|
||||
|
||||
SubOpcode31Grabber[20] = ppc_lwarx;
|
||||
SubOpcode31Grabber[23] = ppc_lwzx;
|
||||
SubOpcode31Grabber[55] = ppc_lwzux;
|
||||
SubOpcode31Grabber[87] = ppc_lbzx;
|
||||
SubOpcode31Grabber[119] = ppc_lbzux;
|
||||
SubOpcode31Grabber[279] = ppc_lhzx;
|
||||
SubOpcode31Grabber[311] = ppc_lhzux;
|
||||
SubOpcode31Grabber[343] = ppc_lhax;
|
||||
SubOpcode31Grabber[375] = ppc_lhaux;
|
||||
SubOpcode31Grabber[533] = ppc_lswx;
|
||||
SubOpcode31Grabber[534] = ppc_lwbrx;
|
||||
SubOpcode31Grabber[535] = ppc_lfsx;
|
||||
SubOpcode31Grabber[567] = ppc_lfsux;
|
||||
SubOpcode31Grabber[597] = ppc_lswi;
|
||||
SubOpcode31Grabber[599] = ppc_lfdx;
|
||||
SubOpcode31Grabber[631] = ppc_lfdux;
|
||||
SubOpcode31Grabber[790] = ppc_lhbrx;
|
||||
|
||||
SubOpcode31Grabber[150] = ppc_stwcx;
|
||||
SubOpcode31Grabber[151] = ppc_stwx;
|
||||
SubOpcode31Grabber[183] = ppc_stwux;
|
||||
SubOpcode31Grabber[215] = ppc_stbx;
|
||||
SubOpcode31Grabber[247] = ppc_stbux;
|
||||
SubOpcode31Grabber[407] = ppc_sthx;
|
||||
SubOpcode31Grabber[439] = ppc_sthux;
|
||||
SubOpcode31Grabber[661] = ppc_stswx;
|
||||
SubOpcode31Grabber[662] = ppc_stwbrx;
|
||||
SubOpcode31Grabber[663] = ppc_stfsx;
|
||||
SubOpcode31Grabber[695] = ppc_stfsux;
|
||||
SubOpcode31Grabber[725] = ppc_stswi;
|
||||
SubOpcode31Grabber[727] = ppc_stfdx;
|
||||
SubOpcode31Grabber[759] = ppc_stfdux;
|
||||
SubOpcode31Grabber[918] = ppc_sthbrx;
|
||||
SubOpcode31Grabber[983] = ppc_stfiwx;
|
||||
|
||||
SubOpcode31Grabber[24] = ppc_slw;
|
||||
SubOpcode31Grabber[28] = ppc_and;
|
||||
SubOpcode31Grabber[60] = ppc_andc;
|
||||
SubOpcode31Grabber[124] = ppc_nor;
|
||||
SubOpcode31Grabber[284] = ppc_eqv;
|
||||
SubOpcode31Grabber[316] = ppc_xor;
|
||||
SubOpcode31Grabber[412] = ppc_orc;
|
||||
SubOpcode31Grabber[444] = ppc_or;
|
||||
SubOpcode31Grabber[476] = ppc_nand;
|
||||
SubOpcode31Grabber[536] = ppc_srw;
|
||||
SubOpcode31Grabber[792] = ppc_sraw;
|
||||
SubOpcode31Grabber[824] = ppc_srawi;
|
||||
SubOpcode31Grabber[922] = ppc_extsh;
|
||||
SubOpcode31Grabber[954] = ppc_extsb;
|
||||
|
||||
SubOpcode31Grabber[26] = ppc_cntlzw;
|
||||
|
||||
SubOpcode31Grabber[19] = ppc_mfcr;
|
||||
SubOpcode31Grabber[83] = ppc_mfmsr;
|
||||
SubOpcode31Grabber[144] = ppc_mtcrf;
|
||||
SubOpcode31Grabber[146] = ppc_mtmsr;
|
||||
SubOpcode31Grabber[210] = ppc_mtsr;
|
||||
SubOpcode31Grabber[242] = ppc_mtsrin;
|
||||
SubOpcode31Grabber[339] = ppc_mfspr;
|
||||
SubOpcode31Grabber[371] = ppc_mftb;
|
||||
SubOpcode31Grabber[467] = ppc_mtspr;
|
||||
SubOpcode31Grabber[512] = ppc_mcrxr;
|
||||
SubOpcode31Grabber[595] = ppc_mfsr;
|
||||
SubOpcode31Grabber[659] = ppc_mfsrin;
|
||||
|
||||
SubOpcode31Grabber[54] = ppc_dcbst;
|
||||
SubOpcode31Grabber[86] = ppc_dcbf;
|
||||
SubOpcode31Grabber[246] = ppc_dcbtst;
|
||||
SubOpcode31Grabber[278] = ppc_dcbt;
|
||||
SubOpcode31Grabber[598] = ppc_sync;
|
||||
SubOpcode31Grabber[470] = ppc_dcbi;
|
||||
SubOpcode31Grabber[1014] = ppc_dcbz;
|
||||
|
||||
SubOpcode31Grabber[29] = power_maskg;
|
||||
SubOpcode31Grabber[107] = SubOpcode31Grabber[619] = power_mul;
|
||||
SubOpcode31Grabber[152] = power_slq;
|
||||
SubOpcode31Grabber[153] = power_sle;
|
||||
SubOpcode31Grabber[184] = power_sliq;
|
||||
SubOpcode31Grabber[216] = power_sllq;
|
||||
SubOpcode31Grabber[217] = power_sleq;
|
||||
SubOpcode31Grabber[248] = power_slliq;
|
||||
SubOpcode31Grabber[264] = SubOpcode31Grabber[776] = power_doz;
|
||||
SubOpcode31Grabber[277] = power_lscbx;
|
||||
SubOpcode31Grabber[331] = SubOpcode31Grabber[843] = power_div;
|
||||
SubOpcode31Grabber[360] = SubOpcode31Grabber[872] = power_abs;
|
||||
SubOpcode31Grabber[363] = SubOpcode31Grabber[875] = power_divs;
|
||||
SubOpcode31Grabber[488] = SubOpcode31Grabber[1000] = power_nabs;
|
||||
SubOpcode31Grabber[531] = power_clcs;
|
||||
SubOpcode31Grabber[537] = power_rrib;
|
||||
SubOpcode31Grabber[541] = power_maskir;
|
||||
SubOpcode31Grabber[664] = power_srq;
|
||||
SubOpcode31Grabber[665] = power_sre;
|
||||
SubOpcode31Grabber[696] = power_sriq;
|
||||
SubOpcode31Grabber[728] = power_srlq;
|
||||
SubOpcode31Grabber[729] = power_sreq;
|
||||
SubOpcode31Grabber[760] = power_srliq;
|
||||
SubOpcode31Grabber[920] = power_sraq;
|
||||
SubOpcode31Grabber[921] = power_srea;
|
||||
SubOpcode31Grabber[952] = power_sraiq;
|
||||
|
||||
SubOpcode31Grabber[306] = ppc_tlbie;
|
||||
SubOpcode31Grabber[370] = ppc_tlbia;
|
||||
SubOpcode31Grabber[566] = ppc_tlbsync;
|
||||
SubOpcode31Grabber[854] = ppc_eieio;
|
||||
SubOpcode31Grabber[982] = ppc_icbi;
|
||||
SubOpcode31Grabber[978] = ppc_tlbld;
|
||||
SubOpcode31Grabber[1010] = ppc_tlbli;
|
||||
|
||||
SubOpcode59Grabber[18] = ppc_fdivs;
|
||||
SubOpcode59Grabber[20] = ppc_fsubs;
|
||||
SubOpcode59Grabber[22] = ppc_fsqrts;
|
||||
SubOpcode59Grabber[24] = ppc_fres;
|
||||
|
||||
for (int i = 25; i < 1024; i += 32) {
|
||||
SubOpcode59Grabber[i] = ppc_fmults;
|
||||
}
|
||||
|
||||
for (int i = 28; i < 1024; i += 32) {
|
||||
SubOpcode59Grabber[i] = ppc_fmsubs;
|
||||
}
|
||||
|
||||
for (int i = 29; i < 1024; i += 32) {
|
||||
SubOpcode59Grabber[i] = ppc_fmadds;
|
||||
}
|
||||
|
||||
for (int i = 30; i < 1024; i += 32) {
|
||||
SubOpcode59Grabber[i] = ppc_fnmsubs;
|
||||
}
|
||||
|
||||
for (int i = 31; i < 1024; i += 32) {
|
||||
SubOpcode59Grabber[i] = ppc_fnmadds;
|
||||
}
|
||||
|
||||
SubOpcode63Grabber[0] = ppc_fcmpu;
|
||||
SubOpcode63Grabber[12] = ppc_frsp;
|
||||
SubOpcode63Grabber[14] = ppc_fctiw;
|
||||
SubOpcode63Grabber[15] = ppc_fctiwz;
|
||||
SubOpcode63Grabber[18] = ppc_fdiv;
|
||||
SubOpcode63Grabber[20] = ppc_fsub;
|
||||
SubOpcode63Grabber[21] = ppc_fadd;
|
||||
SubOpcode63Grabber[22] = ppc_fsqrt;
|
||||
SubOpcode63Grabber[26] = ppc_frsqrte;
|
||||
SubOpcode63Grabber[32] = ppc_fcmpo;
|
||||
SubOpcode63Grabber[38] = ppc_mtfsb1;
|
||||
SubOpcode63Grabber[40] = ppc_fneg;
|
||||
SubOpcode63Grabber[64] = ppc_mcrfs;
|
||||
SubOpcode63Grabber[70] = ppc_mtfsb0;
|
||||
SubOpcode63Grabber[72] = ppc_fmr;
|
||||
SubOpcode63Grabber[134] = ppc_mtfsfi;
|
||||
SubOpcode63Grabber[136] = ppc_fnabs;
|
||||
SubOpcode63Grabber[264] = ppc_fabs;
|
||||
SubOpcode63Grabber[583] = ppc_mffs;
|
||||
SubOpcode63Grabber[711] = ppc_mtfsf;
|
||||
|
||||
for (int i = 23; i < 1024; i += 32) {
|
||||
SubOpcode63Grabber[i] = ppc_fsel;
|
||||
}
|
||||
|
||||
for (int i = 25; i < 1024; i += 32) {
|
||||
SubOpcode63Grabber[i] = ppc_fmult;
|
||||
}
|
||||
|
||||
for (int i = 28; i < 1024; i += 32) {
|
||||
SubOpcode63Grabber[i] = ppc_fmsub;
|
||||
}
|
||||
|
||||
for (int i = 29; i < 1024; i += 32) {
|
||||
SubOpcode63Grabber[i] = ppc_fmadd;
|
||||
}
|
||||
|
||||
for (int i = 30; i < 1024; i += 32) {
|
||||
SubOpcode63Grabber[i] = ppc_fnmsub;
|
||||
}
|
||||
|
||||
for (int i = 31; i < 1024; i += 32) {
|
||||
SubOpcode63Grabber[i] = ppc_fnmadd;
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t proc_version) {
|
||||
int i;
|
||||
|
||||
|
@ -711,6 +694,8 @@ void ppc_cpu_init(MemCtrlBase* mem_ctrl, uint32_t proc_version) {
|
|||
|
||||
//test_timebase_update();
|
||||
|
||||
initialize_ppc_opcode_tables();
|
||||
|
||||
/* initialize timer variables */
|
||||
#ifdef NEW_TBR_UPDATE_ALGO
|
||||
cycles_count = 0;
|
||||
|
|
|
@ -371,73 +371,43 @@ void ppc_changecrf1() {
|
|||
}
|
||||
|
||||
// Floating Point Arithmetic
|
||||
void ppc_fadd() {
|
||||
void dppc_interpreter::ppc_fadd() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a + ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fadddot() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a + ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsub() {
|
||||
void dppc_interpreter::ppc_fsub() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 56)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a - ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsubdot() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 56)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a - ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fdiv() {
|
||||
void dppc_interpreter::ppc_fdiv() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 36)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a / ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fdivdot() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 36)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a / ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmult() {
|
||||
ppc_grab_regsfpdac(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 50)) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_a * ppc_dblresult64_b;
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_fmultdot() {
|
||||
void dppc_interpreter::ppc_fmult() {
|
||||
ppc_grab_regsfpdac(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 50)) {
|
||||
|
@ -445,10 +415,11 @@ void ppc_fmultdot() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmadd() {
|
||||
void dppc_interpreter::ppc_fmadd() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
|
@ -459,23 +430,12 @@ void ppc_fmadd() {
|
|||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmadddot() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
ppc_dblresult64_d = (ppc_dblresult64_a * ppc_dblresult64_c);
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
|
||||
ppc_dblresult64_d += ppc_dblresult64_b;
|
||||
}
|
||||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmsub() {
|
||||
void dppc_interpreter::ppc_fmsub() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
|
@ -486,23 +446,12 @@ void ppc_fmsub() {
|
|||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmsubdot() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
ppc_dblresult64_d = (ppc_dblresult64_a * ppc_dblresult64_c);
|
||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
||||
ppc_dblresult64_d -= ppc_dblresult64_b;
|
||||
}
|
||||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmadd() {
|
||||
void dppc_interpreter::ppc_fnmadd() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
|
@ -514,25 +463,12 @@ void ppc_fnmadd() {
|
|||
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmadddot() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
ppc_dblresult64_d = (ppc_dblresult64_a * ppc_dblresult64_c);
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, false, 58)) {
|
||||
ppc_dblresult64_d += ppc_dblresult64_b;
|
||||
}
|
||||
}
|
||||
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmsub() {
|
||||
void dppc_interpreter::ppc_fnmsub() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
|
@ -544,34 +480,12 @@ void ppc_fnmsub() {
|
|||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmsubdot() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
ppc_dblresult64_d = (ppc_dblresult64_a * ppc_dblresult64_c);
|
||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
||||
ppc_dblresult64_d -= ppc_dblresult64_b;
|
||||
}
|
||||
}
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fadds() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
||||
float intermediate = (float)ppc_dblresult64_a + (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_faddsdot() {
|
||||
void dppc_interpreter::ppc_fadds() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
||||
|
@ -580,20 +494,11 @@ void ppc_faddsdot() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsubs() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 56)) {
|
||||
float intermediate = (float)ppc_dblresult64_a - (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_fsubsdot() {
|
||||
void dppc_interpreter::ppc_fsubs() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 56)) {
|
||||
|
@ -602,10 +507,11 @@ void ppc_fsubsdot() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmults() {
|
||||
void dppc_interpreter::ppc_fmults() {
|
||||
ppc_grab_regsfpdac(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 50)) {
|
||||
|
@ -613,30 +519,12 @@ void ppc_fmults() {
|
|||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmultsdot() {
|
||||
ppc_grab_regsfpdac(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 50)) {
|
||||
float intermediate = (float)ppc_dblresult64_a * (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fdivs() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 36)) {
|
||||
float intermediate = (float)ppc_dblresult64_a / (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_fdivsdot() {
|
||||
void dppc_interpreter::ppc_fdivs() {
|
||||
ppc_grab_regsfpdab(false);
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 36)) {
|
||||
|
@ -645,26 +533,11 @@ void ppc_fdivsdot() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmadds() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
||||
intermediate = (float)ppc_dblresult64_a * (float)ppc_dblresult64_c;
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
||||
intermediate += (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_fmaddsdot() {
|
||||
void dppc_interpreter::ppc_fmadds() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
@ -679,26 +552,11 @@ void ppc_fmaddsdot() {
|
|||
}
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fmsubs() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
intermediate = (float)ppc_dblresult64_a * (float)ppc_dblresult64_c;
|
||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
||||
intermediate -= (float)ppc_dblresult64_b;
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_fmsubsdot() {
|
||||
void dppc_interpreter::ppc_fmsubs() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
@ -713,28 +571,11 @@ void ppc_fmsubsdot() {
|
|||
}
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmadds() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
||||
intermediate = (float)ppc_dblresult64_a * (float)ppc_dblresult64_c;
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_b, true, 58)) {
|
||||
intermediate += (float)ppc_dblresult64_b;
|
||||
intermediate = -intermediate;
|
||||
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
}
|
||||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
|
||||
void ppc_fnmaddsdot() {
|
||||
void dppc_interpreter::ppc_fnmadds() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
@ -751,10 +592,11 @@ void ppc_fnmaddsdot() {
|
|||
}
|
||||
}
|
||||
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmsubs() {
|
||||
void dppc_interpreter::ppc_fnmsubs() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
@ -770,81 +612,46 @@ void ppc_fnmsubs() {
|
|||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnmsubsdot() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
float intermediate;
|
||||
|
||||
if (!ppc_confirm_inf_nan(reg_a, reg_c, false, 50)) {
|
||||
intermediate = (float)ppc_dblresult64_a * (float)ppc_dblresult64_c;
|
||||
if (!ppc_confirm_inf_nan(reg_d, reg_b, false, 56)) {
|
||||
intermediate -= (float)ppc_dblresult64_b;
|
||||
intermediate = -intermediate;
|
||||
|
||||
ppc_dblresult64_d = static_cast<double>(intermediate);
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
}
|
||||
}
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fabs() {
|
||||
void dppc_interpreter::ppc_fabs() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
ppc_dblresult64_d = abs(ppc_dblresult64_b);
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fabsdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
ppc_dblresult64_d = abs(ppc_dblresult64_b);
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnabs() {
|
||||
void dppc_interpreter::ppc_fnabs() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
ppc_dblresult64_d = abs(ppc_dblresult64_b);
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnabsdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
ppc_dblresult64_d = abs(ppc_dblresult64_b);
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fneg() {
|
||||
void dppc_interpreter::ppc_fneg() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fnegdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
ppc_dblresult64_d = -ppc_dblresult64_d;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsel() {
|
||||
void dppc_interpreter::ppc_fsel() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (ppc_dblresult64_a >= 0.0) {
|
||||
|
@ -854,35 +661,21 @@ void ppc_fsel() {
|
|||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fseldot() {
|
||||
ppc_grab_regsfpdabc(false);
|
||||
|
||||
if (ppc_dblresult64_a >= 0.0) {
|
||||
ppc_dblresult64_d = ppc_dblresult64_c;
|
||||
} else {
|
||||
ppc_dblresult64_d = ppc_dblresult64_b;
|
||||
}
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsqrt() {
|
||||
void dppc_interpreter::ppc_fsqrt() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
ppc_dblresult64_d = std::sqrt(ppc_dblresult64_b);
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsqrtdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
ppc_dblresult64_d = std::sqrt(ppc_dblresult64_b);
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsqrts() {
|
||||
void dppc_interpreter::ppc_fsqrts() {
|
||||
ppc_grab_regsfpdb(true);
|
||||
uint32_t test = (uint32_t)ppc_result64_b;
|
||||
test += 127 << 23;
|
||||
|
@ -890,20 +683,12 @@ void ppc_fsqrts() {
|
|||
uint64_t* pre_final = (uint64_t*)&test;
|
||||
ppc_result64_d = *pre_final;
|
||||
ppc_store_dfpresult(true);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fsqrtsdot() {
|
||||
ppc_grab_regsfpdb(true);
|
||||
uint32_t test = (uint32_t)ppc_result64_b;
|
||||
test += 127 << 23;
|
||||
test >>= 1;
|
||||
uint64_t* pre_final = (uint64_t*)&test;
|
||||
ppc_result64_d = *pre_final;
|
||||
ppc_store_dfpresult(true);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_frsqrte() {
|
||||
void dppc_interpreter::ppc_frsqrte() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
|
@ -912,55 +697,34 @@ void ppc_frsqrte() {
|
|||
ppc_dblresult64_d = testd2;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_frsqrtedot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
testd2 = testd2 * (1.5 - (testd2 * .5) * testd2 * testd2);
|
||||
}
|
||||
ppc_dblresult64_d = testd2;
|
||||
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_frsp() {
|
||||
void dppc_interpreter::ppc_frsp() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
float testf2 = (float)testd2;
|
||||
ppc_dblresult64_d = (double)testf2;
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_frspdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
double testd2 = (double)ppc_result64_b;
|
||||
float testf2 = (float)testd2;
|
||||
ppc_dblresult64_d = (double)testf2;
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fres() {
|
||||
void dppc_interpreter::ppc_fres() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
float testf2 = (float)ppc_dblresult64_b;
|
||||
testf2 = 1 / testf2;
|
||||
ppc_dblresult64_d = (double)testf2;
|
||||
ppc_store_dfpresult(false);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fresdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
float testf2 = (float)ppc_dblresult64_b;
|
||||
testf2 = 1 / testf2;
|
||||
ppc_dblresult64_d = (double)testf2;
|
||||
ppc_store_dfpresult(false);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fctiw() {
|
||||
void dppc_interpreter::ppc_fctiw() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
switch (ppc_state.fpscr & 0x3) {
|
||||
|
@ -975,44 +739,24 @@ void ppc_fctiw() {
|
|||
}
|
||||
|
||||
ppc_store_dfpresult(true);
|
||||
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fctiwdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
|
||||
switch (ppc_state.fpscr & 0x3) {
|
||||
case 0:
|
||||
ppc_result64_d = round_to_nearest(ppc_dblresult64_b);
|
||||
case 1:
|
||||
ppc_result64_d = round_to_zero(ppc_dblresult64_b);
|
||||
case 2:
|
||||
ppc_result64_d = round_to_pos_inf(ppc_dblresult64_b);
|
||||
case 3:
|
||||
ppc_result64_d = round_to_neg_inf(ppc_dblresult64_b);
|
||||
}
|
||||
|
||||
ppc_store_dfpresult(true);
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_fctiwz() {
|
||||
void dppc_interpreter::ppc_fctiwz() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
ppc_result64_d = round_to_zero(ppc_dblresult64_b);
|
||||
|
||||
ppc_store_result_regd();
|
||||
}
|
||||
|
||||
void ppc_fctiwzdot() {
|
||||
ppc_grab_regsfpdb(false);
|
||||
ppc_result64_d = round_to_zero(ppc_dblresult64_b);
|
||||
|
||||
ppc_store_result_regd();
|
||||
ppc_changecrf1();
|
||||
if (rc_flag)
|
||||
ppc_changecrf1();
|
||||
}
|
||||
|
||||
// Floating Point Store and Load
|
||||
|
||||
void ppc_lfs() {
|
||||
void dppc_interpreter::ppc_lfs() {
|
||||
ppc_grab_regsfpdia(true);
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
|
||||
|
@ -1021,9 +765,9 @@ void ppc_lfs() {
|
|||
}
|
||||
|
||||
|
||||
void ppc_lfsu() {
|
||||
void dppc_interpreter::ppc_lfsu() {
|
||||
ppc_grab_regsfpdia(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
|
||||
ppc_result64_d = mem_grab_dword(ppc_effective_address);
|
||||
|
@ -1031,31 +775,31 @@ void ppc_lfsu() {
|
|||
ppc_store_dfpresult(true);
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_lfsx() {
|
||||
void dppc_interpreter::ppc_lfsx() {
|
||||
ppc_grab_regsfpdiab(true);
|
||||
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
|
||||
ppc_result64_d = mem_grab_dword(ppc_effective_address);
|
||||
ppc_store_dfpresult(true);
|
||||
}
|
||||
|
||||
void ppc_lfsux() {
|
||||
void dppc_interpreter::ppc_lfsux() {
|
||||
ppc_grab_regsfpdiab(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = ppc_result_a + ppc_result_b;
|
||||
ppc_result64_d = mem_grab_dword(ppc_effective_address);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_dfpresult(true);
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_lfd() {
|
||||
void dppc_interpreter::ppc_lfd() {
|
||||
ppc_grab_regsfpdia(true);
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
|
||||
|
@ -1063,9 +807,9 @@ void ppc_lfd() {
|
|||
ppc_store_dfpresult(true);
|
||||
}
|
||||
|
||||
void ppc_lfdu() {
|
||||
void dppc_interpreter::ppc_lfdu() {
|
||||
ppc_grab_regsfpdia(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += ppc_result_a;
|
||||
ppc_result64_d = mem_grab_qword(ppc_effective_address);
|
||||
|
@ -1073,107 +817,107 @@ void ppc_lfdu() {
|
|||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_lfdx() {
|
||||
void dppc_interpreter::ppc_lfdx() {
|
||||
ppc_grab_regsfpdia(true);
|
||||
ppc_effective_address += (reg_a > 0) ? ppc_result_a + ppc_result_b : ppc_result_b;
|
||||
ppc_effective_address = (reg_a > 0) ? ppc_result_a + ppc_result_b : ppc_result_b;
|
||||
ppc_result64_d = mem_grab_qword(ppc_effective_address);
|
||||
ppc_store_dfpresult(true);
|
||||
}
|
||||
|
||||
void ppc_lfdux() {
|
||||
void dppc_interpreter::ppc_lfdux() {
|
||||
ppc_grab_regsfpdiab(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = ppc_result_a + ppc_result_b;
|
||||
ppc_result64_d = mem_grab_qword(ppc_effective_address);
|
||||
ppc_store_dfpresult(true);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_stfs() {
|
||||
void dppc_interpreter::ppc_stfs() {
|
||||
ppc_grab_regsfpsia(true);
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
|
||||
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
}
|
||||
|
||||
void ppc_stfsu() {
|
||||
void dppc_interpreter::ppc_stfsu() {
|
||||
ppc_grab_regsfpsia(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += ppc_result_a;
|
||||
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_stfsx() {
|
||||
void dppc_interpreter::ppc_stfsx() {
|
||||
ppc_grab_regsfpsiab(true);
|
||||
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
|
||||
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
}
|
||||
|
||||
void ppc_stfsux() {
|
||||
void dppc_interpreter::ppc_stfsux() {
|
||||
ppc_grab_regsfpsiab(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = ppc_result_a + ppc_result_b;
|
||||
mem_write_dword(ppc_effective_address, uint32_t(ppc_state.fpr[reg_s].int64_r));
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_stfd() {
|
||||
void dppc_interpreter::ppc_stfd() {
|
||||
ppc_grab_regsfpsia(true);
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += (reg_a > 0) ? ppc_result_a : 0;
|
||||
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
|
||||
}
|
||||
|
||||
void ppc_stfdu() {
|
||||
void dppc_interpreter::ppc_stfdu() {
|
||||
ppc_grab_regsfpsia(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = (int32_t)((int16_t)(ppc_cur_instruction & 0xFFFF));
|
||||
ppc_effective_address += ppc_result_a;
|
||||
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_stfdx() {
|
||||
void dppc_interpreter::ppc_stfdx() {
|
||||
ppc_grab_regsfpsiab(true);
|
||||
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
|
||||
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
|
||||
}
|
||||
|
||||
void ppc_stfdux() {
|
||||
void dppc_interpreter::ppc_stfdux() {
|
||||
ppc_grab_regsfpsiab(true);
|
||||
if (reg_a == 0) {
|
||||
if (reg_a != 0) {
|
||||
ppc_effective_address = ppc_result_a + ppc_result_b;
|
||||
mem_write_qword(ppc_effective_address, ppc_state.fpr[reg_s].int64_r);
|
||||
ppc_result_a = ppc_effective_address;
|
||||
ppc_store_result_rega();
|
||||
} else {
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, 0x20000);
|
||||
ppc_exception_handler(Except_Type::EXC_PROGRAM, Exc_Cause::ILLEGAL_OP);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_stfiwx() {
|
||||
void dppc_interpreter::ppc_stfiwx() {
|
||||
ppc_grab_regsfpsiab(true);
|
||||
ppc_effective_address = (reg_a == 0) ? ppc_result_b : ppc_result_a + ppc_result_b;
|
||||
mem_write_dword(ppc_effective_address, (uint32_t)(ppc_state.fpr[reg_s].int64_r));
|
||||
|
@ -1181,14 +925,14 @@ void ppc_stfiwx() {
|
|||
|
||||
// Floating Point Register Transfer
|
||||
|
||||
void ppc_fmr() {
|
||||
void dppc_interpreter::ppc_fmr() {
|
||||
ppc_grab_regsfpdb(true);
|
||||
ppc_state.fpr[reg_d] = ppc_state.fpr[reg_b];
|
||||
ppc_store_dfpresult(true);
|
||||
}
|
||||
|
||||
|
||||
void ppc_mffs() {
|
||||
void dppc_interpreter::ppc_mffs() {
|
||||
ppc_grab_regsda();
|
||||
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000;
|
||||
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF;
|
||||
|
@ -1196,7 +940,7 @@ void ppc_mffs() {
|
|||
fp_save_uint64(fpstore1);
|
||||
}
|
||||
|
||||
void ppc_mffsdot() {
|
||||
void dppc_interpreter::ppc_mffsdot() {
|
||||
ppc_grab_regsda();
|
||||
uint64_t fpstore1 = ppc_state.fpr[reg_d].int64_r & 0xFFFFFFFF00000000;
|
||||
uint64_t fpstore2 = ppc_state.fpscr & 0x00000000FFFFFFFF;
|
||||
|
@ -1205,7 +949,7 @@ void ppc_mffsdot() {
|
|||
ppc_fp_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_mtfsf() {
|
||||
void dppc_interpreter::ppc_mtfsf() {
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
|
||||
crm += ((fm_mask & 1) == 1) ? 0xF0000000 : 0x00000000;
|
||||
|
@ -1220,7 +964,7 @@ void ppc_mtfsf() {
|
|||
ppc_state.fpscr = (quickfprval & crm) | (quickfprval & ~(crm));
|
||||
}
|
||||
|
||||
void ppc_mtfsfdot() {
|
||||
void dppc_interpreter::ppc_mtfsfdot() {
|
||||
reg_b = (ppc_cur_instruction >> 11) & 31;
|
||||
uint32_t fm_mask = (ppc_cur_instruction >> 17) & 255;
|
||||
crm += ((fm_mask & 1) == 1) ? 0xF0000000 : 0x00000000;
|
||||
|
@ -1236,7 +980,7 @@ void ppc_mtfsfdot() {
|
|||
ppc_fp_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_mtfsfi() {
|
||||
void dppc_interpreter::ppc_mtfsfi() {
|
||||
ppc_result_b = (ppc_cur_instruction >> 11) & 15;
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
|
@ -1244,7 +988,7 @@ void ppc_mtfsfi() {
|
|||
((ppc_state.spr[SPR::XER] & 0xF0000000UL) >> crf_d);
|
||||
}
|
||||
|
||||
void ppc_mtfsfidot() {
|
||||
void dppc_interpreter::ppc_mtfsfidot() {
|
||||
ppc_result_b = (ppc_cur_instruction >> 11) & 15;
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
|
@ -1253,14 +997,14 @@ void ppc_mtfsfidot() {
|
|||
ppc_fp_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_mtfsb0() {
|
||||
void dppc_interpreter::ppc_mtfsb0() {
|
||||
crf_d = (ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)) {
|
||||
ppc_state.fpscr &= ~(1 << (31 - crf_d));
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_mtfsb0dot() {
|
||||
void dppc_interpreter::ppc_mtfsb0dot() {
|
||||
crf_d = (ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)) {
|
||||
ppc_state.fpscr &= ~(1 << crf_d);
|
||||
|
@ -1268,14 +1012,14 @@ void ppc_mtfsb0dot() {
|
|||
ppc_fp_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_mtfsb1() {
|
||||
void dppc_interpreter::ppc_mtfsb1() {
|
||||
crf_d = (ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)) {
|
||||
ppc_state.fpscr |= (1 << crf_d);
|
||||
}
|
||||
}
|
||||
|
||||
void ppc_mtfsb1dot() {
|
||||
void dppc_interpreter::ppc_mtfsb1dot() {
|
||||
crf_d = ~(ppc_cur_instruction >> 21) & 0x31;
|
||||
if ((crf_d == 0) || (crf_d > 2)) {
|
||||
ppc_state.fpscr |= (1 << crf_d);
|
||||
|
@ -1283,7 +1027,7 @@ void ppc_mtfsb1dot() {
|
|||
ppc_fp_changecrf1();
|
||||
}
|
||||
|
||||
void ppc_mcrfs() {
|
||||
void dppc_interpreter::ppc_mcrfs() {
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
crf_d = crf_d << 2;
|
||||
crf_s = (ppc_cur_instruction >> 18) & 7;
|
||||
|
@ -1294,7 +1038,7 @@ void ppc_mcrfs() {
|
|||
|
||||
// Floating Point Comparisons
|
||||
|
||||
void ppc_fcmpo() {
|
||||
void dppc_interpreter::ppc_fcmpo() {
|
||||
ppc_grab_regsfpsab(true);
|
||||
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
|
@ -1328,7 +1072,7 @@ void ppc_fcmpo() {
|
|||
}
|
||||
}
|
||||
|
||||
void ppc_fcmpu() {
|
||||
void dppc_interpreter::ppc_fcmpu() {
|
||||
ppc_grab_regsfpsab(true);
|
||||
|
||||
crf_d = (ppc_cur_instruction >> 23) & 7;
|
||||
|
|
|
@ -48,13 +48,15 @@ PPC_BAT_entry ibat_array[4] = {{0}};
|
|||
PPC_BAT_entry dbat_array[4] = {{0}};
|
||||
|
||||
/** remember recently used physical memory regions for quicker translation. */
|
||||
AddressMapEntry last_read_area = {0};
|
||||
AddressMapEntry last_write_area = {0};
|
||||
AddressMapEntry last_exec_area = {0};
|
||||
AddressMapEntry last_ptab_area = {0};
|
||||
AddressMapEntry last_dma_area = {0};
|
||||
AddressMapEntry last_read_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
AddressMapEntry last_write_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
AddressMapEntry last_exec_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
AddressMapEntry last_ptab_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
AddressMapEntry last_dma_area = {0xFFFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
|
||||
#define WRITE_BYTE(addr, val) (*(addr) = val)
|
||||
|
||||
/* macro for generating code reading from physical memory */
|
||||
#define READ_PHYS_MEM(ENTRY, ADDR, OP, SIZE, UNVAL) \
|
||||
{ \
|
||||
|
@ -371,13 +373,32 @@ static uint32_t ppc_mmu_addr_translate(uint32_t la, int is_write) {
|
|||
}
|
||||
|
||||
static void mem_write_unaligned(uint32_t addr, uint32_t value, uint32_t size) {
|
||||
#ifdef MMU_DEBUG
|
||||
LOG_F(WARNING, "Attempt to write unaligned %d bytes to 0x%08X\n", size, addr);
|
||||
#endif
|
||||
|
||||
if (((addr & 0xFFF) + size) > 0x1000) {
|
||||
LOG_F(ERROR, "SOS! Cross-page unaligned write, addr=%08X, size=%d\n", addr, size);
|
||||
exit(-1); // FIXME!
|
||||
// Special case: unaligned cross-page writes
|
||||
LOG_F(WARNING, "Cross-page unaligned write, addr=%08X, size=%d\n",
|
||||
addr, size);
|
||||
|
||||
uint32_t phys_addr;
|
||||
uint32_t shift = (size - 1) * 8;
|
||||
|
||||
// Break misaligned memory accesses into multiple, smaller accesses
|
||||
// and retranslate on page boundary.
|
||||
// Because such accesses suffer a performance penalty, they will be
|
||||
// presumably very rare so don't care much about performance.
|
||||
for (int i = 0; i < size; shift -= 8, addr++, phys_addr++, i++) {
|
||||
if ((ppc_state.msr & 0x10) && (!i || !(addr & 0xFFF))) {
|
||||
phys_addr = ppc_mmu_addr_translate(addr, 0);
|
||||
}
|
||||
|
||||
WRITE_PHYS_MEM(last_write_area, phys_addr, WRITE_BYTE,
|
||||
(value >> shift) & 0xFF, 1);
|
||||
}
|
||||
} else {
|
||||
/* data address translation if enabled */
|
||||
// data address translation if enabled
|
||||
if (ppc_state.msr & 0x10) {
|
||||
addr = ppc_mmu_addr_translate(addr, 0);
|
||||
}
|
||||
|
@ -396,8 +417,6 @@ void mem_write_byte(uint32_t addr, uint8_t value) {
|
|||
addr = ppc_mmu_addr_translate(addr, 1);
|
||||
}
|
||||
|
||||
#define WRITE_BYTE(addr, val) (*(addr) = val)
|
||||
|
||||
WRITE_PHYS_MEM(last_write_area, addr, WRITE_BYTE, value, 1);
|
||||
}
|
||||
|
||||
|
@ -444,11 +463,32 @@ void mem_write_qword(uint32_t addr, uint64_t value) {
|
|||
static uint32_t mem_grab_unaligned(uint32_t addr, uint32_t size) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
#ifdef MMU_DEBUG
|
||||
LOG_F(WARNING, "Attempt to read unaligned %d bytes from 0x%08X\n", size, addr);
|
||||
#endif
|
||||
|
||||
if (((addr & 0xFFF) + size) > 0x1000) {
|
||||
LOG_F(ERROR, "SOS! Cross-page unaligned read, addr=%08X, size=%d\n", addr, size);
|
||||
exit(-1); // FIXME!
|
||||
// Special case: misaligned cross-page reads
|
||||
LOG_F(WARNING, "Cross-page unaligned read, addr=%08X, size=%d\n",
|
||||
addr, size);
|
||||
|
||||
uint32_t phys_addr;
|
||||
uint32_t res = 0;
|
||||
|
||||
// Break misaligned memory accesses into multiple, smaller accesses
|
||||
// and retranslate on page boundary.
|
||||
// Because such accesses suffer a performance penalty, they will be
|
||||
// presumably very rare so don't care much about performance.
|
||||
for (int i = 0; i < size; addr++, phys_addr++, i++) {
|
||||
if ((ppc_state.msr & 0x10) && (!i || !(addr & 0xFFF))) {
|
||||
phys_addr = ppc_mmu_addr_translate(addr, 0);
|
||||
}
|
||||
|
||||
READ_PHYS_MEM(last_read_area, phys_addr, *, 1, 0xFFU);
|
||||
res = (res << 8) | ret;
|
||||
}
|
||||
return res;
|
||||
|
||||
} else {
|
||||
/* data address translation if enabled */
|
||||
if (ppc_state.msr & 0x10) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -142,6 +142,8 @@ static void read_test_data() {
|
|||
}
|
||||
|
||||
int main() {
|
||||
initialize_ppc_opcode_tables(); //kludge
|
||||
|
||||
cout << "Running DingusPPC emulator tests..." << endl << endl;
|
||||
|
||||
ntested = 0;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
include_directories("${PROJECT_SOURCE_DIR}")
|
||||
include_directories("${PROJECT_SOURCE_DIR}"
|
||||
"${PROJECT_SOURCE_DIR}/thirdparty/capstone/include")
|
||||
|
||||
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||
|
||||
add_library(debugger OBJECT ${SOURCES})
|
||||
add_library(debugger OBJECT ${SOURCES})
|
||||
|
|
|
@ -19,9 +19,6 @@ You should have received a copy of the GNU General Public License
|
|||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../cpu/ppc/ppcdisasm.h"
|
||||
#include "../cpu/ppc/ppcemu.h"
|
||||
#include "../cpu/ppc/ppcmmu.h"
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
@ -30,7 +27,13 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include "../cpu/ppc/ppcdisasm.h"
|
||||
#include "../cpu/ppc/ppcemu.h"
|
||||
#include "../cpu/ppc/ppcmmu.h"
|
||||
|
||||
#ifdef ENABLE_68K_DEBUGGER // optionally defined in CMakeLists.txt
|
||||
#include <capstone/capstone.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -71,23 +74,153 @@ static void show_help() {
|
|||
cout << " disas N,X -- disassemble N instructions starting at address X" << endl;
|
||||
cout << " X can be any number or a known register name" << endl;
|
||||
cout << " disas with no arguments defaults to disas 1,pc" << endl;
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
cout << " context X -- switch to the debugging context X." << endl;
|
||||
cout << " X can be either 'ppc' (default) or '68k'" << endl;
|
||||
cout << " Use 68k for debugging emulated 68k code only." << endl;
|
||||
#endif
|
||||
cout << " quit -- quit the debugger" << endl << endl;
|
||||
cout << "Pressing ENTER will repeat last command." << endl;
|
||||
}
|
||||
|
||||
static void disasm(uint32_t count, uint32_t address) {
|
||||
PPCDisasmContext ctx;
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
|
||||
ctx.instr_addr = address;
|
||||
ctx.simplified = true;
|
||||
static void disasm_68k(uint32_t count, uint32_t address) {
|
||||
csh cs_handle;
|
||||
uint8_t code[10];
|
||||
size_t code_size;
|
||||
uint64_t dis_addr;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ctx.instr_code = mem_read_dbg(ctx.instr_addr, 4);
|
||||
cout << uppercase << hex << ctx.instr_addr;
|
||||
cout << " " << disassemble_single(&ctx) << endl;
|
||||
if (cs_open(CS_ARCH_M68K, CS_MODE_M68K_040, &cs_handle) != CS_ERR_OK) {
|
||||
cout << "Capstone initialization error" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
cs_insn* insn = cs_malloc(cs_handle);
|
||||
|
||||
for (; count > 0; count--) {
|
||||
/* prefetch opcode bytes (a 68k instruction can occupy 2...10 bytes) */
|
||||
for (int i = 0; i < sizeof(code); i++) {
|
||||
code[i] = mem_read_dbg(address + i, 1);
|
||||
}
|
||||
|
||||
const uint8_t *code_ptr = code;
|
||||
code_size = sizeof(code);
|
||||
dis_addr = address;
|
||||
|
||||
if (cs_disasm_iter(cs_handle, &code_ptr, &code_size, &dis_addr, insn)) {
|
||||
cout << uppercase << hex << insn->address << " ";
|
||||
cout << setfill(' ');
|
||||
cout << setw(10) << left << insn->mnemonic << insn->op_str << endl;
|
||||
address = dis_addr;
|
||||
} else {
|
||||
cout << "DS.W " << hex << ((code[0] << 8) | code[1]) << endl;
|
||||
address += 2;
|
||||
}
|
||||
}
|
||||
|
||||
cs_free(insn, 1);
|
||||
cs_close(&cs_handle);
|
||||
}
|
||||
|
||||
/* emulator opcode table size --> 512 KB */
|
||||
#define EMU_68K_TABLE_SIZE 0x80000
|
||||
|
||||
/** Execute one emulated 68k instruction. */
|
||||
void exec_single_68k()
|
||||
{
|
||||
string reg;
|
||||
uint32_t emu_table_virt, cur_68k_pc, cur_instr_tab_entry, ppc_pc;
|
||||
|
||||
/* PPC r24 contains 68k PC advanced by two bytes
|
||||
as part of instruction prefetching */
|
||||
reg = "R24";
|
||||
cur_68k_pc = get_reg(reg) - 2;
|
||||
|
||||
/* PPC r29 contains base address of the emulator opcode table */
|
||||
reg = "R29";
|
||||
emu_table_virt = get_reg(reg) & 0xFFF80000;
|
||||
|
||||
/* calculate address of the current opcode table entry as follows:
|
||||
get_word(68k_PC) * entry_size + table_base */
|
||||
cur_instr_tab_entry = mem_grab_word(cur_68k_pc) * 8 + emu_table_virt;
|
||||
|
||||
/* grab the PPC PC too */
|
||||
reg = "PC";
|
||||
ppc_pc = get_reg(reg);
|
||||
|
||||
//printf("cur_instr_tab_entry = %X\n", cur_instr_tab_entry);
|
||||
|
||||
/* because the first two PPC instructions for each emulated 68k once
|
||||
are resided in the emulator opcode table, we need to execute them
|
||||
one by one until the execution goes outside the opcode table. */
|
||||
while (ppc_pc >= cur_instr_tab_entry && ppc_pc < cur_instr_tab_entry + 8) {
|
||||
ppc_exec_single();
|
||||
reg = "PC";
|
||||
ppc_pc = get_reg(reg);
|
||||
LOG_F(9, "Tracing within emulator table, PC = %X\n", ppc_pc);
|
||||
}
|
||||
|
||||
/* Getting here means we're outside the emualtor opcode table.
|
||||
Execute PPC code until we hit the opcode table again. */
|
||||
LOG_F(9, "Tracing outside the emulator table, PC = %X\n", ppc_pc);
|
||||
ppc_exec_dbg(emu_table_virt, EMU_68K_TABLE_SIZE - 1);
|
||||
}
|
||||
|
||||
/** Execute emulated 68k code until target_addr is reached. */
|
||||
void exec_until_68k(uint32_t target_addr)
|
||||
{
|
||||
string reg;
|
||||
uint32_t emu_table_virt, ppc_pc;
|
||||
|
||||
reg = "R29";
|
||||
emu_table_virt = get_reg(reg) & 0xFFF80000;
|
||||
|
||||
reg = "R24";
|
||||
while (target_addr != (get_reg(reg) - 2)) {
|
||||
reg = "PC";
|
||||
ppc_pc = get_reg(reg);
|
||||
|
||||
if (ppc_pc >= emu_table_virt && ppc_pc < (emu_table_virt + EMU_68K_TABLE_SIZE - 1)) {
|
||||
LOG_F(9, "Tracing within emulator table, PC = %X\n", ppc_pc);
|
||||
ppc_exec_single();
|
||||
} else {
|
||||
LOG_F(9, "Tracing outside the emulator table, PC = %X\n", ppc_pc);
|
||||
ppc_exec_dbg(emu_table_virt, EMU_68K_TABLE_SIZE - 1);
|
||||
}
|
||||
reg = "R24";
|
||||
}
|
||||
}
|
||||
|
||||
void print_68k_regs()
|
||||
{
|
||||
int i;
|
||||
string reg;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
reg = "R" + to_string(i + 8);
|
||||
cout << "D" << dec << i << " : " << uppercase << hex << get_reg(reg) << endl;
|
||||
}
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
reg = "R" + to_string(i + 16);
|
||||
cout << "A" << dec << i << " : " << uppercase << hex << get_reg(reg) << endl;
|
||||
}
|
||||
reg = "R1";
|
||||
cout << "A7 : " << uppercase << hex << get_reg(reg) << endl;
|
||||
|
||||
reg = "R24";
|
||||
cout << "PC: " << uppercase << hex << get_reg(reg) - 2 << endl;
|
||||
|
||||
reg = "R25";
|
||||
cout << "SR: " << uppercase << hex << ((get_reg(reg) & 0xFF) << 8) << endl;
|
||||
|
||||
reg = "R26";
|
||||
cout << "CCR: " << uppercase << hex << get_reg(reg) << endl;
|
||||
}
|
||||
|
||||
#endif // ENABLE_68K_DEBUGGER
|
||||
|
||||
static void dump_mem(string& params) {
|
||||
int cell_size, chars_per_line;
|
||||
bool is_char;
|
||||
|
@ -169,7 +302,8 @@ static void dump_mem(string& params) {
|
|||
cout << (char)val;
|
||||
chars_per_line += cell_size;
|
||||
} else {
|
||||
cout << setw(cell_size * 2) << setfill('0') << uppercase << hex << val << " ";
|
||||
cout << setw(cell_size * 2) << setfill('0') << right;
|
||||
cout << uppercase << hex << val << " ";
|
||||
chars_per_line += cell_size * 2 + 2;
|
||||
}
|
||||
}
|
||||
|
@ -181,18 +315,33 @@ static void dump_mem(string& params) {
|
|||
cout << endl << endl;
|
||||
}
|
||||
|
||||
static void disasm(uint32_t count, uint32_t address) {
|
||||
PPCDisasmContext ctx;
|
||||
|
||||
ctx.instr_addr = address;
|
||||
ctx.simplified = true;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ctx.instr_code = mem_read_dbg(ctx.instr_addr, 4);
|
||||
cout << uppercase << hex << ctx.instr_addr;
|
||||
cout << " " << disassemble_single(&ctx) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void enter_debugger() {
|
||||
string inp, cmd, addr_str, expr_str, reg_expr, last_cmd, reg_value_str, inst_string, inst_num_str;
|
||||
uint32_t addr, inst_grab;
|
||||
std::stringstream ss;
|
||||
int log_level;
|
||||
int log_level, context;
|
||||
size_t separator_pos;
|
||||
|
||||
context = 1; /* start with the PowerPC context */
|
||||
|
||||
cout << "Welcome to the DingusPPC command line debugger." << endl;
|
||||
cout << "Please enter a command or 'help'." << endl << endl;
|
||||
|
||||
while (1) {
|
||||
cout << "ppcdbg> ";
|
||||
cout << "dingusdbg> ";
|
||||
|
||||
/* reset string stream */
|
||||
ss.str("");
|
||||
|
@ -220,7 +369,13 @@ void enter_debugger() {
|
|||
}
|
||||
#endif
|
||||
else if (cmd == "regs") {
|
||||
print_gprs();
|
||||
if (context == 2) {
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
print_68k_regs();
|
||||
#endif
|
||||
} else {
|
||||
print_gprs();
|
||||
}
|
||||
} else if (cmd == "set") {
|
||||
ss >> expr_str;
|
||||
|
||||
|
@ -248,7 +403,13 @@ void enter_debugger() {
|
|||
cout << exc.what() << endl;
|
||||
}
|
||||
} else if (cmd == "step" || cmd == "si") {
|
||||
ppc_exec_single();
|
||||
if (context == 2) {
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
exec_single_68k();
|
||||
#endif
|
||||
} else {
|
||||
ppc_exec_single();
|
||||
}
|
||||
} else if (cmd == "next" || cmd == "ni") {
|
||||
addr_str = "PC";
|
||||
addr = get_reg(addr_str) + 4;
|
||||
|
@ -257,7 +418,13 @@ void enter_debugger() {
|
|||
ss >> addr_str;
|
||||
try {
|
||||
addr = str2addr(addr_str);
|
||||
ppc_exec_until(addr);
|
||||
if (context == 2) {
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
exec_until_68k(addr);
|
||||
#endif
|
||||
} else {
|
||||
ppc_exec_until(addr);
|
||||
}
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
}
|
||||
|
@ -278,27 +445,58 @@ void enter_debugger() {
|
|||
} catch (invalid_argument& exc) {
|
||||
try {
|
||||
/* number conversion failed, trying reg name */
|
||||
addr = get_reg(addr_str);
|
||||
if (context == 2 && (addr_str == "pc" || addr_str == "PC")) {
|
||||
addr_str = "R24";
|
||||
addr = get_reg(addr_str) - 2;
|
||||
} else {
|
||||
addr = get_reg(addr_str);
|
||||
}
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
disasm(inst_grab, addr);
|
||||
if (context == 2) {
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
disasm_68k(inst_grab, addr);
|
||||
#endif
|
||||
} else {
|
||||
disasm(inst_grab, addr);
|
||||
}
|
||||
} catch (invalid_argument& exc) {
|
||||
cout << exc.what() << endl;
|
||||
}
|
||||
} else {
|
||||
/* disas without arguments defaults to disas 1,pc */
|
||||
addr_str = "PC";
|
||||
addr = get_reg(addr_str);
|
||||
disasm(1, addr);
|
||||
if (context == 2) {
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
addr_str = "R24";
|
||||
addr = get_reg(addr_str);
|
||||
disasm_68k(1, addr - 2);
|
||||
#endif
|
||||
} else {
|
||||
addr_str = "PC";
|
||||
addr = get_reg(addr_str);
|
||||
disasm(1, addr);
|
||||
}
|
||||
}
|
||||
} else if (cmd == "dump") {
|
||||
expr_str = "";
|
||||
ss >> expr_str;
|
||||
dump_mem(expr_str);
|
||||
#ifdef ENABLE_68K_DEBUGGER
|
||||
} else if (cmd == "context") {
|
||||
expr_str = "";
|
||||
ss >> expr_str;
|
||||
if (expr_str == "ppc" || expr_str == "PPC") {
|
||||
context = 1;
|
||||
} else if (expr_str == "68k" || expr_str == "68K") {
|
||||
context = 2;
|
||||
} else {
|
||||
cout << "Unknown debugging context: " << expr_str << endl;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
cout << "Unknown command: " << cmd << endl;
|
||||
continue;
|
||||
|
|
|
@ -135,13 +135,13 @@ private:
|
|||
0x00 // unknown defaults
|
||||
};
|
||||
|
||||
uint32_t int_mask2;
|
||||
uint32_t int_clear2;
|
||||
uint32_t int_levels2;
|
||||
uint32_t int_mask1;
|
||||
uint32_t int_clear1;
|
||||
uint32_t int_levels1;
|
||||
uint32_t feat_ctrl; // features control register
|
||||
uint32_t int_mask2 = 0;
|
||||
uint32_t int_clear2 = 0;
|
||||
uint32_t int_levels2 = 0;
|
||||
uint32_t int_mask1 = 0;
|
||||
uint32_t int_clear1 = 0;
|
||||
uint32_t int_levels1 = 0;
|
||||
uint32_t feat_ctrl = 0; // features control register
|
||||
|
||||
/* device cells */
|
||||
ViaCuda* viacuda; /* VIA cell with Cuda MCU attached to it */
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
include_directories("${PROJECT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||
|
||||
add_library(execution OBJECT ${SOURCES})
|
||||
target_link_libraries(execution PRIVATE cubeb)
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-20 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
#include <cinttypes>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <interpreter_loop.h>
|
||||
#include <thirdparty/loguru/loguru.hpp>
|
||||
#include <cpu/ppc/ppcemu.h>
|
||||
|
||||
std::chrono::high_resolution_clock::time_point global; // global timer
|
||||
std::chrono::high_resolution_clock::time_point cuda_timer; // updates every 11 ms
|
||||
std::chrono::high_resolution_clock::time_point disp_timer; // updates every 16 ms
|
||||
|
||||
using namespace std;
|
||||
|
||||
const uint64_t cuda_update = 11000;
|
||||
const uint64_t display_update = 16667;
|
||||
|
||||
bool cuda_priority = 0;
|
||||
bool disp_priority = 0;
|
||||
|
||||
uint64_t elapsed_times[3] = {0}; // Elapsed time to reach a cycle (for display)
|
||||
uint64_t routine_bench[3] = {0}; // Estimated time (in microseconds) to cycle through functions
|
||||
uint64_t routine_runtime[3] = {0, cuda_update, display_update}; // Time to elapse before execution
|
||||
|
||||
enum general_routine_timepoint { OVERALL_UPDATE_TIME, CUDA_UPDATE_TIME, DISPLAY_UPDATE_TIME };
|
||||
|
||||
void round_robin_bench() {
|
||||
// Benchmark how much time elapses during a minimal CPU block
|
||||
|
||||
std::chrono::high_resolution_clock::time_point dummy = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
dppc_interpreter::ppc_ori(); //execute NOPs as a basic test
|
||||
}
|
||||
|
||||
std::chrono::high_resolution_clock::time_point dummy2 = std::chrono::high_resolution_clock::now();
|
||||
routine_bench[OVERALL_UPDATE_TIME] =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(dummy2 - dummy).count();
|
||||
std::cout << "Initial test: " << routine_bench[OVERALL_UPDATE_TIME] << endl;
|
||||
}
|
||||
|
||||
void interpreter_update_counters() {
|
||||
std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
|
||||
elapsed_times[OVERALL_UPDATE_TIME] =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end - global).count();
|
||||
elapsed_times[CUDA_UPDATE_TIME] =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end - cuda_timer).count();
|
||||
elapsed_times[DISPLAY_UPDATE_TIME] =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end - disp_timer).count();
|
||||
|
||||
// Calculate if the threshold for updating a time-critical section has reached or is about to be reached
|
||||
if ((elapsed_times[CUDA_UPDATE_TIME] + routine_bench[OVERALL_UPDATE_TIME]) >=
|
||||
routine_runtime[CUDA_UPDATE_TIME]) {
|
||||
cuda_priority = true;
|
||||
elapsed_times[CUDA_UPDATE_TIME] = 0;
|
||||
cuda_timer = end;
|
||||
}
|
||||
|
||||
if ((elapsed_times[DISPLAY_UPDATE_TIME] + routine_bench[OVERALL_UPDATE_TIME]) >=
|
||||
routine_runtime[DISPLAY_UPDATE_TIME]) {
|
||||
disp_priority = true;
|
||||
elapsed_times[DISPLAY_UPDATE_TIME] = 0;
|
||||
disp_timer = end;
|
||||
}
|
||||
}
|
||||
|
||||
void interpreter_main_loop() {
|
||||
// Round robin algorithm goes here
|
||||
round_robin_bench();
|
||||
|
||||
global = std::chrono::high_resolution_clock::now();
|
||||
cuda_timer = global;
|
||||
disp_timer = global;
|
||||
|
||||
for (;;) {
|
||||
if (cuda_priority) {
|
||||
LOG_F(9, "Placeholder for Cuda Update function!\n");
|
||||
cuda_priority = false;
|
||||
}
|
||||
|
||||
if (disp_priority) {
|
||||
LOG_F(9, "Placeholder for Display Update function! \n");
|
||||
disp_priority = false;
|
||||
}
|
||||
|
||||
ppc_exec();
|
||||
|
||||
interpreter_update_counters();
|
||||
}
|
||||
}
|
|
@ -1,46 +1,23 @@
|
|||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-20 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// The uniquely Gekko opcodes for the processor - ppcgekkoopcodes.cpp
|
||||
|
||||
#include "ppcemu.h"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
void ppc_psq_l() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_lu() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_st() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void ppc_psq_stu() {
|
||||
printf("Hello. There's no GameCube emulation...yet. Goodbye.");
|
||||
exit(0);
|
||||
}
|
||||
/*
|
||||
DingusPPC - The Experimental PowerPC Macintosh emulator
|
||||
Copyright (C) 2018-20 divingkatae and maximum
|
||||
(theweirdo) spatium
|
||||
|
||||
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
void interpreter_update_counters();
|
||||
void interpreter_main_loop();
|
5
main.cpp
5
main.cpp
|
@ -23,6 +23,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||
// This is where the magic begins
|
||||
|
||||
#include "debugger/debugger.h"
|
||||
#include "execution/interpreter_loop.h"
|
||||
#include "machines/machinefactory.h"
|
||||
#include "machines/machineproperties.h"
|
||||
#include "ppcemu.h"
|
||||
|
@ -165,9 +166,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
switch (execution_mode) {
|
||||
case 0:
|
||||
for (;;) {
|
||||
ppc_exec();
|
||||
}
|
||||
interpreter_main_loop();
|
||||
break;
|
||||
case 1:
|
||||
enter_debugger();
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit bfb2e45d76dd3dda08b40dfad6da94db01bd27ad
|
Loading…
Reference in New Issue