fix sort and reverse on strings on 6502 codegen

This commit is contained in:
Irmen de Jong 2023-04-10 18:43:51 +02:00
parent dd1592b03b
commit 7c1d5cadd7
9 changed files with 59 additions and 27 deletions

View File

@ -1,5 +1,6 @@
package prog8.codegen.cpu6502
import prog8.code.StStaticVariable
import prog8.code.ast.*
import prog8.code.core.*
import prog8.codegen.cpu6502.assignment.*
@ -337,6 +338,16 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
lda #$numElements
jsr prog8_lib.func_reverse_w""")
}
DataType.STR -> {
val stringLength = (symbol as StStaticVariable).length!!-1
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$stringLength
jsr prog8_lib.func_reverse_b""")
}
DataType.ARRAY_F -> {
asmgen.out("""
lda #<$varName
@ -381,6 +392,16 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
lda #$numElements""")
asmgen.out(if (decl.type == DataType.ARRAY_UW) " jsr prog8_lib.func_sort_uw" else " jsr prog8_lib.func_sort_w")
}
DataType.STR -> {
val stringLength = (symbol as StStaticVariable).length!!-1
asmgen.out("""
lda #<$varName
ldy #>$varName
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
lda #$stringLength
jsr prog8_lib.func_sort_ub""")
}
DataType.ARRAY_F -> throw AssemblyError("sorting of floating point array is not supported")
else -> throw AssemblyError("weird type")
}

View File

@ -273,7 +273,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
addToResult(result, tr, tr.resultReg, -1)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1 = tr.resultReg)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = tr.resultReg, immediate = array.length)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = tr.resultReg, immediate = if(array.dt==DataType.STR) array.length!!-1 else array.length)
it += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1 = tr.resultReg)
it += IRInstruction(Opcode.SYSCALL, immediate = syscall.number)
}
@ -298,7 +298,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
addToResult(result, tr, tr.resultReg, -1)
result += IRCodeChunk(null, null).also {
it += IRInstruction(Opcode.PUSH, IRDataType.WORD, reg1 = tr.resultReg)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = tr.resultReg, immediate = array.length)
it += IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = tr.resultReg, immediate = if(array.dt==DataType.STR) array.length!!-1 else array.length)
it += IRInstruction(Opcode.PUSH, IRDataType.BYTE, reg1 = tr.resultReg)
it += IRInstruction(Opcode.SYSCALL, immediate = syscall.number)
}

View File

@ -127,6 +127,8 @@ sub input_chars (uword buffer) -> ubyte {
%ir {{
loadm.w r65535,txt.input_chars.buffer
push.w r65535
load.b r65535,80
push.b r65535
syscall 6
pop.b r0
returnreg.b r0

View File

@ -3,8 +3,6 @@ TODO
For next minor release
^^^^^^^^^^^^^^^^^^^^^^
test vm array reverse, sort, string containment, string input, float array containment (how translated? there is no syscall)
...
@ -35,6 +33,9 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
Compiler:
- ir: investigate passing parameters to function calls using fixed set of regs r60000,r60001, etc.
these have to be offset somehow by the subroutine number (?) somehow to have a unique list of them per subroutine.
also only if we can optimize the subroutine to replace the parameter variables to those registers.
- ir: can we determine for the loop variable in forloops if it could be kept in a (virtual) register instead of a real variable? Need to be able to check if the variable is used by another statement beside just the for loop.
- ir: mechanism to determine for chunks which registers are getting input values from "outside"
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)

View File

@ -1,7 +1,6 @@
%import textio
%import conv
%import math
%import test_stack
%zeropage basicsafe
; The classic number guessing game.
@ -61,8 +60,6 @@ main {
txt.print("Thanks for playing, ")
txt.print(name)
txt.print(".\n")
; test_stack.test()
}
}
}

View File

@ -5,7 +5,18 @@
main {
sub start() {
math.rndseed(11111,22222)
str name = "irmen"
reverse(name)
txt.print(name)
txt.nl()
sort(name)
txt.print(name)
txt.nl()
txt.print_ub('@' in name)
txt.nl()
txt.print_ub('i' in name)
txt.nl()
sys.wait(60)
}
}

View File

@ -5,21 +5,21 @@ package prog8.intermediate
// Note that in the VM these are translated into whatever the corresponding Syscall number in the VM is.
enum class IMSyscall(val number: Int) {
SORT_UBYTE(10000),
SORT_BYTE(10001),
SORT_UWORD(10002),
SORT_WORD(10003),
ANY_BYTE(10004),
ANY_WORD(10005),
ANY_FLOAT(10006),
ALL_BYTE(10007),
ALL_WORD(10008),
ALL_FLOAT(10009),
REVERSE_BYTES(10010),
REVERSE_WORDS(10011),
REVERSE_FLOATS(10012),
COMPARE_STRINGS(10013),
STRING_CONTAINS(10014),
BYTEARRAY_CONTAINS(10015),
WORDARRAY_CONTAINS(10016)
SORT_UBYTE(0x1000),
SORT_BYTE(0x1001),
SORT_UWORD(0x1002),
SORT_WORD(0x1003),
ANY_BYTE(0x1004),
ANY_WORD(0x1005),
ANY_FLOAT(0x1006),
ALL_BYTE(0x1007),
ALL_WORD(0x1008),
ALL_FLOAT(0x1009),
REVERSE_BYTES(0x100a),
REVERSE_WORDS(0x100b),
REVERSE_FLOATS(0x100c),
COMPARE_STRINGS(0x100d),
STRING_CONTAINS(0x100e),
BYTEARRAY_CONTAINS(0x100f),
WORDARRAY_CONTAINS(0x1010)
}

View File

@ -119,7 +119,7 @@ object SysCalls {
if(maxlen>0)
input = input.substring(0, min(input.length, maxlen))
vm.memory.setString(vm.valueStack.popw().toInt(), input, true)
vm.valueStack.pushw(input.length.toUShort())
vm.valueStack.push(input.length.toUByte())
}
Syscall.SLEEP -> {
val duration = vm.valueStack.popw().toLong()

View File

@ -2299,7 +2299,7 @@ class VirtualMachine(irProgram: IRProgram) {
val y = valueStack.popw()
val x = valueStack.popw()
val color = Color(window!!.getpixel(x.toInt(), y.toInt()))
registers.setUB(0, color.green.toUByte())
valueStack.push(color.green.toUByte()) // gets called from a syscall, return value via stack.
}
}