mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
vm: add sorting and reverse functions, fix value arg out of range errors
This commit is contained in:
parent
d78bfcc35c
commit
8e4c0f7c22
@ -4,6 +4,7 @@ import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.IAssemblyProgram
|
||||
import prog8.vm.Instruction
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.OpcodesWithAddress
|
||||
import prog8.vm.VmDataType
|
||||
import java.io.BufferedWriter
|
||||
import kotlin.io.path.bufferedWriter
|
||||
@ -66,7 +67,7 @@ internal class VmCodeInstruction(
|
||||
val ins = Instruction(opcode, type, reg1, reg2, reg3, value, symbol)
|
||||
|
||||
init {
|
||||
if(value!=null) {
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
|
@ -1,8 +1,12 @@
|
||||
package prog8.codegen.virtual
|
||||
|
||||
import prog8.code.StArray
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.ast.PtBuiltinFunctionCall
|
||||
import prog8.code.ast.PtIdentifier
|
||||
import prog8.code.ast.PtNumber
|
||||
import prog8.code.ast.PtString
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.WordDatatypes
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.Syscall
|
||||
@ -127,6 +131,37 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
if(resultRegister!=0)
|
||||
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
}
|
||||
"sort" -> {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||
val sortSyscall =
|
||||
when(array.dt) {
|
||||
DataType.ARRAY_UB -> Syscall.SORT_UBYTE
|
||||
DataType.ARRAY_B -> Syscall.SORT_BYTE
|
||||
DataType.ARRAY_UW -> Syscall.SORT_UWORD
|
||||
DataType.ARRAY_W -> Syscall.SORT_WORD
|
||||
DataType.FLOAT -> TODO("float sort")
|
||||
DataType.STR -> Syscall.SORT_UBYTE
|
||||
else -> throw IllegalArgumentException("weird type to sort")
|
||||
}
|
||||
code += exprGen.translateExpression(call.args[0], 0)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||
}
|
||||
"reverse" -> {
|
||||
val arrayName = call.args[0] as PtIdentifier
|
||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||
val sortSyscall =
|
||||
when(array.dt) {
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> Syscall.REVERSE_BYTES
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.REVERSE_WORDS
|
||||
DataType.FLOAT -> TODO("reverse floats")
|
||||
else -> throw IllegalArgumentException("weird type to reverse")
|
||||
}
|
||||
code += exprGen.translateExpression(call.args[0], 0)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||
}
|
||||
else -> {
|
||||
TODO("builtinfunc ${call.name}")
|
||||
// code += VmCodeInstruction(Opcode.NOP))
|
||||
|
@ -3,6 +3,7 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- add -vm option to load an existing p8virt file directly in the virtual machine
|
||||
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
||||
- writeAssembly(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
||||
|
@ -1,5 +1,4 @@
|
||||
%import textio
|
||||
%import test_stack
|
||||
%zeropage basicsafe
|
||||
|
||||
; Note: this program is compatible with C64 and CX16.
|
||||
|
@ -132,7 +132,7 @@ class Assembler {
|
||||
throw IllegalArgumentException("invalid reg3 for $line")
|
||||
if(!format.value && value!=null)
|
||||
throw IllegalArgumentException("invalid value for $line")
|
||||
if(value!=null) {
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
@ -161,6 +161,9 @@ class Assembler {
|
||||
}
|
||||
|
||||
private fun parseValue(value: String, pc: Int): Int {
|
||||
if(value.startsWith("-")) {
|
||||
return -parseValue(value.substring(1), pc)
|
||||
}
|
||||
if(value.startsWith('$'))
|
||||
return value.substring(1).toInt(16)
|
||||
if(value.startsWith('%'))
|
||||
|
@ -214,6 +214,16 @@ enum class Opcode {
|
||||
BREAKPOINT
|
||||
}
|
||||
|
||||
val OpcodesWithAddress = setOf(
|
||||
Opcode.LOADM,
|
||||
Opcode.LOADX,
|
||||
Opcode.STOREM,
|
||||
Opcode.STOREX,
|
||||
Opcode.STOREZ,
|
||||
Opcode.STOREZX
|
||||
)
|
||||
|
||||
|
||||
enum class VmDataType {
|
||||
BYTE,
|
||||
WORD
|
||||
|
@ -22,6 +22,12 @@ SYSCALLS:
|
||||
13 = waitvsync ; wait on vsync
|
||||
14 = sin8u
|
||||
15 = cos8u
|
||||
16 = sort_ubyte array
|
||||
17 = sort_byte array
|
||||
18 = sort_uword array
|
||||
19 = sort_word array
|
||||
20 = reverse_bytes array
|
||||
21 = reverse_words array
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -40,7 +46,13 @@ enum class Syscall {
|
||||
WAIT,
|
||||
WAITVSYNC,
|
||||
SIN8U,
|
||||
COS8U
|
||||
COS8U,
|
||||
SORT_UBYTE,
|
||||
SORT_BYTE,
|
||||
SORT_UWORD,
|
||||
SORT_WORD,
|
||||
REVERSE_BYTES,
|
||||
REVERSE_WORDS
|
||||
}
|
||||
|
||||
object SysCalls {
|
||||
@ -107,6 +119,66 @@ object SysCalls {
|
||||
val answer = truncate(128.0 + 127.5 * cos(rad))
|
||||
vm.registers.setUB(0, answer.toUInt().toUByte())
|
||||
}
|
||||
Syscall.SORT_UBYTE -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getUB(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUB(address+index, value)
|
||||
}
|
||||
}
|
||||
Syscall.SORT_BYTE -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getSB(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setSB(address+index, value)
|
||||
}
|
||||
}
|
||||
Syscall.SORT_UWORD -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getUW(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUW(address+index*2, value)
|
||||
}
|
||||
}
|
||||
Syscall.SORT_WORD -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getSW(it)
|
||||
}.sorted()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setSW(address+index*2, value)
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_BYTES -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length-1, 1).map {
|
||||
vm.memory.getUB(it)
|
||||
}.reversed()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUB(address+index, value)
|
||||
}
|
||||
}
|
||||
Syscall.REVERSE_WORDS -> {
|
||||
val address = vm.registers.getUW(0).toInt()
|
||||
val length = vm.registers.getUB(1).toInt()
|
||||
val array = IntProgression.fromClosedRange(address, address+length*2-2, 2).map {
|
||||
vm.memory.getUW(it)
|
||||
}.reversed()
|
||||
array.withIndex().forEach { (index, value)->
|
||||
vm.memory.setUW(address+index*2, value)
|
||||
}
|
||||
}
|
||||
else -> TODO("syscall ${call.name}")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user