Page 7 of 12
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Sat Dec 07, 2019 4:00 pm
by qus
New problem. Optimizing chain of single register assignment sometimes produces code that uses already deallocated reg:
Code: Select all
call __wolin_pl_qus_wolin_SomeClass_suma[adr]
free SPF<pl.qus.wolin.SomeClass.suma.__returnValue>, #1
let &SP(0)<__wolin_reg16>[ubyte*] = SPF(2)<pl.qus.wolin.SomeClass.suma.__returnValue>[ubyte] <--- OOOOOPS!
I guess I have to find such cases and "manually" move
past such assignment.
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Sun Dec 08, 2019 12:58 pm
by qus
I'm pretty sure I've found no OO language for C64 during my searches, so am I getting "First 6502 OO Cup"?
This code sets border to result of calling a method on allocated object:
Code: Select all
package pl.qus.wolin
var border: ubyte^53280
fun allocMem(size: uword, count: uword): uword {
return 30000
}
class SummingClass {
var x: ubyte = 3
var y: ubyte = 7
fun suma(): ubyte {
return x+y
}
}
fun main() {
val testowa : SummingClass
testowa = SummingClass()
border = testowa.suma()
}
In optimized pseudo-asm:
Code: Select all
setup HEADER
setup SPF = 251[ubyte], 40959[uword]
setup SP = 143[ubyte]
setup HEAP = 176[ubyte]
let __wolin_pl_qus_wolin_znak<pl.qus.wolin.znak>[ubyte] = #0[ubyte]
let __wolin_pl_qus_wolin_i<pl.qus.wolin.i>[uword] = #0[ubyte]
alloc SPF, #2
call __wolin_pl_qus_wolin_main[adr]
ret
function __wolin_pl_qus_wolin_allocMem
let SPF(4)<pl.qus.wolin.allocMem.__returnValue>[uword] = #30000[uword]
free SPF<pl.qus.wolin.allocMem.__fnargs>, #4
ret
function __wolin_pl_qus_wolin_SummingClass
alloc SPF, #6
let SPF(2)<pl.qus.wolin.allocMem.size>[uword] = #3[uword]
let SPF(0)<pl.qus.wolin.allocMem.count>[uword] = #1[uword]
call __wolin_pl_qus_wolin_allocMem[adr]
let SPF(2)<pl.qus.wolin.SummingClass.__returnValue>[any*] = SPF(0)<pl.qus.wolin.allocMem.__returnValue>[uword]
setup HEAP = SPF(0)<pl.qus.wolin.allocMem.__returnValue>[uword]
let HEAP(2)<pl.qus.wolin.SummingClass.x>[ubyte] = #3[ubyte]
let HEAP(1)<pl.qus.wolin.SummingClass.y>[ubyte] = #7[ubyte]
free SPF<pl.qus.wolin.allocMem.__returnValue>, #2
ret
function __wolin_pl_qus_wolin_SummingClass_suma
setup HEAP = this
alloc SP<__wolin_reg8>, #2
let SP(0)<__wolin_reg8>[ubyte*] = *HEAP(2)<pl.qus.wolin.SummingClass.x>[ubyte]
add &SP(0)<__wolin_reg8>[ubyte*] = &SP(0)<__wolin_reg8>[ubyte*], HEAP(1)<pl.qus.wolin.SummingClass.y>[ubyte]
let SPF(2)<pl.qus.wolin.SummingClass.suma.__returnValue>[ubyte] = &SP(0)<__wolin_reg8>[ubyte*]
free SP<__wolin_reg8>, #2
free SPF<pl.qus.wolin.SummingClass.suma.__fnargs>, #2
ret
function __wolin_pl_qus_wolin_main
alloc SP<__wolin_reg13>, #2
let SP(0)<__wolin_reg13>[any*] = SPF(0)<pl.qus.wolin.main..testowa>[any*]
alloc SP<__wolin_reg14>, #2
alloc SPF, #2
call __wolin_pl_qus_wolin_SummingClass[adr]
let SP(0)<__wolin_reg14>[any*] = SPF(0)<pl.qus.wolin.SummingClass.__returnValue>[any*]
let &SP(2)<__wolin_reg13>[any*] = &SP(0)<__wolin_reg14>[any*]
free SP<__wolin_reg14>, #2
free SP<__wolin_reg13>, #2
alloc SP<__wolin_reg16>, #2
let SP(0)<__wolin_reg16>[ubyte*] = 53280[ubyte*]
alloc SPF, #3
let SPF(0)[any*] = SPF(2)<pl.qus.wolin.main..testowa>[any*]
call __wolin_pl_qus_wolin_SummingClass_suma[adr]
let &SP(0)<__wolin_reg16>[ubyte*] = SPF(0)<pl.qus.wolin.SummingClass.suma.__returnValue>[ubyte]
free SP<__wolin_reg16>, #2
free SPF<pl.qus.wolin.main.__fnargs>, #1
free SPF<pl.qus.wolin.SummingClass.__returnValue>, #2
free SPF<pl.qus.wolin.SummingClass.suma.__returnValue>, #1
ret
label __wolin_indirect_jsr
goto 65535[adr]
label __wolin_pl_qus_wolin_znak
alloc 0[ubyte]
label __wolin_pl_qus_wolin_i
alloc 0[uword]
And finally in 6502 asm:
Code: Select all
; setupHEADER
;**********************************************
;*
;* BASIC header
;*
;* compile with:
;* cl65.exe -o assembler.prg -t c64 -C c64-asm.cfg -g -Ln labels.txt assembler.s
;*
;**********************************************
.org 2049
.export LOADADDR = *
Bas10: .word BasEnd
.word 10
.byte 158 ; sys
.byte " 2064"
.byte 0
BasEnd: .word 0
.word 0
;
; setupSPF=251[ubyte],40959[uword]
; prepare function stack
__wolin_spf := 251 ; function stack ptr
__wolin_spf_hi := 251+1 ; function stack ptr
__wolin_spf_top := 40959 ; function stack top
__wolin_spf_top_hi := 40959+1 ; function stack top
lda #<__wolin_spf_top ; set function stack top
sta __wolin_spf
lda #>__wolin_spf_top
sta __wolin_spf+1
; setupSP=143[ubyte]
; prepare program stack
__wolin_sp_top := 143 ; program stack top
__wolin_sp_top_hi := 143+1 ; program stack top
ldx #__wolin_sp_top ; set program stack top
; setupHEAP=176[ubyte]
__wolin_this_ptr := 176
__wolin_this_ptr_hi := 176+1
; let__wolin_pl_qus_wolin_znak<pl.qus.wolin.znak>[ubyte]=#0[ubyte]
lda #0
sta __wolin_pl_qus_wolin_znak
; let__wolin_pl_qus_wolin_i<pl.qus.wolin.i>[uword]=#0[ubyte]
lda #<0
sta __wolin_pl_qus_wolin_i
lda #0
sta __wolin_pl_qus_wolin_i+1
; allocSPF,#2
clc
lda __wolin_spf
sbc #2
sta __wolin_spf
bcs :+
dec __wolin_spf+1
:
; call__wolin_pl_qus_wolin_main[adr]
jsr __wolin_pl_qus_wolin_main
; ret
rts
; function__wolin_pl_qus_wolin_allocMem
__wolin_pl_qus_wolin_allocMem:
; letSPF(4)<pl.qus.wolin.allocMem.__returnValue>[uword]=#30000[uword]
ldy #4
lda #<30000
sta (__wolin_spf),y
iny
lda #>30000
sta (__wolin_spf),y
; freeSPF<pl.qus.wolin.allocMem.__fnargs>,#4
clc
lda __wolin_spf
adc #4
sta __wolin_spf
bcc :+
inc __wolin_spf+1
:
; ret
rts
; function__wolin_pl_qus_wolin_SummingClass
__wolin_pl_qus_wolin_SummingClass:
; allocSPF,#6
clc
lda __wolin_spf
sbc #6
sta __wolin_spf
bcs :+
dec __wolin_spf+1
:
; letSPF(2)<pl.qus.wolin.allocMem.size>[uword]=#3[uword]
ldy #2
lda #<3
sta (__wolin_spf),y
iny
lda #>3
sta (__wolin_spf),y
; letSPF(0)<pl.qus.wolin.allocMem.count>[uword]=#1[uword]
ldy #0
lda #<1
sta (__wolin_spf),y
iny
lda #>1
sta (__wolin_spf),y
; call__wolin_pl_qus_wolin_allocMem[adr]
jsr __wolin_pl_qus_wolin_allocMem
; letSPF(2)<pl.qus.wolin.SummingClass.__returnValue>[any*]=SPF(0)<pl.qus.wolin.allocMem.__returnValue>[uword]
ldy #0
lda (__wolin_spf),y
ldy #2
sta (__wolin_spf),y
ldy #0+1
lda (__wolin_spf),y
ldy #2+1
sta (__wolin_spf),y
; setupHEAP=SPF(0)<pl.qus.wolin.allocMem.__returnValue>[uword]
ldy #0 ; this pointer from SPF to this pointer on ZP
lda (__wolin_spf),y
sta __wolin_this_ptr
iny
lda (__wolin_spf),y
sta __wolin_this_ptr+1
; letHEAP(2)<pl.qus.wolin.SummingClass.x>[ubyte]=#3[ubyte]
lda #3
ldy #2
sta (__wolin_this_ptr),y
; letHEAP(1)<pl.qus.wolin.SummingClass.y>[ubyte]=#7[ubyte]
lda #7
ldy #1
sta (__wolin_this_ptr),y
; freeSPF<pl.qus.wolin.allocMem.__returnValue>,#2
clc
lda __wolin_spf
adc #2
sta __wolin_spf
bcc :+
inc __wolin_spf+1
:
; ret
rts
; function__wolin_pl_qus_wolin_SummingClass_suma
__wolin_pl_qus_wolin_SummingClass_suma:
; setupHEAP=this
ldy #0 ; this pointer from SPF to this pointer on ZP
lda (__wolin_spf),y
sta __wolin_this_ptr
iny
lda (__wolin_spf),y
sta __wolin_this_ptr+1
; allocSP<__wolin_reg8>,#2
dex
dex
; letSP(0)<__wolin_reg8>[ubyte*]=*HEAP(2)<pl.qus.wolin.SummingClass.x>[ubyte]
clc
lda __wolin_this_ptr
adc #2
sta 0,x
lda __wolin_this_ptr+1
adc #0
sta 0+1,x
; add&SP(0)<__wolin_reg8>[ubyte*]=&SP(0)<__wolin_reg8>[ubyte*],HEAP(1)<pl.qus.wolin.SummingClass.y>[ubyte]
clc
lda (0,x)
ldy #1
adc (__wolin_this_ptr), y
sta (0,x)
; letSPF(2)<pl.qus.wolin.SummingClass.suma.__returnValue>[ubyte]=&SP(0)<__wolin_reg8>[ubyte*]
lda (0,x)
ldy #2
sta (__wolin_spf),y
; freeSP<__wolin_reg8>,#2
inx
inx
; freeSPF<pl.qus.wolin.SummingClass.suma.__fnargs>,#2
clc
lda __wolin_spf
adc #2
sta __wolin_spf
bcc :+
inc __wolin_spf+1
:
; ret
rts
; function__wolin_pl_qus_wolin_main
__wolin_pl_qus_wolin_main:
; allocSP<__wolin_reg13>,#2
dex
dex
; letSP(0)<__wolin_reg13>[any*]=SPF(0)<pl.qus.wolin.main..testowa>[any*]
ldy #0
lda (__wolin_spf),y
sta 0,x
iny
lda (__wolin_spf),y
sta 0+1,x
; allocSP<__wolin_reg14>,#2
dex
dex
; allocSPF,#2
clc
lda __wolin_spf
sbc #2
sta __wolin_spf
bcs :+
dec __wolin_spf+1
:
; call__wolin_pl_qus_wolin_SummingClass[adr]
jsr __wolin_pl_qus_wolin_SummingClass
; letSP(0)<__wolin_reg14>[any*]=SPF(0)<pl.qus.wolin.SummingClass.__returnValue>[any*]
ldy #0
lda (__wolin_spf),y
sta 0,x
iny
lda (__wolin_spf),y
sta 0+1,x
; let&SP(2)<__wolin_reg13>[any*]=&SP(0)<__wolin_reg14>[any*]
; take value that is located at address stored in 0
lda (0,x)
; store it at address stored in 2
sta (2,x)
inc 0,x
bne :+
inc 0+1,x
:
lda (0,x)
sta (2,x)
; freeSP<__wolin_reg14>,#2
inx
inx
; freeSP<__wolin_reg13>,#2
inx
inx
; allocSP<__wolin_reg16>,#2
dex
dex
; letSP(0)<__wolin_reg16>[ubyte*]=53280[ubyte*]
lda #<53280
sta 0,x
lda #>53280
sta 0+1,x
; allocSPF,#3
clc
lda __wolin_spf
sbc #3
sta __wolin_spf
bcs :+
dec __wolin_spf+1
:
; letSPF(0)[any*]=SPF(2)<pl.qus.wolin.main..testowa>[any*]
ldy #2
lda (__wolin_spf),y
ldy #0
sta (__wolin_spf),y
ldy #2
iny
lda (__wolin_spf),y
ldy #0
iny
sta (__wolin_spf),y
; call__wolin_pl_qus_wolin_SummingClass_suma[adr]
jsr __wolin_pl_qus_wolin_SummingClass_suma
; let&SP(0)<__wolin_reg16>[ubyte*]=SPF(0)<pl.qus.wolin.SummingClass.suma.__returnValue>[ubyte]
ldy #0
lda (__wolin_spf),y
sta (0,x)
; freeSP<__wolin_reg16>,#2
inx
inx
; freeSPF<pl.qus.wolin.main.__fnargs>,#1
clc
lda __wolin_spf
adc #1
sta __wolin_spf
bcc :+
inc __wolin_spf+1
:
; freeSPF<pl.qus.wolin.SummingClass.__returnValue>,#2
clc
lda __wolin_spf
adc #2
sta __wolin_spf
bcc :+
inc __wolin_spf+1
:
; freeSPF<pl.qus.wolin.SummingClass.suma.__returnValue>,#1
clc
lda __wolin_spf
adc #1
sta __wolin_spf
bcc :+
inc __wolin_spf+1
:
; ret
rts
; label__wolin_indirect_jsr
__wolin_indirect_jsr:
; goto65535[adr]
jmp 65535
; alloc0[uword]
.word 0
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Sun Jan 05, 2020 10:46 am
by qus
Update.
Since I always hated how I had to set things in BASIC via some POKE X, PEEK(Y) OR A AND B, I really wanted to have neat and simple bit operations via variables attached to bits at specific address, like:
That would be very useful on C64, as it would make handling lot of I/O as simple as:
Unfortunately it would break literally everything I've done so far. So instead I've added bit setting ops.
Code: Select all
var spritesOn: ubyte^0xd015
spritesOn := 0 // show sprite 1 (set bit 0 at d015)
spritesOn .= 128 // hide sprite 7 (clear bit 0 at d015)
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Sun Jan 05, 2020 3:04 pm
by qus
And here's a question (anyone reading?) for feature described above. While setting bits is straightforward, how do I clear bits on 6502 if there's no NOT opcode? How would I implement in assembly clearing bit 7 and 0 like in code below:
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Sun Jan 05, 2020 3:12 pm
by BigEd
To complement a value you'd generally use EOR #$FF - in the case of clearing bits, you first invert the mask and then use it to AND the variable to be masked. (Is this the question you're asking?)
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Sun Jan 05, 2020 9:30 pm
by qus
Yep. Exactly that. Thanks.
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Mon Jan 06, 2020 10:03 am
by qus
Would that be right code for setting byte at address pointed by ZP:
Set val bits in &dst:
Code: Select all
bit &SP(?dst)[ubyte*] = #?val[ubyte], #1[bool] -> """
lda ({dst},x)
ora #{val}
sta ({dst},x)
"""
Clear val bits in &dst:
Code: Select all
bit &SP(?dst)[ubyte*] = #?val[ubyte], #0[bool] -> """
lda #{val}
xor #$ff
and ({dst},x)
sta ({dst},x)
"""
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Mon Jan 06, 2020 12:51 pm
by qus
Don't need no ouija board to summon some ghosts now:
Code: Select all
package pl.qus.wolin
var screen: ubyte[]^1024
var spritesOn: ubyte^0xd015
var sprite0X: ubyte^0xd000
var sprite0Y: ubyte^0xd001
var spritesFat: ubyte^0xd01d
var spritesTall: ubyte^0xd017
var sprite0Color: ubyte^0xd027
fun main() {
spritesOn := 1
spritesFat := 1
spritesTall := 1
sprite0X = 100
sprite0Y = 100
sprite0Color = 2
}
Compiles to:
Code: Select all
; setupHEADER
;**********************************************
;*
;* BASIC header
;*
;* compile with:
;* cl65.exe -o assembler.prg -t c64 -C c64-asm.cfg -g -Ln labels.txt assembler.s
;*
;**********************************************
.org 2049
.export LOADADDR = *
Bas10: .word BasEnd
.word 10
.byte 158 ; sys
.byte " 2064"
.byte 0
BasEnd: .word 0
.word 0
;
; setupSPF=251[ubyte],40959[uword]
; prepare function stack
__wolin_spf := 251 ; function stack ptr
__wolin_spf_hi := 251+1 ; function stack ptr
__wolin_spf_top := 40959 ; function stack top
__wolin_spf_top_hi := 40959+1 ; function stack top
lda #<__wolin_spf_top ; set function stack top
sta __wolin_spf
lda #>__wolin_spf_top
sta __wolin_spf+1
; setupSP=143[ubyte]
; prepare program stack
__wolin_sp_top := 143 ; program stack top
__wolin_sp_top_hi := 143+1 ; program stack top
ldx #__wolin_sp_top ; set program stack top
; setupHEAP=176[ubyte]
__wolin_this_ptr := 176
__wolin_this_ptr_hi := 176+1
; allocSPF,#0
; call__wolin_pl_qus_wolin_main[adr]
jsr __wolin_pl_qus_wolin_main
; ret
rts
; function__wolin_pl_qus_wolin_main
__wolin_pl_qus_wolin_main:
; bit53269[ubyte]=#1[ubyte],#1[bool]
lda 53269
ora 1
sta 53269
; bit53277[ubyte]=#1[ubyte],#1[bool]
lda 53277
ora 1
sta 53277
; let53248[ubyte]=#100[ubyte]
lda #100
sta 53248
; let53249[ubyte]=#100[ubyte]
lda #100
sta 53249
; let53287[ubyte]=#2[ubyte]
lda #2
sta 53287
; ret
rts
; label__wolin_indirect_jsr
__wolin_indirect_jsr:
; goto65535[adr]
jmp 65535
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Mon Jan 06, 2020 11:35 pm
by dmsc
Hi!
Would that be right code for setting byte at address pointed by ZP:
Set val bits in &dst:
Code: Select all
bit &SP(?dst)[ubyte*] = #?val[ubyte], #1[bool] -> """
lda ({dst},x)
ora #{val}
sta ({dst},x)
"""
That looks ok.
Clear val bits in &dst:
Code: Select all
bit &SP(?dst)[ubyte*] = #?val[ubyte], #0[bool] -> """
lda #{val}
xor #$ff
and ({dst},x)
sta ({dst},x)
"""
That does look OK, but it is simpler to do:
Code: Select all
bit &SP(?dst)[ubyte*] = #?val[ubyte], #0[bool] -> """
lda #$FF-{val}
and ({dst},x)
sta ({dst},x)
"""
Also, you can write the first version to be similar to the second:
Code: Select all
bit &SP(?dst)[ubyte*] = #?val[ubyte], #1[bool] -> """
lda #{val}
ora ({dst},x)
sta ({dst},x)
"""
But a warning: it is typical for simple hardware register to have different functions on READ and WRITE, you can't read back the value you just wrote - so the above won't work. For example, on the Atari 8-bit computers you can't read back ANTIC, GTIA or POKEY registers, you must always write the full register values.
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Tue Jan 07, 2020 5:17 pm
by qus
Ha! I'm well aware of that. But is there any solution for such cases besides keeping a separate variable, making bit ops on it and then writing this variable to I/O reg?
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Tue Jan 07, 2020 9:11 pm
by Chromatix
In these cases, the "shadow register" technique is the standard. Often the ROM will reserve a location for it, if the hardware is standard for the machine.
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Tue Jan 07, 2020 9:25 pm
by drogon
Ha! I'm well aware of that. But is there any solution for such cases besides keeping a separate variable, making bit ops on it and then writing this variable to I/O reg?
The solution is left as an exercise to the user
ie. Don't make the language do more than it needs to. If you/me/anyone is writing code in this language and we're poking hardware, then we need to know if the hardware supports read/modify/write (some do, some don't) or not, and if not, then w need to keep a copy, managed by our own code.
My thoughts on this, anyway.
-Gordon
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Thu Jan 09, 2020 6:40 am
by qus
Update. Finally optimized pointer ops, so:
Code: Select all
alloc SP<__wolin_reg5>, #2
let SP(0)<__wolin_reg5>[ubyte*] = 53269[ubyte]
bit 53269[ubyte] = #1[ubyte], #1[bool]
free SP<__wolin_reg5>, #2
alloc SP<__wolin_reg8>, #2
let SP(0)<__wolin_reg8>[ubyte*] = 53277[ubyte]
bit 53277[ubyte] = #1[ubyte], #1[bool]
free SP<__wolin_reg8>, #2
alloc SP<__wolin_reg11>, #2
let SP(0)<__wolin_reg11>[ubyte*] = 53271[ubyte]
bit 53271[ubyte] = #1[ubyte], #1[bool]
free SP<__wolin_reg11>, #2
alloc SP<__wolin_reg14>, #2
let SP(0)<__wolin_reg14>[ubyte*] = 53248[ubyte]
let 53248[ubyte], #100[ubyte]
free SP<__wolin_reg14>, #2
alloc SP<__wolin_reg17>, #2
let SP(0)<__wolin_reg17>[ubyte*] = 53249[ubyte]
let 53249[ubyte], #100[ubyte]
free SP<__wolin_reg17>, #2
alloc SP<__wolin_reg20>, #2
let SP(0)<__wolin_reg20>[ubyte*] = 53287[ubyte]
let 53287[ubyte], #2[ubyte]
free SP<__wolin_reg20>, #2
becomes:
Code: Select all
bit 53269[ubyte]=#1[ubyte],#1[bool]
bit 53277[ubyte]=#1[ubyte],#1[bool]
bit 53271[ubyte]=#1[ubyte],#1[bool]
let 53248[ubyte]=#100[ubyte]
let 53249[ubyte]=#100[ubyte]
let 53287[ubyte]=#2[ubyte]
And the last todo opt is return values:
Code: Select all
function __wolin_pl_qus_wolin_suma
alloc SP<__wolin_reg1>, #2
let SP(0)<__wolin_reg1>[ubyte*] = *SPF(1)<pl.qus.wolin.suma.a>[ubyte]
add &SP(0)<__wolin_reg1>[ubyte*] = &SP(0)<__wolin_reg1>[ubyte*], SPF(0)<pl.qus.wolin.suma.b>[ubyte]
let SPF(2)<pl.qus.wolin.suma.__returnValue>[ubyte] = &SP(0)<__wolin_reg1>[ubyte*]
free SP<__wolin_reg1>, #2
free SPF<pl.qus.wolin.suma.__fnargs>, #2
ret
to:
Code: Select all
function __wolin_pl_qus_wolin_suma
let SPF(2)<pl.qus.wolin.suma.__returnValue>[ubyte] = *SPF(1)<pl.qus.wolin.suma.a>[ubyte]
add &SPF(2)<pl.qus.wolin.suma.__returnValue>[ubyte] = &SP(0)<__wolin_reg1>[ubyte*], SPF(0)<pl.qus.wolin.suma.b>[ubyte]
free SPF<pl.qus.wolin.suma.__fnargs>, #2
ret
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Fri Jan 17, 2020 7:50 am
by qus
Update.
I forgot to mention that before but there was another reason for creating Wolin. An argument with some guy on C64 forum that you can open the border ONLY from assembler. He was unable to provide a reason for this ridiculous statement, though.
So I thought I will open C64 border form higl level language, and I guess a language with OO and lambdas is pretty high level, right? But still I need to set interrupt vector somehow. So now it is possible. Look at below Wolin code:
Code: Select all
package pl.qus.wolin
var rasterVector: uword^0x0314 // this is C64 raster interrupt vector
var border: ubyte^53280
fun rasterProc() {
// do something
border = 5
}
fun main() {
// do somethig more, set raster line, etc.
rasterVector = rasterProc
}
Compiles to:
Code: Select all
; setupHEADER
;**********************************************
;*
;* BASIC header
;*
;* compile with:
;* cl65.exe -o assembler.prg -t c64 -C c64-asm.cfg -g -Ln labels.txt assembler.s
;*
;**********************************************
.org 2049
.export LOADADDR = *
Bas10: .word BasEnd
.word 10
.byte 158 ; sys
.byte " 2064"
.byte 0
BasEnd: .word 0
.word 0
;
; setupSPF=251[ubyte],40959[uword]
; prepare function stack
__wolin_spf := 251 ; function stack ptr
__wolin_spf_hi := 251+1 ; function stack ptr
__wolin_spf_top := 40959 ; function stack top
__wolin_spf_top_hi := 40959+1 ; function stack top
lda #<__wolin_spf_top ; set function stack top
sta __wolin_spf
lda #>__wolin_spf_top
sta __wolin_spf+1
; setupSP=143[ubyte]
; prepare program stack
__wolin_sp_top := 143 ; program stack top
__wolin_sp_top_hi := 143+1 ; program stack top
ldx #__wolin_sp_top ; set program stack top
; setupHEAP=176[ubyte]
__wolin_this_ptr := 176
__wolin_this_ptr_hi := 176+1
; allocSPF,#0
; call__wolin_pl_qus_wolin_main[adr]
jsr __wolin_pl_qus_wolin_main
; ret
rts
; function__wolin_pl_qus_wolin_rasterProc
__wolin_pl_qus_wolin_rasterProc:
; let53280[ubyte]=#5[ubyte]
lda #5
sta 53280
; ret
rts
; function__wolin_pl_qus_wolin_main
__wolin_pl_qus_wolin_main:
; let788[uword]=__wolin_pl_qus_wolin_rasterProc[uword]
lda #<__wolin_pl_qus_wolin_rasterProc
sta 788
lda #>__wolin_pl_qus_wolin_rasterProc
sta 788+1
; ret
rts
; label__wolin_indirect_jsr
__wolin_indirect_jsr:
; goto65535[adr]
jmp 65535
Re: Wolin - a minimal Kotlin-like language compiler for 65xx
Posted: Fri Jan 17, 2020 9:27 am
by drogon
Update.
I forgot to mention that before but there was another reason for creating Wolin. An argument with some guy on C64 forum that you can open the border ONLY from assembler. He was unable to provide a reason for this ridiculous statement, though.
Hehe... Well done! I love this sort of stuff!
But no different, really, from being able to point an interrupt (if that's what it takes, I know nothing about the C64 hardware) to a function in C - it's done daily in just about every CPU that supports C ... So if not C, then anything else that can do the right thing at function entry/exit...
-Gordon