mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
4958463e75
added txt.print_f as alias to floats.print
498 lines
12 KiB
Lua
498 lines
12 KiB
Lua
; Prog8 definitions for the Neo6502
|
|
|
|
%option no_symbol_prefixing, ignore_unused
|
|
|
|
neo {
|
|
&uword NMI_VEC = $FFFA ; 6502 nmi vector, determined by the kernal if banked in
|
|
&uword RESET_VEC = $FFFC ; 6502 reset vector, determined by the kernal if banked in
|
|
&uword IRQ_VEC = $FFFE ; 6502 interrupt vector, determined by the kernal if banked in
|
|
|
|
%asminclude "library:neo/neo6502.asm"
|
|
}
|
|
|
|
sys {
|
|
; ------- lowlevel system routines --------
|
|
|
|
const ubyte target = 7 ; compilation target specifier. 255=virtual, 128=C128, 64=C64, 32=PET, 16=CommanderX16, 8=atari800XL, 7=Neo6502
|
|
|
|
const ubyte SIZEOF_BOOL = 1
|
|
const ubyte SIZEOF_BYTE = 1
|
|
const ubyte SIZEOF_UBYTE = 1
|
|
const ubyte SIZEOF_WORD = 2
|
|
const ubyte SIZEOF_UWORD = 2
|
|
const ubyte SIZEOF_FLOAT = 0 ; undefined, no floats supported
|
|
const byte MIN_BYTE = -128
|
|
const byte MAX_BYTE = 127
|
|
const ubyte MIN_UBYTE = 0
|
|
const ubyte MAX_UBYTE = 255
|
|
const word MIN_WORD = -32768
|
|
const word MAX_WORD = 32767
|
|
const uword MIN_UWORD = 0
|
|
const uword MAX_UWORD = 65535
|
|
; MIN_FLOAT and MAX_FLOAT are defined in the floats module if importec
|
|
|
|
|
|
asmsub reset_system() {
|
|
; Soft-reset the system back to initial power-on status
|
|
; TODO
|
|
%asm {{
|
|
sei
|
|
jmp (neo.RESET_VEC)
|
|
}}
|
|
}
|
|
|
|
sub wait(uword jiffies) {
|
|
; --- wait approximately the given number of jiffies (1/60th seconds)
|
|
; TODO
|
|
}
|
|
|
|
asmsub waitvsync() clobbers(A) {
|
|
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
|
; TODO
|
|
%asm {{
|
|
nop
|
|
rts
|
|
}}
|
|
}
|
|
|
|
asmsub internal_stringcopy(uword source @R0, uword target @AY) clobbers (A,Y) {
|
|
; Called when the compiler wants to assign a string value to another string.
|
|
%asm {{
|
|
sta P8ZP_SCRATCH_W1
|
|
sty P8ZP_SCRATCH_W1+1
|
|
lda cx16.r0
|
|
ldy cx16.r0+1
|
|
jmp prog8_lib.strcpy
|
|
}}
|
|
}
|
|
|
|
asmsub memcopy(uword source @R0, uword target @R1, uword count @AY) clobbers(A,X,Y) {
|
|
; note: only works for NON-OVERLAPPING memory regions!
|
|
; note: can't be inlined because is called from asm as well
|
|
%asm {{
|
|
ldx cx16.r0
|
|
stx P8ZP_SCRATCH_W1 ; source in ZP
|
|
ldx cx16.r0+1
|
|
stx P8ZP_SCRATCH_W1+1
|
|
ldx cx16.r1
|
|
stx P8ZP_SCRATCH_W2 ; target in ZP
|
|
ldx cx16.r1+1
|
|
stx P8ZP_SCRATCH_W2+1
|
|
cpy #0
|
|
bne _longcopy
|
|
|
|
; copy <= 255 bytes
|
|
tay
|
|
bne _copyshort
|
|
rts ; nothing to copy
|
|
|
|
_copyshort
|
|
dey
|
|
beq +
|
|
- lda (P8ZP_SCRATCH_W1),y
|
|
sta (P8ZP_SCRATCH_W2),y
|
|
dey
|
|
bne -
|
|
+ lda (P8ZP_SCRATCH_W1),y
|
|
sta (P8ZP_SCRATCH_W2),y
|
|
rts
|
|
|
|
_longcopy
|
|
sta P8ZP_SCRATCH_B1 ; lsb(count) = remainder in last page
|
|
tya
|
|
tax ; x = num pages (1+)
|
|
ldy #0
|
|
- lda (P8ZP_SCRATCH_W1),y
|
|
sta (P8ZP_SCRATCH_W2),y
|
|
iny
|
|
bne -
|
|
inc P8ZP_SCRATCH_W1+1
|
|
inc P8ZP_SCRATCH_W2+1
|
|
dex
|
|
bne -
|
|
ldy P8ZP_SCRATCH_B1
|
|
bne _copyshort
|
|
rts
|
|
}}
|
|
}
|
|
|
|
asmsub memset(uword mem @R0, uword numbytes @R1, ubyte value @A) clobbers(A,X,Y) {
|
|
%asm {{
|
|
ldy cx16.r0
|
|
sty P8ZP_SCRATCH_W1
|
|
ldy cx16.r0+1
|
|
sty P8ZP_SCRATCH_W1+1
|
|
ldx cx16.r1
|
|
ldy cx16.r1+1
|
|
jmp prog8_lib.memset
|
|
}}
|
|
}
|
|
|
|
asmsub memsetw(uword mem @R0, uword numwords @R1, uword value @AY) clobbers(A,X,Y) {
|
|
%asm {{
|
|
ldx cx16.r0
|
|
stx P8ZP_SCRATCH_W1
|
|
ldx cx16.r0+1
|
|
stx P8ZP_SCRATCH_W1+1
|
|
ldx cx16.r1
|
|
stx P8ZP_SCRATCH_W2
|
|
ldx cx16.r1+1
|
|
stx P8ZP_SCRATCH_W2+1
|
|
jmp prog8_lib.memsetw
|
|
}}
|
|
}
|
|
|
|
inline asmsub read_flags() -> ubyte @A {
|
|
%asm {{
|
|
php
|
|
pla
|
|
}}
|
|
}
|
|
|
|
inline asmsub clear_carry() {
|
|
%asm {{
|
|
clc
|
|
}}
|
|
}
|
|
|
|
inline asmsub set_carry() {
|
|
%asm {{
|
|
sec
|
|
}}
|
|
}
|
|
|
|
inline asmsub clear_irqd() {
|
|
%asm {{
|
|
cli
|
|
}}
|
|
}
|
|
|
|
inline asmsub set_irqd() {
|
|
%asm {{
|
|
sei
|
|
}}
|
|
}
|
|
|
|
inline asmsub irqsafe_set_irqd() {
|
|
%asm {{
|
|
php
|
|
sei
|
|
}}
|
|
}
|
|
|
|
inline asmsub irqsafe_clear_irqd() {
|
|
%asm {{
|
|
plp
|
|
}}
|
|
}
|
|
|
|
sub disable_caseswitch() {
|
|
; no-op
|
|
}
|
|
|
|
sub enable_caseswitch() {
|
|
; no-op
|
|
}
|
|
|
|
asmsub save_prog8_internals() {
|
|
%asm {{
|
|
lda P8ZP_SCRATCH_B1
|
|
sta save_SCRATCH_ZPB1
|
|
lda P8ZP_SCRATCH_REG
|
|
sta save_SCRATCH_ZPREG
|
|
lda P8ZP_SCRATCH_W1
|
|
sta save_SCRATCH_ZPWORD1
|
|
lda P8ZP_SCRATCH_W1+1
|
|
sta save_SCRATCH_ZPWORD1+1
|
|
lda P8ZP_SCRATCH_W2
|
|
sta save_SCRATCH_ZPWORD2
|
|
lda P8ZP_SCRATCH_W2+1
|
|
sta save_SCRATCH_ZPWORD2+1
|
|
rts
|
|
save_SCRATCH_ZPB1 .byte 0
|
|
save_SCRATCH_ZPREG .byte 0
|
|
save_SCRATCH_ZPWORD1 .word 0
|
|
save_SCRATCH_ZPWORD2 .word 0
|
|
; !notreached!
|
|
}}
|
|
}
|
|
|
|
asmsub restore_prog8_internals() {
|
|
%asm {{
|
|
lda save_prog8_internals.save_SCRATCH_ZPB1
|
|
sta P8ZP_SCRATCH_B1
|
|
lda save_prog8_internals.save_SCRATCH_ZPREG
|
|
sta P8ZP_SCRATCH_REG
|
|
lda save_prog8_internals.save_SCRATCH_ZPWORD1
|
|
sta P8ZP_SCRATCH_W1
|
|
lda save_prog8_internals.save_SCRATCH_ZPWORD1+1
|
|
sta P8ZP_SCRATCH_W1+1
|
|
lda save_prog8_internals.save_SCRATCH_ZPWORD2
|
|
sta P8ZP_SCRATCH_W2
|
|
lda save_prog8_internals.save_SCRATCH_ZPWORD2+1
|
|
sta P8ZP_SCRATCH_W2+1
|
|
rts
|
|
}}
|
|
}
|
|
|
|
asmsub exit(ubyte returnvalue @A) {
|
|
; -- immediately exit the program with a return code in the A register
|
|
%asm {{
|
|
sta cleanup_at_exit._exitcode
|
|
ldx prog8_lib.orig_stackpointer
|
|
txs
|
|
jmp cleanup_at_exit
|
|
}}
|
|
}
|
|
|
|
asmsub exit2(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y) {
|
|
; -- immediately exit the program with result values in the A, X and Y registers.
|
|
%asm {{
|
|
sta cleanup_at_exit._exitcode
|
|
stx cleanup_at_exit._exitcodeX
|
|
sty cleanup_at_exit._exitcodeY
|
|
ldx prog8_lib.orig_stackpointer
|
|
txs
|
|
jmp cleanup_at_exit
|
|
}}
|
|
}
|
|
|
|
asmsub exit3(ubyte resulta @A, ubyte resultx @X, ubyte resulty @Y, bool carry @Pc) {
|
|
; -- immediately exit the program with result values in the A, X and Y registers, and the Carry flag in the status register.
|
|
%asm {{
|
|
sta cleanup_at_exit._exitcode
|
|
lda #0
|
|
rol a
|
|
sta cleanup_at_exit._exitcodeCarry
|
|
stx cleanup_at_exit._exitcodeX
|
|
sty cleanup_at_exit._exitcodeY
|
|
ldx prog8_lib.orig_stackpointer
|
|
txs
|
|
jmp cleanup_at_exit
|
|
}}
|
|
}
|
|
|
|
inline asmsub progend() -> uword @AY {
|
|
%asm {{
|
|
lda #<prog8_program_end
|
|
ldy #>prog8_program_end
|
|
}}
|
|
}
|
|
|
|
inline asmsub progstart() -> uword @AY {
|
|
%asm {{
|
|
lda #<prog8_program_start
|
|
ldy #>prog8_program_start
|
|
}}
|
|
}
|
|
|
|
inline asmsub push(ubyte value @A) {
|
|
%asm {{
|
|
pha
|
|
}}
|
|
}
|
|
|
|
inline asmsub pushw(uword value @AY) {
|
|
%asm {{
|
|
pha
|
|
tya
|
|
pha
|
|
}}
|
|
}
|
|
|
|
inline asmsub pop() -> ubyte @A {
|
|
%asm {{
|
|
pla
|
|
}}
|
|
}
|
|
|
|
inline asmsub popw() -> uword @AY {
|
|
%asm {{
|
|
pla
|
|
tay
|
|
pla
|
|
}}
|
|
}
|
|
|
|
}
|
|
|
|
cx16 {
|
|
; the sixteen virtual 16-bit registers that the CX16 has defined in the zeropage
|
|
; the sixteen virtual 16-bit registers in both normal unsigned mode and signed mode (s)
|
|
&uword r0 = $0002
|
|
&uword r1 = $0004
|
|
&uword r2 = $0006
|
|
&uword r3 = $0008
|
|
&uword r4 = $000a
|
|
&uword r5 = $000c
|
|
&uword r6 = $000e
|
|
&uword r7 = $0010
|
|
&uword r8 = $0012
|
|
&uword r9 = $0014
|
|
&uword r10 = $0016
|
|
&uword r11 = $0018
|
|
&uword r12 = $001a
|
|
&uword r13 = $001c
|
|
&uword r14 = $001e
|
|
&uword r15 = $0020
|
|
|
|
&word r0s = $0002
|
|
&word r1s = $0004
|
|
&word r2s = $0006
|
|
&word r3s = $0008
|
|
&word r4s = $000a
|
|
&word r5s = $000c
|
|
&word r6s = $000e
|
|
&word r7s = $0010
|
|
&word r8s = $0012
|
|
&word r9s = $0014
|
|
&word r10s = $0016
|
|
&word r11s = $0018
|
|
&word r12s = $001a
|
|
&word r13s = $001c
|
|
&word r14s = $001e
|
|
&word r15s = $0020
|
|
|
|
&ubyte r0L = $0002
|
|
&ubyte r1L = $0004
|
|
&ubyte r2L = $0006
|
|
&ubyte r3L = $0008
|
|
&ubyte r4L = $000a
|
|
&ubyte r5L = $000c
|
|
&ubyte r6L = $000e
|
|
&ubyte r7L = $0010
|
|
&ubyte r8L = $0012
|
|
&ubyte r9L = $0014
|
|
&ubyte r10L = $0016
|
|
&ubyte r11L = $0018
|
|
&ubyte r12L = $001a
|
|
&ubyte r13L = $001c
|
|
&ubyte r14L = $001e
|
|
&ubyte r15L = $0020
|
|
|
|
&ubyte r0H = $0003
|
|
&ubyte r1H = $0005
|
|
&ubyte r2H = $0007
|
|
&ubyte r3H = $0009
|
|
&ubyte r4H = $000b
|
|
&ubyte r5H = $000d
|
|
&ubyte r6H = $000f
|
|
&ubyte r7H = $0011
|
|
&ubyte r8H = $0013
|
|
&ubyte r9H = $0015
|
|
&ubyte r10H = $0017
|
|
&ubyte r11H = $0019
|
|
&ubyte r12H = $001b
|
|
&ubyte r13H = $001d
|
|
&ubyte r14H = $001f
|
|
&ubyte r15H = $0021
|
|
|
|
&byte r0sL = $0002
|
|
&byte r1sL = $0004
|
|
&byte r2sL = $0006
|
|
&byte r3sL = $0008
|
|
&byte r4sL = $000a
|
|
&byte r5sL = $000c
|
|
&byte r6sL = $000e
|
|
&byte r7sL = $0010
|
|
&byte r8sL = $0012
|
|
&byte r9sL = $0014
|
|
&byte r10sL = $0016
|
|
&byte r11sL = $0018
|
|
&byte r12sL = $001a
|
|
&byte r13sL = $001c
|
|
&byte r14sL = $001e
|
|
&byte r15sL = $0020
|
|
|
|
&byte r0sH = $0003
|
|
&byte r1sH = $0005
|
|
&byte r2sH = $0007
|
|
&byte r3sH = $0009
|
|
&byte r4sH = $000b
|
|
&byte r5sH = $000d
|
|
&byte r6sH = $000f
|
|
&byte r7sH = $0011
|
|
&byte r8sH = $0013
|
|
&byte r9sH = $0015
|
|
&byte r10sH = $0017
|
|
&byte r11sH = $0019
|
|
&byte r12sH = $001b
|
|
&byte r13sH = $001d
|
|
&byte r14sH = $001f
|
|
&byte r15sH = $0021
|
|
|
|
asmsub save_virtual_registers() clobbers(A,Y) {
|
|
%asm {{
|
|
ldy #31
|
|
- lda cx16.r0,y
|
|
sta _cx16_vreg_storage,y
|
|
dey
|
|
bpl -
|
|
rts
|
|
|
|
_cx16_vreg_storage
|
|
.word 0,0,0,0,0,0,0,0
|
|
.word 0,0,0,0,0,0,0,0
|
|
; !notreached!
|
|
}}
|
|
}
|
|
|
|
asmsub restore_virtual_registers() clobbers(A,Y) {
|
|
%asm {{
|
|
ldy #31
|
|
- lda save_virtual_registers._cx16_vreg_storage,y
|
|
sta cx16.r0,y
|
|
dey
|
|
bpl -
|
|
rts
|
|
}}
|
|
}
|
|
|
|
sub cpu_is_65816() -> bool {
|
|
; Returns true when you have a 65816 cpu, false when it's a 6502.
|
|
return false
|
|
}
|
|
|
|
}
|
|
|
|
p8_sys_startup {
|
|
; program startup and shutdown machinery. Needs to reside in normal system ram.
|
|
|
|
asmsub init_system() {
|
|
; Initializes the machine to a sane starting state.
|
|
; Called automatically by the loader program logic.
|
|
%asm {{
|
|
sei
|
|
cld
|
|
clc
|
|
; TODO reset screen mode etc etc?
|
|
clv
|
|
; TODO what about IRQ handler? cli
|
|
rts
|
|
}}
|
|
}
|
|
|
|
asmsub init_system_phase2() {
|
|
%asm {{
|
|
rts ; no phase 2 steps on the Neo6502
|
|
}}
|
|
}
|
|
|
|
asmsub cleanup_at_exit() {
|
|
; executed when the main subroutine does rts
|
|
%asm {{
|
|
_exitcodeCarry = *+1
|
|
lda #0
|
|
lsr a
|
|
_exitcode = *+1
|
|
lda #0 ; exit code possibly modified in exit()
|
|
_exitcodeX = *+1
|
|
ldx #0
|
|
_exitcodeY = *+1
|
|
ldy #0
|
|
rts
|
|
}}
|
|
}
|
|
|
|
}
|