From e0c5ccc16be82b6892c0d53831ce2b2b7085e6a3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Mon, 2 Nov 2020 22:45:46 +0100 Subject: [PATCH] begun with converting builtin functions to new call convention --- compiler/res/prog8lib/c64/floats.asm | 20 ++- compiler/res/prog8lib/prog8_lib.asm | 135 ++++++++---------- .../target/c64/C64MachineDefinition.kt | 2 +- .../c64/codegen/BuiltinFunctionsAsmGen.kt | 22 +-- .../target/cx16/CX16MachineDefinition.kt | 2 +- compiler/test/UnitTests.kt | 20 ++- docs/source/todo.rst | 1 + examples/test.p8 | 44 +++++- 8 files changed, 139 insertions(+), 107 deletions(-) diff --git a/compiler/res/prog8lib/c64/floats.asm b/compiler/res/prog8lib/c64/floats.asm index 2b135abc2..255cc61f3 100644 --- a/compiler/res/prog8lib/c64/floats.asm +++ b/compiler/res/prog8lib/c64/floats.asm @@ -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 diff --git a/compiler/res/prog8lib/prog8_lib.asm b/compiler/res/prog8lib/prog8_lib.asm index e2efd4b7a..f8843213d 100644 --- a/compiler/res/prog8lib/prog8_lib.asm +++ b/compiler/res/prog8lib/prog8_lib.asm @@ -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 diff --git a/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt b/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt index e939f2541..3e57d3f9a 100644 --- a/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt +++ b/compiler/src/prog8/compiler/target/c64/C64MachineDefinition.kt @@ -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 diff --git a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt index 4aef72bb6..dd3355459 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/BuiltinFunctionsAsmGen.kt @@ -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) diff --git a/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt b/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt index 091ce5827..dfe174103 100644 --- a/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt +++ b/compiler/src/prog8/compiler/target/cx16/CX16MachineDefinition.kt @@ -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 diff --git a/compiler/test/UnitTests.kt b/compiler/test/UnitTests.kt index 236e96550..a617280d2 100644 --- a/compiler/test/UnitTests.kt +++ b/compiler/test/UnitTests.kt @@ -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") + } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 323b7265c..349f04fc8 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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) diff --git a/examples/test.p8 b/examples/test.p8 index dbe4f810a..c7bf03fbc 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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