begun with converting builtin functions to new call convention

This commit is contained in:
Irmen de Jong 2020-11-02 22:45:46 +01:00
parent ebc2c614d7
commit e0c5ccc16b
8 changed files with 139 additions and 107 deletions

View File

@ -343,20 +343,16 @@ neg_f .proc
rts
.pend
abs_f .proc
; -- strip the sign bit on the stack
lda P8ESTACK_HI+3,x
and #$7f
sta P8ESTACK_HI+3,x
rts
abs_f_cc .proc
; -- push abs(AY) on stack
jsr abs_f_into_fac1_cc
jmp push_fac1
.pend
abs_f_into_fac1 .proc
; -- strip the sign bit on the stack, push stack into FAC1
lda P8ESTACK_HI+3,x
and #$7f
sta P8ESTACK_HI+3,x
jmp pop_float_fac1
abs_f_into_fac1_cc .proc
; -- FAC1 = abs(AY)
jsr floats.MOVFM
jmp floats.ABS
.pend
equal_f .proc

View File

@ -245,24 +245,27 @@ xor_w .proc
.pend
abs_b .proc
; -- push abs(byte) on stack (as byte)
lda P8ESTACK_LO+1,x
bmi neg_b
abs_b_cc .proc
; -- push abs(A) on stack (as byte)
jsr abs_b_into_A_cc
sta P8ESTACK_LO,x
dex
rts
.pend
abs_w .proc
; -- push abs(word) on stack (as word)
lda P8ESTACK_HI+1,x
bmi neg_w
abs_w_cc .proc
; -- push abs(AY) on stack (as word)
jsr abs_w_into_AY_cc
sta P8ESTACK_LO,x
tya
sta P8ESTACK_HI,x
dex
rts
.pend
abs_b_into_A .proc
; -- A = abs(pop stack byte)
inx
lda P8ESTACK_LO,x
abs_b_into_A_cc .proc
; -- A = abs(A)
cmp #0
bmi +
rts
+ eor #$ff
@ -271,11 +274,9 @@ abs_b_into_A .proc
rts
.pend
abs_w_into_AY .proc
; -- AY = abs(pop stack word)
inx
lda P8ESTACK_LO,x
ldy P8ESTACK_HI,x
abs_w_into_AY_cc .proc
; -- AY = abs(AY)
cpy #0
bmi +
rts
+ eor #$ff
@ -1388,20 +1389,19 @@ func_rndw .proc
.pend
func_memcopy255 .proc
func_memcopy255_cc .proc
; fast memcopy of up to 255 bytes, note: clobbers A,Y
inx
; note: also uses the _arg variables from regular func_memcopy
stx P8ZP_SCRATCH_REG
lda P8ESTACK_LO+2,x
lda func_memcopy_cc._arg_from
sta P8ZP_SCRATCH_W1
lda P8ESTACK_HI+2,x
lda func_memcopy_cc._arg_from+1
sta P8ZP_SCRATCH_W1+1
lda P8ESTACK_LO+1,x
lda func_memcopy_cc._arg_to
sta P8ZP_SCRATCH_W2
lda P8ESTACK_HI+1,x
lda func_memcopy_cc._arg_to+1
sta P8ZP_SCRATCH_W2+1
lda P8ESTACK_LO,x
tax
ldx func_memcopy_cc._arg_numbytes
ldy #0
- lda (P8ZP_SCRATCH_W1), y
sta (P8ZP_SCRATCH_W2), y
@ -1409,31 +1409,23 @@ func_memcopy255 .proc
dex
bne -
ldx P8ZP_SCRATCH_REG
inx
inx
rts
.pend
func_memcopy .proc
func_memcopy_cc .proc
; memcopy of any number of bytes, note: clobbers A,Y
inx
stx P8ZP_SCRATCH_REG
lda P8ESTACK_LO+2,x
lda _arg_from
sta P8ZP_SCRATCH_W1
lda P8ESTACK_HI+2,x
lda _arg_from+1
sta P8ZP_SCRATCH_W1+1
lda P8ESTACK_LO+1,x
lda _arg_to
sta P8ZP_SCRATCH_W2
lda P8ESTACK_HI+1,x
lda _arg_to+1
sta P8ZP_SCRATCH_W2+1
lda P8ESTACK_LO,x
pha
lda P8ESTACK_HI,x
pha
ldy #0
pla
tax
ldx _arg_numbytes+1
beq _remain
- lda (P8ZP_SCRATCH_W1),y ; move a page at a time
sta (P8ZP_SCRATCH_W2),y
@ -1443,8 +1435,7 @@ func_memcopy .proc
inc P8ZP_SCRATCH_W2+1
dex
bne -
_remain pla
tax
_remain ldx _arg_numbytes
beq _done
- lda (P8ZP_SCRATCH_W1),y ; move the remaining bytes
sta (P8ZP_SCRATCH_W2),y
@ -1453,54 +1444,52 @@ _remain pla
bne -
_done ldx P8ZP_SCRATCH_REG
inx
inx
rts
_arg_from .word 0
_arg_to .word 0
_arg_numbytes .word 0
.pend
func_memset .proc
func_memset_cc .proc
; note: clobbers A,Y
inx
stx P8ZP_SCRATCH_REG
lda P8ESTACK_LO+2,x
lda _arg_address
sta P8ZP_SCRATCH_W1
lda P8ESTACK_HI+2,x
lda _arg_address+1
sta P8ZP_SCRATCH_W1+1
lda P8ESTACK_LO+1,x
sta P8ZP_SCRATCH_B1
ldy P8ESTACK_HI+1,x
lda P8ESTACK_LO,x
ldx P8ZP_SCRATCH_B1
ldx _arg_numbytes
ldy _arg_numbytes+1
lda _arg_bytevalue
jsr memset
ldx P8ZP_SCRATCH_REG
inx
inx
rts
_arg_address .word 0
_arg_numbytes .word 0
_arg_bytevalue .byte 0
.pend
func_memsetw .proc
func_memsetw_cc .proc
; note: clobbers A,Y
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
inx
lda P8ESTACK_LO+2,x
sta P8ZP_SCRATCH_W1
lda P8ESTACK_HI+2,x
sta P8ZP_SCRATCH_W1+1
lda P8ESTACK_LO+1,x
sta P8ZP_SCRATCH_W2
lda P8ESTACK_HI+1,x
sta P8ZP_SCRATCH_W2+1
txa
pha
lda P8ESTACK_LO,x
ldy P8ESTACK_HI,x
lda _arg_address
sta P8ZP_SCRATCH_W1
lda _arg_address+1
sta P8ZP_SCRATCH_W1+1
lda _arg_numwords
sta P8ZP_SCRATCH_W2
lda _arg_numwords+1
sta P8ZP_SCRATCH_W2+1
lda _arg_wordvalue
ldy _arg_wordvalue+1
jsr memsetw
pla
tax
inx
inx
rts
_arg_address .word 0
_arg_numwords .word 0
_arg_wordvalue .word 0
.pend
strlen .proc
@ -1518,7 +1507,7 @@ strlen .proc
memcopy16_up .proc
; -- copy memory UP from (SCRATCH_ZPWORD1) to (SCRATCH_ZPWORD2) of length X/Y (16-bit, X=lo, Y=hi)
; -- copy memory UP from (P8ZP_SCRATCH_W1) to (P8ZP_SCRATCH_W2) of length X/Y (16-bit, X=lo, Y=hi)
; clobbers register A,X,Y
source = P8ZP_SCRATCH_W1
dest = P8ZP_SCRATCH_W2
@ -1546,7 +1535,7 @@ memcopy16_up .proc
memset .proc
; -- fill memory from (SCRATCH_ZPWORD1), length XY, with value in A.
; -- fill memory from (P8ZP_SCRATCH_W1), length XY, with value in A.
; clobbers X, Y
stx P8ZP_SCRATCH_B1
sty _save_reg
@ -1573,7 +1562,7 @@ _save_reg .byte 0
memsetw .proc
; -- fill memory from (SCRATCH_ZPWORD1) number of words in SCRATCH_ZPWORD2, with word value in AY.
; -- fill memory from (P8ZP_SCRATCH_W1) number of words in P8ZP_SCRATCH_W2, with word value in AY.
; clobbers A, X, Y
sta _mod1+1 ; self-modify
sty _mod1b+1 ; self-modify

