leuat / TRSE

Turbo Rascal Syntax Error full repo
GNU General Public License v3.0
243 stars 44 forks source link

Incorrect optimization of hand-rolled assembly #852

Closed jtgans closed 6 months ago

jtgans commented 6 months ago

TRSE is incorrectly optimizing out an LDY instruction and replacing it horribly with a TAY instruction. In my project configuration, I have all post optimization steps disabled, and it's still generating this junk, and I'm running version 0.17.173 on macos, ARM.

The procedure in question is here:

procedure NMI_ISR();
begin
    asm("
    CLD

    LDA #$7F
    STA $DD0D
    LDY $DD0D
    BMI __rs232

    JSR $F63D    // Watch for RUN or Shift
    JSR $FFE1    // Test for Stop keypress
    BNE __stop

    JSR $E056    // If stop+restore, reinit
    JSR $E109
    JSR $C000
    JMP ($0A00)

__stop
    .byte $00    // BRK because OrgAsm is stupid

__rs232
    JSR $E805    // RS-232 control
    JMP $FF33    // RFI
    ");
end;

The incorrectly generated ASM is here:

NMI_ISR
    ; LineNumber: 18
    CLD
    LDA #$7F
    STA $DD0D
    tay ; optimized y, look out for bugs L22 ORG    LDY $DD0D
    BMI __rs232

    JSR $F63D    // Watch for RUN or Shift
    JSR $FFE1    // Test for Stop keypress
    BNE __stop
    JSR $E056    // If stop+restore, reinit
    JSR $E109
    JSR $C000
    JMP ($0A00)
__stop
    .byte $00    // BRK because OrgAsm is stupid

__rs232
    JSR $E805    // RS-232 control
    JMP $FF33    // RFI

    ; LineNumber: 42
    rts
end_procedure_NMI_ISR

TRSE should not be attempting to optmize asm() blocks like this. It's not only incorrect here, it's horrifically incorrect for an NMI handler. The end result is that none of the code works correctly because it doesn't know that $DD0D is a register for one of the CIAs on the Commodore 128.

jtgans commented 6 months ago

Naturally, the workaround here was, like the BRK bug in #853, to use .byte $ac, $0d, $dd in place of the LDY $DD0D to bypass the compiler.

AndyHOvine commented 6 months ago

Hi there, this optimisation is usually desired. Obviously in your case you need a specific operation.

Can you try adding ;keep to the end of the line, should tell TRSE not to optimise this line.

eg:

LDY $DD0D ;keep

jtgans commented 6 months ago

Ahh. That's what that means. Yeah, I'll have to try that. Apologies for the spurious bug report.

leuat commented 6 months ago

Hi there, sorry for the late reply! TRSE will try to optimize this yes, but you can always add "; keep" to an assembly instruction in order to not remove it. I just fixed another small bug in the optimizer, so it should now be possible to use volatile variables directly in TRSE:

vol : volatile byte at $4800;

..

vol:=$74;
k:=vol; 

now translates to

lda #$74
sta vol ;keep
lda vol ;keep
sta k