lab313ru / ghidra_psx_ldr

Sony Playstation PSX executables loader for GHIDRA
236 stars 31 forks source link

Add MIPS Unaligned Instruction Fix analyzer. #63

Closed twevs closed 2 years ago

twevs commented 2 years ago

The MIPS Unaligned Instruction Fix analyzer, available for MIPS processors in the Ghidra repository, leads to considerably improved decompilation of lwl/lwr and swl/swr pairs, allowing one to make sense of struct copies, such that for instance:

  if ((pControl->field_55_flags & 2) == 0) {
    puVar1 = (undefined *)((int)&(pControl->field_0_position).vy + 1);
    uVar17 = (uint)puVar1 & 3;
    uVar18 = (uint)pControl & 3;
    uVar19 = (*(int *)(puVar1 + -uVar17) << (3 - uVar17) * 8 |
             in_t0 & 0xffffffffU >> (uVar17 + 1) * 8) & -1 << (4 - uVar18) * 8 |
             *(uint *)((int)pControl - uVar18) >> uVar18 * 8;
    puVar1 = (undefined *)((int)&(pControl->field_0_position).pad + 1);
    uVar17 = (uint)puVar1 & 3;
    psVar2 = &(pControl->field_0_position).vz;
    uVar18 = (uint)psVar2 & 3;
    uVar18 = (*(int *)(puVar1 + -uVar17) << (3 - uVar17) * 8 |
             in_t1 & 0xffffffffU >> (uVar17 + 1) * 8) & -1 << (4 - uVar18) * 8 |
             *(uint *)((int)psVar2 - uVar18) >> uVar18 * 8;
    puVar1 = (undefined *)((int)&(pControl->field_10_pStruct_hzd_unknown).field_14_vec.vy + 1);
    uVar17 = (uint)puVar1 & 3;
    puVar9 = (uint *)(puVar1 + -uVar17);
    *puVar9 = *puVar9 & -1 << (uVar17 + 1) * 8 | uVar19 >> (3 - uVar17) * 8;
    pSVar16 = &(pControl->field_10_pStruct_hzd_unknown).field_14_vec;
    uVar17 = (uint)pSVar16 & 3;
    puVar9 = (uint *)((int)pSVar16 - uVar17);
    *puVar9 = *puVar9 & 0xffffffffU >> (4 - uVar17) * 8 | uVar19 << uVar17 * 8;
    puVar1 = (undefined *)((int)&(pControl->field_10_pStruct_hzd_unknown).field_14_vec.pad + 1);
    uVar17 = (uint)puVar1 & 3;
    puVar9 = (uint *)(puVar1 + -uVar17);
    *puVar9 = *puVar9 & -1 << (uVar17 + 1) * 8 | uVar18 >> (3 - uVar17) * 8;
    psVar2 = &(pControl->field_10_pStruct_hzd_unknown).field_14_vec.vz;
    uVar17 = (uint)psVar2 & 3;
    puVar9 = (uint *)((int)psVar2 - uVar17);
    *puVar9 = *puVar9 & 0xffffffffU >> (4 - uVar17) * 8 | uVar18 << uVar17 * 8;
    (pControl->field_10_pStruct_hzd_unknown).field_14_vec.pad = (pControl->field_8_rotator).vy;
    GM_ActControl_helper6_8002A538((int)pHzd,(ushort *)&pControl->field_10_pStruct_hzd_unknown);
  }

becomes

  if ((pControl->field_55_flags & 2) == 0) {
    uVar16 = *(undefined4 *)&(pControl->field_0_position).vz;
    *(undefined4 *)&(pControl->field_10_pStruct_hzd_unknown).field_14_vec =
         *(undefined4 *)&pControl->field_0_position;
    *(undefined4 *)&(pControl->field_10_pStruct_hzd_unknown).field_14_vec.vz = uVar16;
    (pControl->field_10_pStruct_hzd_unknown).field_14_vec.pad = (pControl->field_8_rotator).vy;
    GM_ActControl_helper6_8002A538((int)pHzd,(ushort *)&pControl->field_10_pStruct_hzd_unknown);
  }

and the SVECTOR copy

  puVar1 = (undefined *)((int)&local_28[1].vy + 1);
  uVar2 = (uint)puVar1 & 3;
  puVar3 = (uint *)(puVar1 + -uVar2);
  *puVar3 = *puVar3 & -1 << (uVar2 + 1) * 8 | uStack48._0_4_ >> (3 - uVar2) * 8;
  local_28[1]._0_4_ = uStack48._0_4_;
  puVar1 = (undefined *)((int)&local_28[1].pad + 1);
  uVar2 = (uint)puVar1 & 3;
  puVar3 = (uint *)(puVar1 + -uVar2);
  *puVar3 = *puVar3 & -1 << (uVar2 + 1) * 8 | uStack48._4_4_ >> (3 - uVar2) * 8;
  local_28[1]._4_4_ = uStack48._4_4_;

becomes simply

  local_28[1]._0_4_ = uStack48._0_4_;
  local_28[1]._4_4_ = uStack48._4_4_;

Given its utility in making sense of decompiled PlayStation code, it seems it would therefore make sense to add it to the list of available analyzers for the PSX.

fatalis commented 2 years ago

This is incredibly useful :+1:

lab313ru commented 2 years ago

Merged via: c4a720a458a2312a16912c662f88e7606354499a.