dirkwhoffmann / Moira

A Motorola 68000 emulator written in C++
https://dirkwhoffmann.github.io/Moira
Other
106 stars 13 forks source link

Link instruction apparently broken? #22

Closed kouta-kun closed 1 year ago

kouta-kun commented 1 year ago

Hi! I'm currently trying to build a fantasy console based on 68k processors and I quickly ran into this strange issue: I have code generated by gcc that uses the link instruction to generate a frame pointer. The code looks something like this:

80000074:   4e56 fff8       linkw %fp,#-8
80000078:   2f0d            movel %a5,%sp@-

The issue is that when using Moira, A6 (FP) is initialized to 0 and is still 0 after running linkw, when it should be 8 bytes under the SP register (0x800030cc and 0x800030c4 in my case). In contrast, running the same instruction under Musashi gives the correct result of 0x800030cc in the FP register. I've attached the ELf that generates this issue, I'm not sure how to convert it to a flat image so it works without parsing it. console-test.elf.gz

dirkwhoffmann commented 1 year ago

I haven't been able to reproduce the issue. Here are two images from the debugger showing the execution of the LINK instruction in question. A6 is modified as expected:

Bildschirm­foto 2022-12-26 um 16 11 51 Bildschirm­foto 2022-12-26 um 16 12 11
kouta-kun commented 1 year ago

That's strange. In that case I'll close it as it's probably some initialization I'm missing in my use of the library. Thanks!

dirkwhoffmann commented 1 year ago

If you don't mind, it'll be great if you could run the code with some printf statements put into the exec handler of the LINK command:

template <Core C, Instr I, Mode M, Size S> void
Moira::execLink(u16 opcode)
{
    AVAILABILITY(S == Long ? C68020 : C68000)

    u16 ird  = getIRD();
    u32 sp   = getSP() - 4;

    int ax   = _____________xxx(opcode);
    i32 disp = SEXT <S> (readI<C, S>());

    // Check for address error
    if (misaligned<C>(sp)) {

        writeBuffer = u16(readA(ax) >> 16);
        writeA(ax, sp);
        throw AddressError(makeFrame<AE_DATA|AE_WRITE>(sp, getPC() + 2, getSR(), ird));
    }

    POLL_IPL;

    // Write to stack
    push <C, Long>(readA(ax) - ((MIMIC_MUSASHI && ax == 7) ? 4 : 0));

    // Modify address register and stack pointer
    writeA(ax, sp);
    reg.sp = U32_ADD(reg.sp, disp);

    prefetch<C>();

    //           00  10  20        00  10  20        00  10  20
    //           .b  .b  .b        .w  .w  .w        .l  .l  .l
    CYCLES_IP   ( 0,  0,  0,       16, 16,  5,        0,  0,  6);

    FINALIZE
}

Simply print the value of A6 prior and after it gets modified (you can get the value via `readA(ax)'. Maybe it's some strange bug related to undefined behavior or something that occurs with your compiler, but not with mine.