Repository navigation
test(recomp): per-instruction tests for R5900 general instructions - #283
Open
luisbraganca wants to merge 1 commit into
Open
luisbraganca wants to merge 1 commit into
luisbraganca wants to merge 1 commit into
Conversation
test(recomp): per-instruction tests for R5900 general instructions Add ps2xTest/src/r5900_general_instruction_tests.cpp: three ps2x_tests suites that cover every MipsOpcodes, SpecialFunctions and RegimmFunctions encoding (46 cases). Each case decodes a real instruction word, pins the C++ the recompiler emits for it, and then executes that same C++ against an R5900Context and guest RAM through ps2_runtime_macros.h, so a case fails both when the emission changes and when the emitted code misbehaves. Branches and jumps go through the function emitter and check the condition expression, delay-slot placement, link writes and dispatch kinds. Manifest cases walk all opcode and function codes and assert that exactly the EE-reserved encodings are rejected. Edge behaviour covered: integer-overflow traps (and that rd/rt is left untouched), MIPS division by zero and INT32_MIN / -1, sign and zero extension per load width, 64-bit versus 32-bit compares, shift-amount masking, LWL/LWR/LDL/LDR/SWL/SWR/SDL/SDR at every offset against a byte-level reference model, LQ/SQ alignment, LL/SC, MTSAB/MTSAH, and the preservation of bits 64..127 across scalar writes. Fix the deviations the tests exposed, cross-checked against the EE Core manual and PCSX2's interpreter: - BLEZ/BGTZ/BLTZ/BGEZ (and their likely and link forms) compared only the low 32 bits; the R5900 tests the full 64-bit register. - BLTZALL/BGEZALL wrote $ra only when taken; every "and link" branch links unconditionally. - MOVZ/MOVN copied the whole 128-bit register and clobbered bits 64..127 of rd; they are 64-bit moves. - LQ/SQ used the unmasked effective address; the hardware ignores the low four bits. LQC2/SQC2 are left as they were. - ADD32_OV/SUB32_OV, DADDI, DADD, DSUB and DADDIU formed the overflowing sum in signed arithmetic, which is undefined behaviour on exactly the inputs the overflow tests use (and the Release build uses LTO). The sums are now unsigned; non-overflowing results are unchanged. ps2x_tests: 483 passed, 0 failed (437 before). Closes ran-j#160
Author
|
Hi @ran-j, Just flagging that this overlaps #285 in |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
ps2xTest/src/r5900_general_instruction_tests.cpp: threeps2x_testssuites covering everyMipsOpcodes,SpecialFunctionsandRegimmFunctionsencoding (46 cases), and fixes the semantic deviations those tests exposed in the translators and the control-flow emitter.Closes #160 (the general-instruction part of #147).
How the tests work
Each case decodes a real 32-bit instruction word with
R5900Decoder, translates it withCodeGenerator::translateInstructionand pins the emitted C++ verbatim (modulo whitespace). The pinned C++ is then executed inside the test against anR5900Contextand a guest RAM buffer throughps2_runtime_macros.h, i.e. through the exact macros a recompiled game compiles against. So a case fails both when the recompiler emits something different and when that code does the wrong thing at runtime (PS2X_EXEC_EMITTED). Branches and jumps are materialised by the function emitter, so those cases emit a six-instruction function around the instruction under test and check the condition expression (also executed, viaPS2X_BRANCH_TAKEN), delay-slot placement, link writes and dispatch kinds.Covered edge behaviour includes: integer-overflow exceptions for ADD/ADDI/SUB/DADD/DADDI/DSUB (and that rd/rt is left untouched), MIPS division-by-zero and
INT32_MIN / -1results, sign/zero extension of every load width, 64-bit vs 32-bit compare semantics (SLT/SLTI/SLTIU/traps/branches), shift-amount masking (5 and 6 bits), LWL/LWR/LDL/LDR/SWL/SWR/SDL/SDR at every offset against a byte-level reference model (with the LWR upper-word rule), LQ/SQ address alignment, LL/SC reservation protocol, MTSAB/MTSAH, and that bits 64..127 of a GPR survive scalar writes.Three "manifest" cases walk all 64 opcodes, 64 SPECIAL function codes and 32 REGIMM codes and check that exactly the EE-reserved encodings (COP3, LWC2/SWC2, LLD/SCD, LDC1/SDC1, the DMULT family, holes) are rejected with a
throw, so a translator regression that silently drops an instruction is caught.Fixes found by the tests
Hardware behaviour cross-checked against the EE Core manual and PCSX2's interpreter (
R5900OpcodeImpl.cpp/Interpreter.cpp):GPR_S32); the R5900 tests the full 64-bit register (cpuRegs.GPR.r[rs].SD[0]in PCSX2). NowGPR_S64.$raonly when taken; every "and link" branch links unconditionally (MIPSGPR[31] ← PC + 8happens in the issue stage,_SetLink(31)precedes the condition in PCSX2).SET_GPR_VEC) and therefore clobbered bits 64..127 of rd; they are 64-bit moves (UD[0]in PCSX2). NowSET_GPR_U64.addr & ~0xfin PCSX2). LQC2/SQC2 are left as they were (PCSX2 does not mask them either).ADD32_OV/SUB32_OV, DADDI, DADD, DSUB computed the overflowing sum in signed arithmetic before testing for overflow, and DADDIU added asint64_t. With LTO Release builds that is undefined behaviour on exactly the inputs the overflow tests use. The sums are now formed in unsigned arithmetic; results are unchanged on every non-overflowing input.Verification
./build/ps2xTest/ps2x_tests: 483 passed, 0 failed (437 before this change).-DPS2X_ENABLE_FFMPEG=OFF).BEQ and BNE compare 64 bits…,BEQL…,BLTZ, BGEZ…,BLTZAL…,MOVZ and MOVN…,LQ and SQ…(the pinned strings and the executed semantics both change).