// // Provide pseudocommands (and other goodies) to make CPU optimizations easier // #if CONFIG_CPU_WDC_65C02 || CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_CSG_4510 || CONFIG_CPU_M65_45GS02 || CONFIG_CPU_WDC_65816 .cpu _65c02 #define HAS_OPCODES_65C02 #define HAS_BCD_SAFE_INTERRUPTS #endif #if CONFIG_CPU_CSG_65CE02 || CONFIG_CPU_CSG_4510 || CONFIG_CPU_M65_45GS02 #define HAS_OPCODES_65CE02 #endif #if CONFIG_CPU_CSG_4510 || CONFIG_CPU_M65_45GS02 #define HAS_OPCODES_4510 #endif #if CONFIG_CPU_M65_45GS02 #define HAS_OPCODES_45GS02 #endif #if CONFIG_CPU_WDC_65816 #define HAS_OPCODES_65816 #endif // // These are not exactly for optimization - but to encourage proper usage of panic screen // .pseudocommand panic code { // If case no panic screen is used, we can skip providing error codes within Kernal #if CONFIG_PANIC_SCREEN lda code #endif jmp ($E4B7) } // // Macros for generating jumptables // .macro put_jumptable_lo(list) { .for (var i = 0; i < list.size(); i++) { .byte mod((list.get(i) - 1), $100) } } .macro put_jumptable_hi(list) { .for (var i = 0; i < list.size(); i++) { .byte floor((list.get(i) - 1) / $100) } } #if HAS_OPCODES_65C02 .macro put_jumptable(list) { .for (var i = 0; i < list.size(); i++) { .word list.get(i) } } #endif // // Trick to skip a 2-byte instruction // .pseudocommand skip_2_bytes_trash_nvz { .byte $2C } // // Memory mapping for C65 and Mega65 // #if HAS_OPCODES_4510 .pseudocommand map { .byte $5C } .pseudocommand eom { .byte $EA } #endif // // Some additional 65CE02 instructions // #if HAS_OPCODES_65CE02 // CPU flags support .pseudocommand cle { .byte $02 } .pseudocommand see { .byte $03 } // .B register support .pseudocommand tab { .byte $5B } .pseudocommand tba { .byte $7B } // .Z register support .pseudocommand inz { .byte $1B } .pseudocommand dez { .byte $3B } .pseudocommand phz { .byte $DB } .pseudocommand plz { .byte $FB } .pseudocommand taz { .byte $4B } .pseudocommand tza { .byte $6B } // 16-bit data processing .pseudocommand dew addr { .var arg = addr.getValue() .if (arg > $FF) .error "DEW requires zeropage address" .byte $C3, arg } .pseudocommand inw addr { .var arg = addr.getValue() .if (arg > $FF) .error "INW requires zeropage address" .byte $E3, arg } // Zero page bit handling .pseudocommand rmb0 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB0 requires zeropage address" .byte $07, arg } .pseudocommand rmb1 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB1 requires zeropage address" .byte $17, arg } .pseudocommand rmb2 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB2 requires zeropage address" .byte $27, arg } .pseudocommand rmb3 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB3 requires zeropage address" .byte $37, arg } .pseudocommand rmb4 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB4 requires zeropage address" .byte $47, arg } .pseudocommand rmb5 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB5 requires zeropage address" .byte $57, arg } .pseudocommand rmb6 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB6 requires zeropage address" .byte $67, arg } .pseudocommand rmb7 addr { .var arg = addr.getValue() .if (arg > $FF) .error "RMB7 requires zeropage address" .byte $77, arg } .pseudocommand smb0 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB0 requires zeropage address" .byte $87, arg } .pseudocommand smb1 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB1 requires zeropage address" .byte $97, arg } .pseudocommand smb2 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB2 requires zeropage address" .byte $A7, arg } .pseudocommand smb3 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB3 requires zeropage address" .byte $B7, arg } .pseudocommand smb4 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB4 requires zeropage address" .byte $C7, arg } .pseudocommand smb5 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB5 requires zeropage address" .byte $D7, arg } .pseudocommand smb6 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB6 requires zeropage address" .byte $E7, arg } .pseudocommand smb7 addr { .var arg = addr.getValue() .if (arg > $FF) .error "SMB7 requires zeropage address" .byte $F7, arg } // Additional addressing modes .pseudocommand jsr_ind addr { .var arg = addr.getValue() .byte $22, mod(arg, $100), floor(arg / $100) } #endif // // Calculation shortcuts // .pseudocommand lda_zero // WARNING: do not use within interrupts { #if HAS_OPCODES_65CE02 tba #else lda #$00 #endif } // // Stack manipulation - some CPUs will leave .A unchanged, some will use it as temporary storage, so consider .A trashed // .pseudocommand phx_trash_a { #if HAS_OPCODES_65C02 phx #else txa pha #endif } .pseudocommand phy_trash_a { #if HAS_OPCODES_65C02 phy #else tya pha #endif } .pseudocommand plx_trash_a { #if HAS_OPCODES_65C02 plx #else pla tax #endif } .pseudocommand ply_trash_a { #if HAS_OPCODES_65C02 ply #else pla tay #endif } // // Branches with far offsets, substitutes by Bxx + JMP for CPUs not supporting the instruction // .pseudocommand bcs_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $B3, mod(offset, $100), floor(offset / $100) #else bcc __l jmp dst __l: #endif } .pseudocommand bcc_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $93, mod(offset, $100), floor(offset / $100) #else bcs __l jmp dst __l: #endif } .pseudocommand beq_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $F3, mod(offset, $100), floor(offset / $100) #else bne __l jmp dst __l: #endif } .pseudocommand bne_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $D3, mod(offset, $100), floor(offset / $100) #else beq __l jmp dst __l: #endif } .pseudocommand bmi_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $33, mod(offset, $100), floor(offset / $100) #else bpl __l jmp dst __l: #endif } .pseudocommand bpl_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $13, mod(offset, $100), floor(offset / $100) #else bmi __l jmp dst __l: #endif } .pseudocommand bvc_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $53, mod(offset, $100), floor(offset / $100) #else bvs __l jmp dst __l: #endif } .pseudocommand bvs_16 dst { #if HAS_OPCODES_65CE02 .var offset = mod($10000 + dst.getValue() - *, $10000) -2 .byte $73, mod(offset, $100), floor(offset / $100) #else bvc __l jmp dst __l: #endif }