428 lines
6.7 KiB
ArmAsm
428 lines
6.7 KiB
ArmAsm
|
|
//
|
|
// 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
|
|
}
|