Meanwhile I'm trying to make the compiler usable by actually writing something useful. Calling "native" functions is tricky, though with stack in X. Let's look at this one, that just calls C64 kernal function, which takes A, Y and X parameters:
Code: Select all
package pl.qus.wolin
fun setLfs^0xffba(lfn: ubyte^CPU.A, channel: ubyte^CPU.Y, dev: ubyte^CPU.X)
fun main() {
setLfs(1, 1, 8)
}
This requires:
1) pushing X, as it's my operations stack pointer
2) evaluating each parameter to proper register
3) push the register, as it can get trashed by evaluation of next argument(s)
4) when all arguments evaluated and pushed, pull them back and call native function
5) restore SP (x)
Of course the only possible argument order is A, Y, X, which means I need to reorder them if user declares function i.e. like this:
fun setLfs^0xffba(lfn: ubyte^CPU.A, dev: ubyte^CPU.X, channel: ubyte^CPU.Y)
Phew! Lot's of code, unfortunately...
Code: Select all
// ****************************************
// funkcja: fun main():unit
// ****************************************
label __wolin_pl_qus_wolintest_main
save CPU.X // save SP, as X is used by native call
alloc SP<__wolin_reg2>, #1 // for call argument 0
let SP(0)<__wolin_reg2>[ubyte] = #1[ubyte] // atomic ex
let CPU.A[ubyte] = SP(0)<__wolin_reg2>[ubyte]
save CPU.A
free SP<__wolin_reg2>, #1 // for call argument 0, type = ubyte
alloc SP<__wolin_reg3>, #1 // for call argument 1
let SP(0)<__wolin_reg3>[ubyte] = #8[ubyte] // atomic ex
let CPU.Y[ubyte] = SP(0)<__wolin_reg3>[ubyte]
save CPU.Y
free SP<__wolin_reg3>, #1 // for call argument 1, type = ubyte
alloc SP<__wolin_reg4>, #1 // for call argument 2
let SP(0)<__wolin_reg4>[ubyte] = #1[ubyte] // atomic ex
let CPU.X[ubyte] = SP(0)<__wolin_reg4>[ubyte]
save CPU.X
free SP<__wolin_reg4>, #1 // for call argument 2, type = ubyte
restore CPU.X // fill register for call
restore CPU.Y // fill register for call
restore CPU.A // fill register for call
call 65466[adr] // pl.qus.wolintest.setLfs
restore CPU.X // restore SP, as X is used by native call
ret
Code: Select all
; label__wolin_pl_qus_wolintest_main
__wolin_pl_qus_wolintest_main:
; allocSPF,#0
; saveCPU.X
txa
pha
; allocSP<__wolin_reg2>,#1
dex
; letSP(0)<__wolin_reg2>[ubyte]=#1[ubyte]
lda #1
sta 0,x
; letCPU.A[ubyte]=SP(0)<__wolin_reg2>[ubyte]
lda 0,x
; saveCPU.A
pha
; freeSP<__wolin_reg2>,#1
inx
; allocSP<__wolin_reg3>,#1
dex
; letSP(0)<__wolin_reg3>[ubyte]=#8[ubyte]
lda #8
sta 0,x
; letCPU.Y[ubyte]=SP(0)<__wolin_reg3>[ubyte]
lda 0,x
tay
; saveCPU.Y
tya
pha
; freeSP<__wolin_reg3>,#1
inx
; allocSP<__wolin_reg4>,#1
dex
; letSP(0)<__wolin_reg4>[ubyte]=#1[ubyte]
lda #1
sta 0,x
; letCPU.X[ubyte]=SP(0)<__wolin_reg4>[ubyte]
lda 0,x
tax
; saveCPU.X
txa
pha
; freeSP<__wolin_reg4>,#1
inx
; restoreCPU.X
pla
tax
; restoreCPU.Y
pla
tay
; restoreCPU.A
pla
; call65466[adr]
jsr 65466
; restoreCPU.X
pla
tax
; freeSPF<unit>,#0
; ret
rts