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),
"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),
"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")

View File

@ -206,6 +206,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
sty (+)+2
+ jsr 0 ; modified""")
}
// note: the routine can return a word value (in AY)
}
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])
addToResult(result, addressTr, addressTr.resultReg, -1)
addInstr(result, IRInstruction(Opcode.CALLI, reg1 = addressTr.resultReg), null)
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 {

View File

@ -64,7 +64,7 @@ verafx {
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
; 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_ADDR_H = srcbank | %00010000 ; source: 1-byte increment
cx16.VERA_ADDR_M = msb(srcaddr)

View File

@ -88,18 +88,17 @@ main {
main {
sub start() {
uword func = 12345
call(func) ; ok
call(12345) ; ok
cx16.r0 = call(func) ; error
call(&start) ; error
call(start) ; error
void call(func) ; ok
void call(12345) ; ok
cx16.r0 = call(func) ; ok
void call(&start) ; error
void call(start) ; error
}
}"""
val errors = ErrorReporterForTests()
compileText(Cx16Target(), false, src, errors, false) shouldBe null
errors.errors.size shouldBe 3
errors.errors[0] shouldContain ":7:19: assignment right hand side doesn't result in a value"
errors.errors.size shouldBe 2
errors.errors[0] 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``
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".
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``
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.
You can only treat it as a pointer or use it in inline assembly.
call (address)
Calls a subroutine given by its memory address. You cannot pass arguments and result values
directly, although it is ofcourse possible to do this via the global ``cx16.r0...`` registers for example.
call (address) -> uword
Calls a subroutine given by its memory address. You cannot pass arguments directly,
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.
But because it doesn't handle bank switching
etcetera by itself, it is a lot faster than ``callfar``. And it works on other systems than just the Commander X16.
But because it doesn't handle bank switching etcetera by itself,
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
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)
- 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: 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)

View File

@ -1,51 +1,18 @@
%import textio
%import verafx
%import diskio
%zeropage dontuse
%zeropage basicsafe
main {
sub start() {
txt.uppercase()
txt.print("abcdefghijklmnopqrstuvwxyz\n")
txt.print("ABCDEFGHIJKLMNOPQRSTUVWXYZ\n")
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())
uword function = &test
uword @shared derp = call(function)
txt.print_uw(derp)
txt.nl()
sys.wait(60)
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()
void call(function)
}
sub slowcopy(ubyte srcbank, uword srcaddr, ubyte tgtbank, uword tgtaddr, uword num_longwords) {
cx16.vaddr(srcbank, srcaddr, 0, 1)
cx16.vaddr(tgtbank, tgtaddr, 1, 1)
repeat num_longwords {
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
sub test() -> uword {
txt.print("test\n")
cx16.r0++
return 999
}
}