// Regression test for the -O0 byte-store-through-pointer miscompile
// (W65816 STB_DPIndLongY atomic pseudo).
//
// The i8 store `*pcout = ...` through a ptr32 lowers to a [dp],Y store
// wrapped in SEP #$20 / STA / REP #$20 (M=8 so only one byte is written).
// The custom inserter used to emit those as THREE separate instructions,
// so the -O0 fast register allocator (which spills everything and reloads
// before each use) could wedge a 16-bit reload BETWEEN the SEP and REP —
// running it in M=8, it loaded only the low byte of a 16-bit value.  That
// truncated `probe`'s `px + 1` pointer reload, so a value carried across
// the call came back wrong (reported by an external SNES user: an
// `unsigned char pid` packed via `<< 16` returned 0).
//
// Fix: emit ONE atomic STB_DPIndLongY pseudo, expanded to SEP/STA/REP at
// the AsmPrinter, so nothing can be inserted inside the M=8 window.
//
// caller(34): probe writes pc = 34 & 7 = 2 through the pointer and returns
// 34 + 1 = 35; caller returns 35 + 2 = 37 = 0x25.  The buggy -O0 build
// returned 3 (probe's return truncated to 1, + pc 2).  MUST be compiled
// at -O0 (the bug does not occur at -O1+).

__attribute__((noinline)) static short probe(short px, unsigned char *pcout) {
    *pcout = (unsigned char)(px & 7);
    return (short)(px + 1);
}

__attribute__((noinline)) static short caller(short px) {
    unsigned char pc;
    short y = probe(px, &pc);    // y (probe's return) is live across the call
    return (short)(y + pc);      // + pc, the byte written through the pointer
}

int main(void) {
    *(volatile unsigned short *)0x025000 = (unsigned short)caller(34);  // 0x0025
    while (1) {}
    return 0;
}
