Merge branch 'ppc-tests' into 'master'.

This commit is contained in:
Maxim Poliakovski 2020-02-11 01:20:55 +01:00
commit d6d85a750f
12 changed files with 12112 additions and 378 deletions

View File

@ -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
View 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": []
}
]
}

View File

@ -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
View File

@ -0,0 +1,5 @@
include_directories("${PROJECT_SOURCE_DIR}")
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
add_library(cpu_ppc OBJECT ${SOURCES})

View File

@ -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();

View File

@ -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
View 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

File diff suppressed because it is too large Load Diff

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
View 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
View File

@ -0,0 +1,5 @@
include_directories("${PROJECT_SOURCE_DIR}")
file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
add_library(devices OBJECT ${SOURCES})