mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
better codegen for call() function
This commit is contained in:
parent
df35aa7942
commit
a064ade1e0
@ -266,23 +266,40 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun funcCall(fcall: PtBuiltinFunctionCall) {
|
private fun funcCall(fcall: PtBuiltinFunctionCall) {
|
||||||
|
// note: the routine can return a word value (in AY)
|
||||||
val constAddr = fcall.args[0].asConstInteger()
|
val constAddr = fcall.args[0].asConstInteger()
|
||||||
if(constAddr!=null) {
|
if(constAddr!=null) {
|
||||||
asmgen.out(" jsr ${constAddr.toHex()}")
|
asmgen.out(" jsr ${constAddr.toHex()}")
|
||||||
} else {
|
return
|
||||||
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY) // jump address
|
|
||||||
asmgen.out("""
|
|
||||||
sta (+)+1
|
|
||||||
sty (+)+2
|
|
||||||
+ jsr 0 ; modified""")
|
|
||||||
// TODO: avoid using modifying code here by pushing return address on the stack manually and use JMP (INDIRECT) ? And if it's just a variable, simply JMP (variable) !
|
|
||||||
// TODO: also do this for CallFar below!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: the routine can return a word value (in AY)
|
val identifier = fcall.args[0] as? PtIdentifier
|
||||||
|
if(identifier!=null) {
|
||||||
|
asmgen.out("""
|
||||||
|
; push a return address so the jmp becomes indirect jsr
|
||||||
|
lda #>((+)-1)
|
||||||
|
pha
|
||||||
|
lda #<((+)-1)
|
||||||
|
pha
|
||||||
|
jmp (${asmgen.asmSymbolName(identifier)})
|
||||||
|
+""")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
asmgen.assignExpressionToVariable(fcall.args[0], asmgen.asmVariableName("P8ZP_SCRATCH_W2"), DataType.UWORD) // jump address
|
||||||
|
asmgen.out("""
|
||||||
|
; push a return address so the jmp becomes indirect jsr
|
||||||
|
lda #>((+)-1)
|
||||||
|
pha
|
||||||
|
lda #<((+)-1)
|
||||||
|
pha
|
||||||
|
jmp (P8ZP_SCRATCH_W2)
|
||||||
|
+""")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcCallFar(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
private fun funcCallFar(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||||
|
// TODO apply same optimizations here as used on call() codegen above
|
||||||
|
|
||||||
if(asmgen.options.compTarget.name != "cx16")
|
if(asmgen.options.compTarget.name != "cx16")
|
||||||
throw AssemblyError("callfar only works on cx16 target at this time")
|
throw AssemblyError("callfar only works on cx16 target at this time")
|
||||||
|
|
||||||
|
@ -1346,7 +1346,7 @@ internal class AstChecker(private val program: Program,
|
|||||||
if(target.name=="call") {
|
if(target.name=="call") {
|
||||||
if(args[0] is AddressOf)
|
if(args[0] is AddressOf)
|
||||||
errors.err("can't call this indirectly, just use normal function call syntax", args[0].position)
|
errors.err("can't call this indirectly, just use normal function call syntax", args[0].position)
|
||||||
if(args[0] is IdentifierReference) {
|
else if(args[0] is IdentifierReference) {
|
||||||
val callTarget = (args[0] as IdentifierReference).targetStatement(program)
|
val callTarget = (args[0] as IdentifierReference).targetStatement(program)
|
||||||
if(callTarget !is VarDecl)
|
if(callTarget !is VarDecl)
|
||||||
errors.err("can't call this indirectly, just use normal function call syntax", args[0].position)
|
errors.err("can't call this indirectly, just use normal function call syntax", args[0].position)
|
||||||
|
@ -92,8 +92,11 @@ main {
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
uword func = 12345
|
uword func = 12345
|
||||||
|
uword[] pointers = [1234,6789]
|
||||||
void call(func) ; ok
|
void call(func) ; ok
|
||||||
void call(12345) ; ok
|
void call(12345) ; ok
|
||||||
|
void call(pointers[1]) ; ok
|
||||||
|
void call(cx16.r0+10) ; ok
|
||||||
cx16.r0 = call(func) ; ok
|
cx16.r0 = call(func) ; ok
|
||||||
void call(&start) ; error
|
void call(&start) ; error
|
||||||
void call(start) ; error
|
void call(start) ; error
|
||||||
|
@ -5,9 +5,8 @@ Regenerate skeleton doc files.
|
|||||||
|
|
||||||
"invalid number of arguments" -> print the list of missing arguments
|
"invalid number of arguments" -> print the list of missing arguments
|
||||||
|
|
||||||
call() asm gen in funcCall() could be improved by not using modifying code , see the TODO.
|
callfar() should allow setting an argument in the X register as well? + similar optimizations that call() got.
|
||||||
|
|
||||||
callfar() should allow setting an argument in the X register as well?
|
|
||||||
|
|
||||||
Add a new SublimeText syntax file for prog8, and also install this for bat: https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
Add a new SublimeText syntax file for prog8, and also install this for bat: https://github.com/sharkdp/bat?tab=readme-ov-file#adding-new-syntaxes--language-definitions
|
||||||
|
|
||||||
@ -21,6 +20,7 @@ Future Things and Ideas
|
|||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Compiler:
|
Compiler:
|
||||||
|
|
||||||
|
- AST weirdness: why is call(...) a normal FunctionCallStatement and not a BuiltinFunctionCall? What does ror() produce for instance?
|
||||||
- Can we support signed % (remainder) somehow?
|
- Can we support signed % (remainder) somehow?
|
||||||
- Don't add "random" rts to %asm blocks but instead give a warning about it? (but this breaks existing behavior that others already depend on... command line switch? block directive?)
|
- Don't add "random" rts to %asm blocks but instead give a warning about it? (but this breaks existing behavior that others already depend on... command line switch? block directive?)
|
||||||
- IR: implement missing operators in AssignmentGen (array shifts etc)
|
- IR: implement missing operators in AssignmentGen (array shifts etc)
|
||||||
|
120
examples/test.p8
120
examples/test.p8
@ -1,115 +1,41 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import string
|
%import string
|
||||||
%import compression
|
%import compression
|
||||||
|
%import test_stack
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
%option no_sysinit
|
%option no_sysinit
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte[] rle = [
|
test_stack.test()
|
||||||
5, '1', '2', '3', '4', '5', '6',
|
example(function1, 42)
|
||||||
3, 'a', 'b', 'c', 'd',
|
example(function1, 99)
|
||||||
0, 'z',
|
example(function2, 42)
|
||||||
3, '1', '2', '3','4',
|
example(function2, 99)
|
||||||
-5, '=',
|
test_stack.test()
|
||||||
-127, '+',
|
cx16.r0++
|
||||||
4, '!', '@', '#', '$', '%',
|
|
||||||
128]
|
|
||||||
|
|
||||||
str @shared result = "\x00"*200
|
sub function1(ubyte arg) {
|
||||||
|
txt.print("function 1 arg=")
|
||||||
uword ptr = &rle
|
txt.print_ub(arg)
|
||||||
|
|
||||||
txt.print_uw(compression.decode_rle_srcfunc(callback, result, len(result)))
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw(compression.decode_rle(rle, result, len(result)))
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uw(string.length(result))
|
|
||||||
txt.nl()
|
|
||||||
txt.print(result)
|
|
||||||
txt.nl()
|
|
||||||
txt.print_uwhex(&result, true)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
sub callback() -> ubyte {
|
|
||||||
ubyte x = @(ptr)
|
|
||||||
ptr++
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ubyte[256] buffer
|
|
||||||
ubyte[256] buffer2
|
|
||||||
uword bufptr = &buffer
|
|
||||||
uword outputsize=0
|
|
||||||
|
|
||||||
sub outputter(ubyte value) {
|
|
||||||
@(bufptr) = value
|
|
||||||
bufptr++
|
|
||||||
outputsize++
|
|
||||||
}
|
|
||||||
|
|
||||||
str input = iso:"123456aaaaabcdzzz1234======++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++!@#$%"
|
|
||||||
ubyte[31] expected_rle = [$5, $31, $32, $33, $34, $35, $36, $fc, $61, $2, $62, $63, $64, $fe, $7a, $3, $31, $32, $33, $34, $fb, $3d, $81, $2b, $4, $21, $40, $23, $24, $25, $80]
|
|
||||||
txt.print(input)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
compression.encode_rle_outfunc(input, len(input), outputter, true)
|
|
||||||
txt.print_uw(outputsize)
|
|
||||||
txt.nl()
|
|
||||||
if outputsize!=len(expected_rle)
|
|
||||||
txt.print("wrong rle size!\n")
|
|
||||||
|
|
||||||
txt.print("\ncompare rle (encode using callback):\n")
|
|
||||||
for cx16.r9L in 0 to len(expected_rle)-1 {
|
|
||||||
; txt.print_ub0(cx16.r9L)
|
|
||||||
; txt.spc()
|
|
||||||
; txt.print_ubhex(expected_rle[cx16.r9L], false)
|
|
||||||
; txt.spc()
|
|
||||||
; txt.print_ubhex(buffer[cx16.r9L], false)
|
|
||||||
if buffer[cx16.r9L] != expected_rle[cx16.r9L]
|
|
||||||
txt.print(" wrong rle data!")
|
|
||||||
; txt.nl()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
cx16.r0 = compression.decode_rle(buffer, buffer2, len(buffer2))
|
|
||||||
if cx16.r0 != len(input)
|
|
||||||
txt.print("wrong decompress result!\n")
|
|
||||||
else {
|
|
||||||
txt.print("good result: ")
|
|
||||||
txt.print(buffer2)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub function2(ubyte arg) {
|
||||||
buffer[0] = buffer[1] = buffer[2] = 128
|
txt.print("function 2 arg=")
|
||||||
outputsize = compression.encode_rle(input, len(input), buffer, true)
|
txt.print_ub(arg)
|
||||||
txt.print_uw(outputsize)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
if outputsize!=len(expected_rle)
|
|
||||||
txt.print("wrong rle size!\n")
|
|
||||||
|
|
||||||
txt.print("\ncompare rle (encode into buffer):\n")
|
|
||||||
for cx16.r9L in 0 to len(expected_rle)-1 {
|
|
||||||
; txt.print_ub0(cx16.r9L)
|
|
||||||
; txt.spc()
|
|
||||||
; txt.print_ubhex(expected_rle[cx16.r9L], false)
|
|
||||||
; txt.spc()
|
|
||||||
; txt.print_ubhex(buffer[cx16.r9L], false)
|
|
||||||
if buffer[cx16.r9L] != expected_rle[cx16.r9L]
|
|
||||||
txt.print(" wrong rle data!")
|
|
||||||
; txt.nl()
|
|
||||||
}
|
}
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
cx16.r0 = compression.decode_rle(buffer, buffer2, len(buffer2))
|
sub example(uword function, ubyte value) {
|
||||||
if cx16.r0 != len(input)
|
|
||||||
txt.print("wrong decompress result!\n")
|
%asm {{
|
||||||
else {
|
lda p8v_value
|
||||||
txt.print("good result: ")
|
}}
|
||||||
txt.print(buffer2)
|
|
||||||
txt.nl()
|
call(function)
|
||||||
|
cx16.r1 = function+10
|
||||||
|
call(cx16.r1-10)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user