View File

@ -110,7 +110,7 @@ internal object C64MachineDefinition: IMachineDefinition {
internal class C64Zeropage(options: CompilationOptions) : Zeropage(options) {
override val SCRATCH_B1 = 0x02 // temp storage for a single byte
override val SCRATCH_REG = 0x03 // temp storage for a register
override val SCRATCH_REG = 0x03 // temp storage for a register, must be B1+1
override val SCRATCH_W1 = 0xfb // temp storage 1 for a word $fb+$fc
override val SCRATCH_W2 = 0xfd // temp storage 2 for a word $fb+$fc

View File

@ -117,7 +117,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
if((count!=null && count <= 255) || countDt.istype(DataType.UBYTE) || countDt.istype(DataType.BYTE)) {
// fast memcopy of up to 255
translateArguments(fcall.args, func)
asmgen.out(" jsr prog8_lib.func_memcopy255")
asmgen.out(" jsr prog8_lib.func_memcopy255_cc")
return
}
@ -141,7 +141,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
}
"memsetw" -> {
translateArguments(fcall.args, func)
asmgen.out(" jsr prog8_lib.func_memsetw")
asmgen.out(" jsr prog8_lib.func_memsetw_cc")
}
}
} else {
@ -150,12 +150,12 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
val countDt = fcall.args[2].inferType(program)
if((count!=null && count <= 255) || countDt.istype(DataType.UBYTE) || countDt.istype(DataType.BYTE)) {
translateArguments(fcall.args, func)
asmgen.out(" jsr prog8_lib.func_memcopy255")
asmgen.out(" jsr prog8_lib.func_memcopy255_cc")
return
}
}
translateArguments(fcall.args, func)
asmgen.out(" jsr prog8_lib.func_${func.name}")
asmgen.out(" jsr prog8_lib.func_${func.name}_cc")
}
}
@ -937,16 +937,16 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
val dt = fcall.args.single().inferType(program).typeOrElse(DataType.STRUCT)
if(resultToStack) {
when (dt) {
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b")
in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w")
DataType.FLOAT -> asmgen.out(" jsr floats.abs_f")
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_cc")
in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w_cc")
DataType.FLOAT -> asmgen.out(" jsr floats.abs_f_cc")
else -> throw AssemblyError("weird type")
}
} else {
when (dt) {
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_into_A")
in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w_into_AY")
DataType.FLOAT -> asmgen.out(" jsr floats.abs_f_into_fac1")
in ByteDatatypes -> asmgen.out(" jsr prog8_lib.abs_b_into_A_cc")
in WordDatatypes -> asmgen.out(" jsr prog8_lib.abs_w_into_AY_cc")
DataType.FLOAT -> asmgen.out(" jsr floats.abs_f_into_fac1_cc")
else -> throw AssemblyError("weird type")
}
}
@ -1052,7 +1052,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program, private val
val value = it.first.first
when {
conv.variable -> {
val varname = "prog8_lib.func_${signature.name}_cc.arg_${paramName}" // TODO after all builtin funcs have been changed into _cc, remove that suffix again
val varname = "prog8_lib.func_${signature.name}_cc._arg_${paramName}" // TODO after all builtin funcs have been changed into _cc, remove that suffix again
val src = AsmAssignSource.fromAstSource(value, program, asmgen)
val tgt = AsmAssignTarget(TargetStorageKind.VARIABLE, program, asmgen, conv.dt, null, variableAsmName = varname)
val assign = AsmAssignment(src, tgt, false, value.position)

View File

@ -75,7 +75,7 @@ internal object CX16MachineDefinition: IMachineDefinition {
internal class CX16Zeropage(options: CompilationOptions) : Zeropage(options) {
override val SCRATCH_B1 = 0x79 // temp storage for a single byte
override val SCRATCH_REG = 0x7a // temp storage for a register
override val SCRATCH_REG = 0x7a // temp storage for a register, must be B1+1
override val SCRATCH_W1 = 0x7c // temp storage 1 for a word $7c+$7d
override val SCRATCH_W2 = 0x7e // temp storage 2 for a word $7e+$7f

View File

@ -5,8 +5,6 @@ import org.hamcrest.Matchers.closeTo
import org.hamcrest.Matchers.equalTo
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import prog8.ast.Module
import prog8.ast.Program
import prog8.ast.base.*
import prog8.ast.expressions.*
import prog8.ast.statements.*
@ -18,8 +16,8 @@ import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_NEGATIVE
import prog8.compiler.target.c64.C64MachineDefinition.FLOAT_MAX_POSITIVE
import prog8.compiler.target.c64.C64MachineDefinition.Mflpt5
import prog8.compiler.target.c64.Petscii
import prog8.compiler.target.cx16.CX16MachineDefinition
import java.io.CharConversionException
import java.nio.file.Path
import kotlin.test.*
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ -288,6 +286,22 @@ class TestC64Zeropage {
assertEquals(0xf9, zp.allocate("", DataType.UBYTE, null, errors))
assertEquals(0, zp.available())
}
@Test
fun testReservedLocations() {
val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false))
assertEquals(zp.SCRATCH_REG, zp.SCRATCH_B1+1, "zp _B1 and _REG must be next to each other to create a word")
}
}
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestCx16Zeropage {
@Test
fun testReservedLocations() {
val zp = CX16MachineDefinition.CX16Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), false, false))
assertEquals(zp.SCRATCH_REG, zp.SCRATCH_B1+1, "zp _B1 and _REG must be next to each other to create a word")
}
}

