Emulator Issues #12062
closedPossible DSP instruction ADDPAXZ bug
0%
Description
Game Name?
Any game which uses AX Ucode (for example Bust-a-Move 3000). I will not fill in further since other information does not apply to the problem.
I reversed the AX mixer procedure (huge procedure called by Command 0x03 handler) and found that the ADDPAXZ instruction does not work as it is guessed by context.
At the very end of the mixer is a small code from a series of ADDPAXZ instructions that increment pointers of current Sample Buffers.
Original disassembled code, according to the Duddie document and the current implementation of ADDPAXZ in Dolphin:
0457 00 83 0E 08 lri ar3, #0x0E08
0459 1C 03 mrr ar0, ar3
045A 1F F5 mrr ac1.m, prod.m1
045B 19 1A lrri ax1.l, @ar0
045C F8 58 addpaxz ac0, ax0 l ax1.h, @ar0
045D FB A0 addpaxz ac1, ax1 ls ax1.l, ac0.m
045E F8 B1 addpaxz ac0, ax0 ls ax1.h, ac1.m
045F FB A0 addpaxz ac1, ax1 ls ax1.l, ac0.m
0460 F8 B1 addpaxz ac0, ax0 ls ax1.h, ac1.m
0461 FB A0 addpaxz ac1, ax1 ls ax1.l, ac0.m
0462 F8 B1 addpaxz ac0, ax0 ls ax1.h, ac1.m
0463 FB A0 addpaxz ac1, ax1 ls ax1.l, ac0.m
0464 F8 3B addpaxz ac0, ax0 s @ar3, ac1.m
0465 1B 7E srri @ar3, ac0.m
If you try to decompile it, then it will do absolutely not what it intended.
But if you fix the ADDPAXZ decoding as follows:
ADDPAXZ * 1111 10sd xxxx xxxx // ADDPAXZ $acD, $ax1.[l|h]
That disassembled code will look like this:
045B 19 1A lrri ax1.l, @ar0
045C F8 58 addpaxz ac0, ax1.l l ax1.h, @ar0
045D FB A0 addpaxz ac1, ax1.h ls ax1.l, ac0.m
045E F8 B1 addpaxz ac0, ax1.l ls ax1.h, ac1.m
045F FB A0 addpaxz ac1, ax1.h ls ax1.l, ac0.m
0460 F8 B1 addpaxz ac0, ax1.l ls ax1.h, ac1.m
0461 FB A0 addpaxz ac1, ax1.h ls ax1.l, ac0.m
0462 F8 B1 addpaxz ac0, ax1.l ls ax1.h, ac1.m
0463 FB A0 addpaxz ac1, ax1.h ls ax1.l, ac0.m
0464 F8 3B addpaxz ac0, ax1.l s @ar3, ac1.m
0465 1B 7E srri @ar3, ac0.m
And if you translate this into c, now it works as intended:
AdvanceSampleBufPtr() // 0459
{
ar3 = 0xE08;
ar0 = ar3;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
*ar3++ = *ar0++ + 0x40;
}
Updated by Anonymous almost 3 years ago
The dsp interpreter has the following comment https://github.com/dolphin-emu/dolphin/blob/d1beb9ef7018c71a2336c62fa31bfe554083a3e7/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp#L106
// ADDPAXZ $acD, $axS
// 1111 10sd xxxx xxxx
// Adds secondary accumulator $axS to product register and stores result
// in accumulator register. Low 16-bits of $acD ($acD.l) are set (round) to 0.
//
// TODO: ugly code and still small error here (+/- 1 in .m - randomly)
// flags out: --xx xx0x
It seems unlikely that this comment could be correct (only some small off-by-one) and also that the s bit indexes [h,l] opposed to [ax1,ax0] ?
However, maybe your observation hints at how to fix this off-by-one. Have you tried this on real hardware?
Updated by flacs almost 3 years ago
- Status changed from New to Invalid
Dolphin's currently disassembly looks correct to me (it's different from yours) and I've verified on hardware that addpaxz behaves as documented.
0457 0083 0e08 lri $AR3, #0x0e08
0459 1c03 mrr $AR0, $AR3
045a 1ff5 mrr $AC1.M, $PROD.M1
045b 191a lrri $AX0.H, @$AR0
045c f858 addpaxz'l $ACC0, $AX0 : $AX1.H, @$AR0
045d fba0 addpaxz'ls $ACC1, $AX1 : $AX0.H, $AC0.M
045e f8b1 addpaxz'ls $ACC0, $AX0 : $AX1.H, $AC1.M
045f fba0 addpaxz'ls $ACC1, $AX1 : $AX0.H, $AC0.M
0460 f8b1 addpaxz'ls $ACC0, $AX0 : $AX1.H, $AC1.M
0461 fba0 addpaxz'ls $ACC1, $AX1 : $AX0.H, $AC0.M
0462 f8b1 addpaxz'ls $ACC0, $AX0 : $AX1.H, $AC1.M
0463 fba0 addpaxz'ls $ACC1, $AX1 : $AX0.H, $AC0.M
0464 f83b addpaxz's $ACC0, $AX0 : @$AR3, $AC1.M
0465 1b7e srri @$AR3, $AC0.M