call now returns a word value

This commit is contained in:
Irmen de Jong 2023-12-22 22:24:11 +01:00
parent 6cd392909c
commit ad9eaeafeb
9 changed files with 32 additions and 59 deletions

View File

@ -133,7 +133,7 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
"rrestore" to FSignature(false, emptyList(), null), "rrestore" to FSignature(false, emptyList(), null),
"memory" to FSignature(true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD), "memory" to FSignature(true, listOf(FParam("name", arrayOf(DataType.STR)), FParam("size", arrayOf(DataType.UWORD)), FParam("alignment", arrayOf(DataType.UWORD))), DataType.UWORD),
"callfar" to FSignature(false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), DataType.UWORD), "callfar" to FSignature(false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), DataType.UWORD),
"call" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD))), null), "call" to FSignature(false, listOf(FParam("address", arrayOf(DataType.UWORD))), DataType.UWORD),
) )
val InplaceModifyingBuiltinFunctions = setOf("setlsb", "setmsb", "rol", "ror", "rol2", "ror2", "sort", "reverse") val InplaceModifyingBuiltinFunctions = setOf("setlsb", "setmsb", "rol", "ror", "rol2", "ror2", "sort", "reverse")

View File

@ -206,6 +206,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
sty (+)+2 sty (+)+2
+ jsr 0 ; modified""") + jsr 0 ; modified""")
} }
// note: the routine can return a word value (in AY)
} }
private fun funcCallFar(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) { private fun funcCallFar(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {

View File

@ -77,7 +77,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val addressTr = exprGen.translateExpression(call.args[0]) val addressTr = exprGen.translateExpression(call.args[0])
addToResult(result, addressTr, addressTr.resultReg, -1) addToResult(result, addressTr, addressTr.resultReg, -1)
addInstr(result, IRInstruction(Opcode.CALLI, reg1 = addressTr.resultReg), null) addInstr(result, IRInstruction(Opcode.CALLI, reg1 = addressTr.resultReg), null)
return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1) if(call.void)
return ExpressionCodeResult(result, IRDataType.BYTE, -1, -1)
else
return ExpressionCodeResult(result, IRDataType.WORD, codeGen.registers.nextFree(), -1) // TODO actually the result is returned in CPU registers AY...
} }
private fun funcCallfar(call: PtBuiltinFunctionCall): ExpressionCodeResult { private fun funcCallfar(call: PtBuiltinFunctionCall): ExpressionCodeResult {

View File

@ -64,7 +64,7 @@ verafx {
sub copy(ubyte srcbank, uword srcaddr, ubyte tgtbank, uword tgtaddr, uword num_longwords) { sub copy(ubyte srcbank, uword srcaddr, ubyte tgtbank, uword tgtaddr, uword num_longwords) {
; use cached 4-byte writes to quickly copy a portion of the video memory to somewhere else ; use cached 4-byte writes to quickly copy a portion of the video memory to somewhere else
; this routine is around 40-50% faster as a plain byte-by-byte copy ; this routine is about 50% faster as a plain byte-by-byte copy
cx16.VERA_CTRL = 1 cx16.VERA_CTRL = 1
cx16.VERA_ADDR_H = srcbank | %00010000 ; source: 1-byte increment cx16.VERA_ADDR_H = srcbank | %00010000 ; source: 1-byte increment
cx16.VERA_ADDR_M = msb(srcaddr) cx16.VERA_ADDR_M = msb(srcaddr)

View File

@ -88,18 +88,17 @@ main {
main { main {
sub start() { sub start() {
uword func = 12345 uword func = 12345
call(func) ; ok void call(func) ; ok
call(12345) ; ok void call(12345) ; ok
cx16.r0 = call(func) ; error cx16.r0 = call(func) ; ok
call(&start) ; error void call(&start) ; error
call(start) ; error void call(start) ; error
} }
}""" }"""
val errors = ErrorReporterForTests() val errors = ErrorReporterForTests()
compileText(Cx16Target(), false, src, errors, false) shouldBe null compileText(Cx16Target(), false, src, errors, false) shouldBe null
errors.errors.size shouldBe 3 errors.errors.size shouldBe 2
errors.errors[0] shouldContain ":7:19: assignment right hand side doesn't result in a value" errors.errors[0] shouldContain "can't call this indirectly"
errors.errors[1] shouldContain "can't call this indirectly" errors.errors[1] shouldContain "can't call this indirectly"
errors.errors[2] shouldContain "can't call this indirectly"
} }
}) })

View File

@ -628,7 +628,7 @@ the emulators already support it).
``copy`` ``copy``
Very quickly copy a portion of the video memory to somewhere else in vram (4 bytes at a time) Very quickly copy a portion of the video memory to somewhere else in vram (4 bytes at a time)
Sometimes this is also called "blitting". Sometimes this is also called "blitting".
This routine is around 40-50% faster as a regular byte-by-byte copy. This routine is about 50% faster as a regular byte-by-byte copy.
``transparency`` ``transparency``
Enable or disable transparent writes (color 0 will be transparent if enabled). Enable or disable transparent writes (color 0 will be transparent if enabled).