View File

@ -2,6 +2,7 @@
TODO
====
- 64tass doesn't output all labels anymore in the vice-mon-list, so %breakpoint labels are no longer present....
- calling convention for builtin functions no longer via stack but via registers or statically allocated vars inside the subroutine proc (like normal subroutines)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)

View File

@ -11,20 +11,37 @@ main {
sub start() {
const uword ADDR = $0400
byte zerob=0
word zerow=0
float zerof=0
byte bb
word ww
float fl
bb = abs(bb)
ww = abs(ww)
fl = abs(fl)
testX()
bb = -100
bb = zerob+abs(bb)
txt.print_b(bb)
txt.chrout('\n')
memset(ADDR, 40*25, 100)
memsetw(ADDR, 20*10, $3031)
memcopy(ADDR, ADDR+40*12, 20*10*2)
ww = -12345
ww = zerow+abs(ww)
txt.print_w(ww)
txt.chrout('\n')
fl = -9.876
fl = zerof+abs(fl)
floats.print_f(fl)
txt.chrout('\n')
; memset(ADDR, 40*25, 100)
; memsetw(ADDR, 20*10, $3031)
; memcopy(ADDR, ADDR+40*12, 20*10*2)
testX()
bb++
}
asmsub testX() {
@ -32,8 +49,23 @@ main {
stx _saveX
lda #13
jsr txt.chrout
lda #'x'
jsr txt.chrout
lda #'='
jsr txt.chrout
lda _saveX
jsr txt.print_ub
lda #' '
jsr txt.chrout
lda #'s'
jsr txt.chrout
lda #'p'
jsr txt.chrout
lda #'='
jsr txt.chrout
tsx
txa
jsr txt.print_ub
lda #13
jsr txt.chrout
ldx _saveX