beardypig / ghidra-emotionengine

Ghidra Processor for the Play Station 2's Emotion Engine MIPS based CPU
Apache License 2.0
198 stars 35 forks source link

`vmadd^bc^dest` not respected in decompiler output #68

Closed JayFoxRox closed 3 years ago

JayFoxRox commented 3 years ago

I'm using the version from #65 with Ghidra 9.2.4 (although I don't think that's causing the issue).

C code generated for Renderware matrix multiplication:

void RwMatrixMultiply(float *param_1,float *param_2,float *param_3)

{
  float fVar1;
  float fVar2;
  float fVar3;
  float fVar4;
  float fVar5;
  float fVar6;
  float fVar7;
  float fVar8;
  float fVar9;
  float fVar10;
  float fVar11;
  float fVar12;
  float fVar13;
  float fVar14;
  float fVar15;
  float fVar16;
  float fVar17;
  float fVar18;
  float fVar19;
  float fVar20;
  float fVar21;
  float fVar22;
  float fVar23;
  float fVar24;
  float fVar25;
  float fVar26;
  float in_vf9w;
  float in_vf10w;
  float in_vf11w;
  float in_vf12w;

  fVar3 = *param_2;
  fVar4 = param_2[1];
  fVar5 = param_2[2];
  fVar6 = param_2[4];
  fVar7 = param_2[5];
  fVar8 = param_2[6];
  fVar9 = param_2[8];
  fVar10 = param_2[9];
  fVar11 = param_2[10];
  fVar12 = param_2[0xc];
  fVar13 = param_2[0xd];
  fVar14 = param_2[0xe];
  fVar1 = param_2[3];
  fVar15 = *param_3;
  fVar16 = param_3[1];
  fVar17 = param_3[2];
  fVar18 = param_3[4];
  fVar19 = param_3[5];
  fVar20 = param_3[6];
  fVar21 = param_3[8];
  fVar22 = param_3[9];
  fVar23 = param_3[10];
  fVar24 = param_3[0xc];
  fVar25 = param_3[0xd];
  fVar26 = param_3[0xe];
  fVar2 = param_3[3];
  *param_1 = fVar15 * fVar3 + fVar18 * fVar4 + fVar21 * fVar5;
  param_1[1] = fVar16 * fVar3 + fVar19 * fVar4 + fVar22 * fVar5;
  param_1[2] = fVar17 * fVar3 + fVar20 * fVar4 + fVar23 * fVar5;
  param_1[3] = in_vf9w;
  param_1[4] = fVar15 * fVar6 + fVar18 * fVar7 + fVar21 * fVar8;
  param_1[5] = fVar16 * fVar6 + fVar19 * fVar7 + fVar22 * fVar8;
  param_1[6] = fVar17 * fVar6 + fVar20 * fVar7 + fVar23 * fVar8;
  param_1[7] = in_vf10w;
  param_1[8] = fVar15 * fVar9 + fVar18 * fVar10 + fVar21 * fVar11;
  param_1[9] = fVar16 * fVar9 + fVar19 * fVar10 + fVar22 * fVar11;
  param_1[10] = fVar17 * fVar9 + fVar20 * fVar10 + fVar23 * fVar11;
  param_1[0xb] = in_vf11w;
  param_1[0xc] = fVar15 * fVar12 + fVar18 * fVar13 + fVar21 * fVar14 + fVar24 * 1.0;
  param_1[0xd] = fVar16 * fVar12 + fVar19 * fVar13 + fVar22 * fVar14 + fVar25 * 1.0;
  param_1[0xe] = fVar17 * fVar12 + fVar20 * fVar13 + fVar23 * fVar14 + fVar26 * 1.0;
  param_1[0xf] = in_vf12w;
  param_1[3] = (float)((uint)fVar2 & (uint)fVar1);
  return;
}

(Let's ignore the weird stuff in param_1[3] for now, and focus on `in_vf`)*

Relevant disassembly:

[...]
0000cfec bc 29 c1 4b       vmulax.xyz ACC,vf5,vf1x
0000cff0 bd 30 c1 4b       vmadday.   ACC,vf6,vf1y
0000cff4 4a 3a c1 4b       vmaddz.xyz vf9,vf7,vf1z
0000cff8 bc 29 c2 4b       vmulax.xyz ACC,vf5,vf2x
0000cffc bd 30 c2 4b       vmadday.   ACC,vf6,vf2y
0000d000 8a 3a c2 4b       vmaddz.xyz vf10,vf7,vf2z
0000d004 bc 29 c3 4b       vmulax.xyz ACC,vf5,vf3x
0000d008 bd 30 c3 4b       vmadday.   ACC,vf6,vf3y
0000d00c ca 3a c3 4b       vmaddz.xyz vf11,vf7,vf3z
0000d010 bc 29 c4 4b       vmulax.xyz ACC,vf5,vf4x
0000d014 bd 30 c4 4b       vmadday.   ACC,vf6,vf4y
0000d018 be 38 c4 4b       vmaddaz.   ACC,vf7,vf4z
0000d01c 0b 43 c0 4b       vmaddw.xyz vf12,vf8,vf0w
0000d020 24 18 64 00       and        v1,v1,a0
0000d024 00 00 49 f8       sqc2       vf9,0x0(v0)
0000d028 10 00 4a f8       sqc2       vf10,0x10(v0)
0000d02c 20 00 4b f8       sqc2       vf11,0x20(v0)
0000d030 30 00 4c f8       sqc2       vf12,0x30(v0)
[...]

As you can see, this writes vf9, vf10, vf11 and vf12 from vmaddz.xyz and friends, but the decompiler claims that this write never happens. Therefore it depends on in_vf*, which is incorrect.

Initially I thought P-Code was simply not implemented, but it looks like it should happen here:

https://github.com/beardypig/ghidra-emotionengine/blob/9e55ddaf47377b1fc5e0cea4f4abb4fb246cfda3/src/main/java/ghidra/emotionengine/InjectPayloadVu.java#L441

Do I manually have to trigger P-Code injection or is there a bug?

astrelsky commented 3 years ago

There is likely a bug. P-Code injection is automatic.

JayFoxRox commented 3 years ago

Looking at it again, the decompilation is actually correct.

It appears to do a 3x4 matrix multiplication, so the w components are never written (as indicated by the .xyz writemask). They might get filled with garbage, but it shouldn't matter.

It actually seems to keep some flags in matrix[0][3], which is also why there's this weird write to param_1[3].

Closed.