View File

@ -966,12 +966,13 @@ memory (name, size, alignment)
The return value is just a simple uword address so it cannot be used as an array in your program. The return value is just a simple uword address so it cannot be used as an array in your program.
You can only treat it as a pointer or use it in inline assembly. You can only treat it as a pointer or use it in inline assembly.
call (address) call (address) -> uword
Calls a subroutine given by its memory address. You cannot pass arguments and result values Calls a subroutine given by its memory address. You cannot pass arguments directly,
directly, although it is ofcourse possible to do this via the global ``cx16.r0...`` registers for example. although it is ofcourse possible to do this via the global ``cx16.r0...`` registers for example.
It is assumed the subroutine returns a word value (in AY), if it does not, just add void to the call to ignore the result value.
This function effectively creates an "indirect JSR" if you use it on a ``uword`` pointer variable. This function effectively creates an "indirect JSR" if you use it on a ``uword`` pointer variable.
But because it doesn't handle bank switching But because it doesn't handle bank switching etcetera by itself,
etcetera by itself, it is a lot faster than ``callfar``. And it works on other systems than just the Commander X16. it is a lot faster than ``callfar``. And it works on other systems than just the Commander X16.
callfar (bank, address, argumentword) -> uword ; NOTE: specific to cx16 target for now callfar (bank, address, argumentword) -> uword ; NOTE: specific to cx16 target for now
Calls an assembly routine in another bank on the Commander X16 (using its ``JSRFAR`` routine) Calls an assembly routine in another bank on the Commander X16 (using its ``JSRFAR`` routine)

View File

@ -27,6 +27,7 @@ Compiler:
- (need separate step in codegen and IR to write the "golden" variables) - (need separate step in codegen and IR to write the "golden" variables)
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block? - do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
- ir: proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
- ir: getting it in shape for code generation - ir: getting it in shape for code generation
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really - ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
- ir: idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype) - ir: idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype)

View File

@ -1,51 +1,18 @@
%import textio %import textio
%import verafx %zeropage basicsafe
%import diskio
%zeropage dontuse
main { main {
sub start() { sub start() {
txt.uppercase() uword function = &test
txt.print("abcdefghijklmnopqrstuvwxyz\n") uword @shared derp = call(function)
txt.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n") txt.print_uw(derp)
txt.print("0123456789!@#$%^&*()-=[]<>\n")
void diskio.vload_raw("fantasy.pf", 0, $4000)
; for cx16.r0 in $4000 to $4000+256*$0008 {
; cx16.vpoke(0, cx16.r0, %10101010)
; }
cbm.SETTIM(0,0,0)
repeat 1000 {
slowcopy(0, $4000, 1, $f000, 8*256/4)
}
txt.print("\nslow copy time: ")
txt.print_uw(cbm.RDTIM16())
txt.nl() txt.nl()
sys.wait(60) void call(function)
txt.lowercase()
sys.wait(120)
cbm.SETTIM(0,0,0)
repeat 1000 {
verafx.copy(0, $4000, 1, $f000, 8*256/4)
}
txt.print("verafx copy time: ")
txt.print_uw(cbm.RDTIM16())
txt.nl()
sys.wait(60)
; txt.uppercase()
} }
sub slowcopy(ubyte srcbank, uword srcaddr, ubyte tgtbank, uword tgtaddr, uword num_longwords) { sub test() -> uword {
cx16.vaddr(srcbank, srcaddr, 0, 1) txt.print("test\n")
cx16.vaddr(tgtbank, tgtaddr, 1, 1) cx16.r0++
repeat num_longwords { return 999
cx16.VERA_DATA1=cx16.VERA_DATA0
cx16.VERA_DATA1=cx16.VERA_DATA0
cx16.VERA_DATA1=cx16.VERA_DATA0
cx16.VERA_DATA1=cx16.VERA_DATA0
}
cx16.VERA_CTRL = 0
} }
} }