【问题标题】:GCC Generated a Misaligned "ldrd" InstructionGCC 生成了一个未对齐的“ldrd”指令
【发布时间】:2017-10-05 01:06:21
【问题描述】:

编译此 C++ 代码时:

#include "../SM64DS_2.h"

//@021026a0, hooks: 0x020bddb8, 0x020bde0c
void CancelPowerups(Player& player)
{
    if(player.isFreezeFramePeach)
    {
        player.isFreezeFramePeach = false;
        player.EndMusic(0x33);
    }
    if(player.isDashyToad)
    {
        player.isDashyToad = false;
        player.EndMusic(0x33);
    }
}

//hook: 0x020b98f8
void EnableFreezeFramePeach(Player& player)
{
    //TODO: Show message on first use
    player.isFreezeFramePeach = true;
    player.flowerPowerTimer = 600;
    player.SetMusic(0x33);
}

//hook: 0x020b9904
void EnableDashyToad(Player& player)
{
    //TODO: Show message on first use
    player.isDashyToad = true;
    player.flowerPowerTimer = 600;
    player.SetMusic(0x33);
}

//hook: 0x020e4f10
void WorkDashyToadPart1(Player& player)
{
    //TODO: Deal with speed of walking animation
    if(player.isDashyToad)
    {
        player.horzSpeed /= 2;
        player.isSpeedHalfed = true;
        if(player.walkOnWaterTimer == 61)
            ++player.walkOnWaterTimer;
    }
}

//hook: 0x020e52e8
void WorkDashyToadPart2(Player& player)
{
    if(player.isSpeedHalfed)
    {
        player.horzSpeed *= 2;
        player.isSpeedHalfed = false;
        player.dashyToadParticleSysID = Particle::System::New(player.dashyToadParticleSysID,
                                                              0x4a,
                                                              player.pos.x,
                                                              player.pos.y + Fix12i(72),
                                                              player.pos.z,
                                                              nullptr,
                                                              nullptr);
    }
}

gcc 带有以下标志

arm-none-eabi-g++ -MMD -MP -MF /c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/build/PeachToadAbilities.d -g -Wall -O2 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math  -iquote /c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/include -I/c/devkitPro/libnds/include -I/c/devkitPro/devkitARM/include -I/c/devkitPro/devkitARM/arm-none-eabi/include -I/c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/build -DARM9 -nodefaultlibs -I. -fno-builtin -c --std=c++14 -fno-rtti -fno-exceptions -Wa,-adl=PeachToadAbilities.lst -c /c/Users/Joshua/Documents/desmume-0.9.11-win64/SM64DSe/SM64DSe/ASMPatchTemplate/source/C_PeachToadAbilities/PeachToadAbilities.cpp -o PeachToadAbilities.o

(特别注意架构是ARMv5TE,CPU是ARM946E-S) 为最后一个函数生成以下 ASM:

push    {r4, lr}
mov     r4, r0
mov     r1, #0x0
ldrd    r2, [r4, #0x5c]
ldr     ip, [r0, #0x98]
ldr     r0, [r0, #0x280]
lsl     ip, ip, #0x1
str     ip, [r4, #0x98]
ldr     ip, [r4, #0x64]
sub     sp, sp, #0x10
strb    r1, [r4, #0x27d]
add     r3, r3, #0x48000
str     r1, [sp, #0x8]
str     r1, [sp, #0x4]
str     ip, [sp]
mov     r1, #0x4a
bl      _ZN8Particle6System3NewEjj5Fix12IiES2_S2_PK11Vector3_16fPNS_8CallbackE
str     r0, [r4, #0x280]
add     sp, sp, #0x10
pop     {r4, pc}

就上下文而言,这是任天堂 DS 游戏的 ROM 破解片段。 Player结构是4字节对齐的,偏移0x5C是玩家的位置,是3个Fix12的结构(一个Fix12是1个4字节整数的结构)。

问题在于 gcc 生成的“ldrd”指令无法证明可以访问 8 字节对齐的地址(它不应该知道“播放器”在哪里,此外,0x5C 不是 8 的倍数。)。我看过的 ARM 文档说,对于 ARMv5,加载未对齐的双字是未定义的行为。然而,no$gba 和 DeSmuME 假设当地址是 4 字节对齐时,这样的访问仍然会从该地址加载一个 8 字节的值。这是 ARM946E-S CPU 上 ARMv5TE 的正确行为吗? (我没有在实际的 DS 上测试过,因为我没有闪存卡。)

【问题讨论】:

  • 看起来 8 字节对齐要求已从后来的 Arm 架构中删除,并且 GCC 不遵守旧要求。一种可能的解决方法是禁用这些指令,仅针对 ARMv5T 进行编译?
  • 显示Player 的定义。 (最好发MCVE

标签: c++ gcc arm


【解决方案1】:

我在 ARMv5TE 和 ARM946E-S 和 GCC 6 中也看到了这一点(在 5 中还可以)。在我的例子中,代码加载了一个数组的两个连续元素,但是编译器无法证明传入的数组指针是 8 字节对齐的。我将尝试生成一个简单的示例并报告这一点。你应该这样做,希望它会得到修复。

【讨论】:

    【解决方案2】:

    类实例很可能与某些字节对齐(例如 64 个字节),并且标头不是 8 个字节的倍数,因此成员变量被打包在一个从“未对齐”地址开始的位置中,这样结合诸如 0x5c 之类的“未对齐”偏移量,该地址保证 8 字节对齐。

    编译器并不完美,但我无法想象他们会犯如此微不足道的错误。

    所以别担心。

    【讨论】:

      猜你喜欢
      • 2017-01-07
      • 2021-12-05
      • 1970-01-01
      • 2018-07-08
      • 2020-04-13
      • 1970-01-01
      • 2022-12-06
      • 2014-03-17
      • 1970-01-01
      相关资源
      最近更新 更多