mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-23 06:31:28 +00:00
Merge branch 'ppc-tests' into 'master'.
This commit is contained in:
commit
d6d85a750f
@ -6,13 +6,26 @@ set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/cpu/ppc/")
|
||||
add_subdirectory("${PROJECT_SOURCE_DIR}/devices/")
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}" "${PROJECT_SOURCE_DIR}/devices"
|
||||
"${PROJECT_SOURCE_DIR}/debugger"
|
||||
"${PROJECT_SOURCE_DIR}/cpu/ppc")
|
||||
"${PROJECT_SOURCE_DIR}/cpu/ppc"
|
||||
"${PROJECT_SOURCE_DIR}/debugger")
|
||||
|
||||
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/*.cpp" "${PROJECT_SOURCE_DIR}/devices/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/debugger/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/cpu/ppc/*.cpp")
|
||||
file(GLOB SOURCES "${PROJECT_SOURCE_DIR}/*.cpp"
|
||||
"${PROJECT_SOURCE_DIR}/debugger/*.cpp")
|
||||
|
||||
file(GLOB TEST_SOURCES "${PROJECT_SOURCE_DIR}/cpu/ppc/test/*.cpp")
|
||||
|
||||
add_executable(dingusppc ${SOURCES} $<TARGET_OBJECTS:cpu_ppc> $<TARGET_OBJECTS:devices>)
|
||||
|
||||
add_executable(testppc ${TEST_SOURCES} $<TARGET_OBJECTS:cpu_ppc> $<TARGET_OBJECTS:devices>)
|
||||
|
||||
add_custom_command(
|
||||
TARGET testppc POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
"${PROJECT_SOURCE_DIR}/cpu/ppc/test/ppcinttests.csv"
|
||||
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
|
||||
|
||||
add_executable(dingusppc ${SOURCES})
|
||||
install (TARGETS dingusppc DESTINATION ${EXECUTABLE_OUTPUT_PATH})
|
||||
|
28
CMakeSettings.json
Normal file
28
CMakeSettings.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "clang_cl_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": []
|
||||
},
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": []
|
||||
}
|
||||
]
|
||||
}
|
13
README.md
13
README.md
@ -35,7 +35,7 @@ the following commands in the OS terminal:
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make
|
||||
make dingusppc
|
||||
```
|
||||
You may specify another build type using the variable CMAKE_BUILD_TYPE.
|
||||
|
||||
@ -43,6 +43,17 @@ Due to the incomplete status of the program at this time, no additional librarie
|
||||
|
||||
Future versions will include SDL 2 as a requirement.
|
||||
|
||||
## Testing
|
||||
|
||||
DingusPPC includes a test suite for verifying the correctness of its PowerPC CPU
|
||||
emulation. To build the tests, use the following terminal commands:
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
make testppc
|
||||
```
|
||||
|
||||
## Intended Minimum Requirements
|
||||
|
||||
- Windows 7 or newer (64-bit), Linux 4.4 or newer, Mac OS X 10.9 or newer (64-bit)
|
||||
|
5
cpu/ppc/CMakeLists.txt
Normal file
5
cpu/ppc/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
include_directories("${PROJECT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||
|
||||
add_library(cpu_ppc OBJECT ${SOURCES})
|
@ -137,13 +137,9 @@ extern uint64_t timebase_counter; //used for storing time base value
|
||||
|
||||
//Additional steps to prevent overflow?
|
||||
extern int32_t add_result;
|
||||
extern int32_t sidiv_result;
|
||||
extern int32_t simult_result;
|
||||
extern uint32_t uiadd_result;
|
||||
extern uint32_t uidiv_result;
|
||||
extern uint32_t uimult_result;
|
||||
extern uint64_t uiproduct;
|
||||
extern int64_t siproduct;
|
||||
|
||||
extern int32_t word_copy_location;
|
||||
extern uint32_t strwrd_replace_value;
|
||||
@ -164,7 +160,6 @@ extern uint32_t rot_sh;
|
||||
extern uint32_t rot_mb;
|
||||
extern uint32_t rot_me;
|
||||
extern uint32_t uimm;
|
||||
extern uint32_t not_this;
|
||||
extern uint32_t grab_sr;
|
||||
extern uint32_t grab_inb; //This is for grabbing the number of immediate bytes for loading and storing
|
||||
extern uint32_t ppc_to;
|
||||
@ -276,8 +271,6 @@ extern void ppc_store_result_rega();
|
||||
extern void ppc_store_sfpresult(bool int_rep);
|
||||
extern void ppc_store_dfpresult(bool int_rep);
|
||||
|
||||
void ppc_carry(uint32_t a, uint32_t b);
|
||||
void ppc_setsoov(uint32_t a, uint32_t b);
|
||||
void ppc_changecrf0(uint32_t set_result);
|
||||
void ppc_fp_changecrf1();
|
||||
|
||||
@ -415,10 +408,16 @@ 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();
|
||||
|
@ -118,14 +118,16 @@ static std::unordered_map<uint16_t, PPCOpcode> SubOpcode31Grabber = {
|
||||
{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}, {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},
|
||||
{1428, &ppc_addzeo}, {1429, &ppc_addzeodot}, {1450, &ppc_stswi},
|
||||
{1454, &ppc_stfdx}, {1456, &power_srlq}, {1457, &power_srlqdot},
|
||||
{1458, &power_sreq}, {1459, &power_sreqdot}, {1492, &ppc_addmeo},
|
||||
{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},
|
||||
|
File diff suppressed because it is too large
Load Diff
312
cpu/ppc/test/genppctests.py
Normal file
312
cpu/ppc/test/genppctests.py
Normal file
@ -0,0 +1,312 @@
|
||||
def gen_ppc_opcode(opc_str, imm):
|
||||
if opc_str == "ADD":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x10A << 1)
|
||||
elif opc_str == "ADD.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x10A << 1) + 1
|
||||
elif opc_str == "ADDC":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0xA << 1)
|
||||
elif opc_str == "ADDC.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0xA << 1) + 1
|
||||
elif opc_str == "ADDCO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x20A << 1)
|
||||
elif opc_str == "ADDCO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x20A << 1) + 1
|
||||
elif opc_str == "ADDO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x30A << 1)
|
||||
elif opc_str == "ADDO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x30A << 1) + 1
|
||||
elif opc_str == "ADDE":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x8A << 1)
|
||||
elif opc_str == "ADDE.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x8A << 1) + 1
|
||||
elif opc_str == "ADDEO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x28A << 1)
|
||||
elif opc_str == "ADDEO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x28A << 1) + 1
|
||||
elif opc_str == "ADDI":
|
||||
return (0x0E << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "ADDIC":
|
||||
return (0x0C << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "ADDIC.":
|
||||
return (0x0D << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "ADDIS":
|
||||
return (0x0F << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "ADDME":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xEA << 1)
|
||||
elif opc_str == "ADDME.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xEA << 1) + 1
|
||||
elif opc_str == "ADDMEO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2EA << 1)
|
||||
elif opc_str == "ADDMEO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2EA << 1) + 1
|
||||
elif opc_str == "ADDZE":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xCA << 1)
|
||||
elif opc_str == "ADDZE.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xCA << 1) + 1
|
||||
elif opc_str == "ADDZEO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2CA << 1)
|
||||
elif opc_str == "ADDZEO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2CA << 1) + 1
|
||||
elif opc_str == "AND":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1C << 1)
|
||||
elif opc_str == "AND.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1C << 1) + 1
|
||||
elif opc_str == "ANDC":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x3C << 1)
|
||||
elif opc_str == "ANDC.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x3C << 1) + 1
|
||||
elif opc_str == "ANDI.":
|
||||
return (0x1C << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "ANDIS.":
|
||||
return (0x1D << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "CMP":
|
||||
return (0x1F << 26) + (3 << 16) + (4 << 11)
|
||||
elif opc_str == "CMPI":
|
||||
return (0x0B << 26) + (0 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "CMPL":
|
||||
return (0x1F << 26) + (3 << 16) + (4 << 11) + (0x20 << 1)
|
||||
elif opc_str == "CMPLI":
|
||||
return (0x0A << 26) + (0 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "CNTLZW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x1A << 1)
|
||||
elif opc_str == "CNTLZW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x1A << 1) + 1
|
||||
elif opc_str == "DIVW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1EB << 1)
|
||||
elif opc_str == "DIVW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1EB << 1) + 1
|
||||
elif opc_str == "DIVWO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x3EB << 1)
|
||||
elif opc_str == "DIVWO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x3EB << 1) + 1
|
||||
elif opc_str == "DIVWU":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1CB << 1)
|
||||
elif opc_str == "DIVWU.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1CB << 1) + 1
|
||||
elif opc_str == "DIVWUO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x3CB << 1)
|
||||
elif opc_str == "DIVWUO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x3CB << 1) + 1
|
||||
elif opc_str == "EQV":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x11C << 1)
|
||||
elif opc_str == "EQV.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x11C << 1) + 1
|
||||
elif opc_str == "EXTSB":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x3BA << 1)
|
||||
elif opc_str == "EXTSB.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x3BA << 1) + 1
|
||||
elif opc_str == "EXTSH":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x39A << 1)
|
||||
elif opc_str == "EXTSH.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x39A << 1) + 1
|
||||
elif opc_str == "MULHW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x4B << 1)
|
||||
elif opc_str == "MULHW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x4B << 1) + 1
|
||||
elif opc_str == "MULHWU":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0xB << 1)
|
||||
elif opc_str == "MULHWU.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0xB << 1) + 1
|
||||
elif opc_str == "MULLI":
|
||||
return (0x07 << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "MULLW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0xEB << 1)
|
||||
elif opc_str == "MULLW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0xEB << 1) + 1
|
||||
elif opc_str == "MULLWO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x2EB << 1)
|
||||
elif opc_str == "MULLWO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x2EB << 1) + 1
|
||||
elif opc_str == "NAND":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1DC << 1)
|
||||
elif opc_str == "NAND.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1DC << 1) + 1
|
||||
elif opc_str == "NEG":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x68 << 1)
|
||||
elif opc_str == "NEG.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x68 << 1) + 1
|
||||
elif opc_str == "NEGO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x268 << 1)
|
||||
elif opc_str == "NEGO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x268 << 1) + 1
|
||||
elif opc_str == "NOR":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x7C << 1)
|
||||
elif opc_str == "NOR.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x7C << 1) + 1
|
||||
elif opc_str == "OR":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1BC << 1)
|
||||
elif opc_str == "OR.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x1BC << 1) + 1
|
||||
elif opc_str == "ORC":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x19C << 1)
|
||||
elif opc_str == "ORC.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x19C << 1) + 1
|
||||
elif opc_str == "ORI":
|
||||
return (0x18 << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "ORIS":
|
||||
return (0x19 << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "SLW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x18 << 1)
|
||||
elif opc_str == "SLW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x18 << 1) + 1
|
||||
elif opc_str == "SRAW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x318 << 1)
|
||||
elif opc_str == "SRAW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x318 << 1) + 1
|
||||
elif opc_str == "SRAWI":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + ((imm & 0x1F) << 11) + (0x338 << 1)
|
||||
elif opc_str == "SRAWI.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + ((imm & 0x1F) << 11) + (0x338 << 1) + 1
|
||||
elif opc_str == "SRW":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x218 << 1)
|
||||
elif opc_str == "SRW.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x218 << 1) + 1
|
||||
elif opc_str == "SUBF":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x28 << 1)
|
||||
elif opc_str == "SUBF.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x28 << 1) + 1
|
||||
elif opc_str == "SUBFO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x228 << 1)
|
||||
elif opc_str == "SUBFO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x228 << 1) + 1
|
||||
elif opc_str == "SUBFC":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x8 << 1)
|
||||
elif opc_str == "SUBFC.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x8 << 1) + 1
|
||||
elif opc_str == "SUBFCO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x208 << 1)
|
||||
elif opc_str == "SUBFCO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x208 << 1) + 1
|
||||
elif opc_str == "SUBFE":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x88 << 1)
|
||||
elif opc_str == "SUBFE.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x88 << 1) + 1
|
||||
elif opc_str == "SUBFEO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x288 << 1)
|
||||
elif opc_str == "SUBFEO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x288 << 1) + 1
|
||||
elif opc_str == "SUBFIC":
|
||||
return (0x08 << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "SUBFME":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xE8 << 1)
|
||||
elif opc_str == "SUBFME.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xE8 << 1) + 1
|
||||
elif opc_str == "SUBFMEO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2E8 << 1)
|
||||
elif opc_str == "SUBFMEO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2E8 << 1) + 1
|
||||
elif opc_str == "SUBFZE":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xC8 << 1)
|
||||
elif opc_str == "SUBFZE.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0xC8 << 1) + 1
|
||||
elif opc_str == "SUBFZEO":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2C8 << 1)
|
||||
elif opc_str == "SUBFZEO.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (0x2C8 << 1) + 1
|
||||
elif opc_str == "XOR":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x13C << 1)
|
||||
elif opc_str == "XOR.":
|
||||
return (0x1F << 26) + (3 << 21) + (3 << 16) + (4 << 11) + (0x13C << 1) + 1
|
||||
elif opc_str == "XORI":
|
||||
return (0x1A << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
elif opc_str == "XORIS":
|
||||
return (0x1B << 26) + (3 << 21) + (3 << 16) + (imm & 0xFFFF)
|
||||
|
||||
def gen_rot_opcode(opc_str, sh, mb, me):
|
||||
if opc_str == "RLWIMI":
|
||||
return (0x14 << 26) + (4 << 21) + (3 << 16) + (sh << 11) + (mb << 6) + (me << 1)
|
||||
elif opc_str == "RLWIMI.":
|
||||
return (0x14 << 26) + (4 << 21) + (3 << 16) + (sh << 11) + (mb << 6) + (me << 1) + 1
|
||||
elif opc_str == "RLWINM":
|
||||
return (0x15 << 26) + (4 << 21) + (3 << 16) + (sh << 11) + (mb << 6) + (me << 1)
|
||||
elif opc_str == "RLWINM.":
|
||||
return (0x15 << 26) + (4 << 21) + (3 << 16) + (sh << 11) + (mb << 6) + (me << 1) + 1
|
||||
|
||||
def extract_imm(line):
|
||||
pos = 12
|
||||
while pos < len(line):
|
||||
reg_id = line[pos:pos+4]
|
||||
if reg_id.startswith("rD") or reg_id.startswith("rA"):
|
||||
pos += 16
|
||||
elif reg_id.startswith("rB"):
|
||||
pos += 16
|
||||
elif reg_id.startswith("XER:"):
|
||||
pos += 18
|
||||
elif reg_id.startswith("CR:"):
|
||||
pos += 17
|
||||
elif reg_id.startswith("imm"):
|
||||
return int(line[pos+4:pos+14], base=16)
|
||||
return 0
|
||||
|
||||
def extract_rot_params(line):
|
||||
pos = 12
|
||||
sh = 0
|
||||
mb = 0
|
||||
me = 0
|
||||
while pos < len(line):
|
||||
reg_id = line[pos:pos+4]
|
||||
if reg_id.startswith("rD") or reg_id.startswith("rA") or reg_id.startswith("rB") or reg_id.startswith("rS"):
|
||||
pos += 16
|
||||
elif reg_id.startswith("XER:"):
|
||||
pos += 18
|
||||
elif reg_id.startswith("CR:"):
|
||||
pos += 17
|
||||
elif reg_id.startswith("SH"):
|
||||
sh = int(line[pos+3:pos+13], base=16)
|
||||
pos += 16
|
||||
elif reg_id.startswith("MB"):
|
||||
mb = int(line[pos+3:pos+13], base=16)
|
||||
pos += 16
|
||||
elif reg_id.startswith("ME"):
|
||||
me = int(line[pos+3:pos+13], base=16)
|
||||
pos += 16
|
||||
return (sh, mb, me)
|
||||
|
||||
|
||||
with open("ppcinttest.txt", "r") as in_file:
|
||||
with open("ppcinttests.csv", "w") as out_file:
|
||||
lineno = 0
|
||||
for line in in_file:
|
||||
lineno += 1
|
||||
|
||||
line = line.strip()
|
||||
opcode = (line[0:8]).rstrip().upper()
|
||||
out_file.write(opcode + ",")
|
||||
|
||||
if opcode.startswith("RLWI"):
|
||||
sh, mb, me = extract_rot_params(line)
|
||||
out_file.write("0x{:X}".format(gen_rot_opcode(opcode, sh, mb, me)))
|
||||
else:
|
||||
imm = extract_imm(line)
|
||||
out_file.write("0x{:X}".format(gen_ppc_opcode(opcode, imm)))
|
||||
|
||||
pos = 12
|
||||
|
||||
while pos < len(line):
|
||||
reg_id = line[pos:pos+4]
|
||||
if reg_id.startswith("rD"):
|
||||
out_file.write(",rD=" + line[pos+3:pos+13])
|
||||
pos += 16
|
||||
elif reg_id.startswith("rA"):
|
||||
out_file.write(",rA=" + line[pos+3:pos+13])
|
||||
pos += 16
|
||||
elif reg_id.startswith("rB") or reg_id.startswith("rS"):
|
||||
out_file.write(",rB=" + line[pos+3:pos+13])
|
||||
pos += 16
|
||||
elif reg_id.startswith("XER:"):
|
||||
out_file.write(",XER=" + line[pos+5:pos+15])
|
||||
pos += 18
|
||||
elif reg_id.startswith("CR:"):
|
||||
out_file.write(",CR=" + line[pos+4:pos+14])
|
||||
pos += 17
|
||||
elif reg_id.startswith("imm"):
|
||||
pos += 17 # ignore immediate operands
|
||||
elif reg_id.startswith("SH"):
|
||||
pos += 16
|
||||
elif reg_id.startswith("MB") or reg_id.startswith("ME"):
|
||||
pos += 16
|
||||
else:
|
||||
out_file.write("Unknown reg ID" + reg_id)
|
||||
break
|
||||
|
||||
out_file.write("\n")
|
5620
cpu/ppc/test/ppcinttest.txt
Executable file
5620
cpu/ppc/test/ppcinttest.txt
Executable file
File diff suppressed because it is too large
Load Diff
5620
cpu/ppc/test/ppcinttests.csv
Normal file
5620
cpu/ppc/test/ppcinttests.csv
Normal file
File diff suppressed because it is too large
Load Diff
171
cpu/ppc/test/ppctests.cpp
Normal file
171
cpu/ppc/test/ppctests.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "../ppcemu.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int ntested; /* number of tested instructions */
|
||||
int nfailed; /* number of failed instructions */
|
||||
|
||||
void xer_ov_test(string mnem, uint32_t opcode)
|
||||
{
|
||||
ppc_state.ppc_gpr[3] = 2;
|
||||
ppc_state.ppc_gpr[4] = 2;
|
||||
ppc_state.ppc_spr[SPR::XER] = 0xFFFFFFFF;
|
||||
ppc_cur_instruction = opcode;
|
||||
ppc_main_opcode();
|
||||
if (ppc_state.ppc_spr[SPR::XER] & 0x40000000UL) {
|
||||
cout << "Invalid " << mnem << " emulation! XER[OV] should not be set."
|
||||
<< endl;
|
||||
nfailed++;
|
||||
}
|
||||
ntested++;
|
||||
}
|
||||
|
||||
void xer_update_test()
|
||||
{
|
||||
xer_ov_test("ADDCO", 0x7C632414);
|
||||
xer_ov_test("ADDCO.", 0x7C632415);
|
||||
xer_ov_test("ADDO", 0x7C632614);
|
||||
xer_ov_test("ADDO.", 0x7C632615);
|
||||
xer_ov_test("ADDEO", 0x7C632514);
|
||||
xer_ov_test("ADDEO.", 0x7C632515);
|
||||
xer_ov_test("ADDMEO", 0x7C6305D4);
|
||||
xer_ov_test("ADDMEO.", 0x7C6305D5);
|
||||
xer_ov_test("ADDZEO", 0x7C630594);
|
||||
xer_ov_test("ADDZEO.", 0x7C630595);
|
||||
xer_ov_test("DIVWO", 0x7C6327D6);
|
||||
xer_ov_test("DIVWO.", 0x7C6327D7);
|
||||
xer_ov_test("DIVWUO", 0x7C632796);
|
||||
xer_ov_test("DIVWUO.", 0x7C632797);
|
||||
xer_ov_test("MULLWO", 0x7C6325D6);
|
||||
xer_ov_test("MULLWO.", 0x7C6325D7);
|
||||
xer_ov_test("NEGO", 0x7C6304D0);
|
||||
xer_ov_test("NEGO.", 0x7C6304D1);
|
||||
xer_ov_test("SUBFO", 0x7C632450);
|
||||
xer_ov_test("SUBFO.", 0x7C632451);
|
||||
xer_ov_test("SUBFCO", 0x7C632410);
|
||||
xer_ov_test("SUBFCO.", 0x7C632411);
|
||||
xer_ov_test("SUBFEO", 0x7C632510);
|
||||
xer_ov_test("SUBFEO.", 0x7C632511);
|
||||
xer_ov_test("SUBFMEO", 0x7C6305D0);
|
||||
xer_ov_test("SUBFMEO.", 0x7C6305D1);
|
||||
xer_ov_test("SUBFZEO", 0x7C630590);
|
||||
xer_ov_test("SUBFZEO.", 0x7C630591);
|
||||
}
|
||||
|
||||
/** testing vehicle */
|
||||
void read_test_data()
|
||||
{
|
||||
string line, token;
|
||||
int i, lineno;
|
||||
uint32_t opcode, dest, src1, src2, check_xer, check_cr;
|
||||
|
||||
ifstream tfstream("ppcinttests.csv");
|
||||
if (!tfstream.is_open()) {
|
||||
cout << "Could not open tests CSV file. Exiting..." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
lineno = 0;
|
||||
|
||||
while(getline(tfstream, line)) {
|
||||
lineno++;
|
||||
|
||||
if (line.empty() || !line.rfind("#", 0))
|
||||
continue; /* skip empty/comment lines */
|
||||
|
||||
istringstream lnstream(line);
|
||||
|
||||
vector<string> tokens;
|
||||
|
||||
while(getline(lnstream, token, ',' )) {
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
if (tokens.size() < 5) {
|
||||
cout << "Too few values in line " << lineno << ". Skipping..." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
opcode = stoul(tokens[1], NULL, 16);
|
||||
|
||||
dest = 0;
|
||||
src1 = 0;
|
||||
src2 = 0;
|
||||
check_xer = 0;
|
||||
check_cr = 0;
|
||||
|
||||
for (i = 2; i < tokens.size(); i++) {
|
||||
if (tokens[i].rfind("rD=", 0) == 0) {
|
||||
dest = stoul(tokens[i].substr(3), NULL, 16);
|
||||
} else if (tokens[i].rfind("rA=", 0) == 0) {
|
||||
src1 = stoul(tokens[i].substr(3), NULL, 16);
|
||||
} else if (tokens[i].rfind("rB=", 0) == 0) {
|
||||
src2 = stoul(tokens[i].substr(3), NULL, 16);
|
||||
} else if (tokens[i].rfind("XER=", 0) == 0) {
|
||||
check_xer = stoul(tokens[i].substr(4), NULL, 16);
|
||||
} else if (tokens[i].rfind("CR=", 0) == 0) {
|
||||
check_cr = stoul(tokens[i].substr(3), NULL, 16);
|
||||
} else {
|
||||
cout << "Unknown parameter " << tokens[i] << " in line " << lineno <<
|
||||
". Exiting..." << endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
ppc_state.ppc_gpr[3] = src1;
|
||||
ppc_state.ppc_gpr[4] = src2;
|
||||
ppc_state.ppc_spr[SPR::XER] = 0;
|
||||
ppc_state.ppc_cr = 0;
|
||||
|
||||
ppc_cur_instruction = opcode;
|
||||
|
||||
ppc_main_opcode();
|
||||
|
||||
ntested++;
|
||||
|
||||
if ((tokens[0].rfind("CMP") && (ppc_state.ppc_gpr[3] != dest)) ||
|
||||
(ppc_state.ppc_spr[SPR::XER] != check_xer) ||
|
||||
(ppc_state.ppc_cr != check_cr)) {
|
||||
cout << "Mismatch: instr=" << tokens[0] << ", src1=0x" << hex << src1
|
||||
<< ", src2=0x" << hex << src2 << endl;
|
||||
cout << "expected: dest=0x" << hex << dest << ", XER=0x" << hex
|
||||
<< check_xer << ", CR=0x" << hex << check_cr << endl;
|
||||
cout << "got: dest=0x" << hex << ppc_state.ppc_gpr[3] << ", XER=0x"
|
||||
<< hex << ppc_state.ppc_spr[SPR::XER] << ", CR=0x" << hex
|
||||
<< ppc_state.ppc_cr << endl;
|
||||
cout << "Test file line #: " << dec << lineno << endl << endl;
|
||||
|
||||
nfailed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int i;
|
||||
|
||||
cout << "Running DingusPPC emulator tests..." << endl << endl;
|
||||
|
||||
ntested = 0;
|
||||
nfailed = 0;
|
||||
|
||||
cout << "Testing XER[OV] updating..." << endl << endl;
|
||||
|
||||
xer_update_test();
|
||||
|
||||
cout << endl << "Testing integer instructions:" << endl;
|
||||
|
||||
read_test_data();
|
||||
|
||||
cout << "... completed." << endl;
|
||||
cout << "--> Tested instructions: " << dec << ntested << endl;
|
||||
cout << "--> Failed: " << dec << nfailed << endl;
|
||||
|
||||
return 0;
|
||||
}
|
5
devices/CMakeLists.txt
Normal file
5
devices/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
include_directories("${PROJECT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
|
||||
|
||||
add_library(devices OBJECT ${SOURCES})
|
Loading…
x
Reference in New Issue
Block a user