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

Code: Select all

free
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:

Code: Select all

var sprite0On: bool^0xd015@0
That would be very useful on C64, as it would make handling lot of I/O as simple as:

Code: Select all

sprite0On = true
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:

Code: Select all

someVariable .= 128+1

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!
qus wrote:
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.
Quote:
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
qus wrote:
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
qus wrote:
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