mirror of
https://github.com/irmen/prog8.git
synced 2026-04-19 20:16:51 +00:00
implementing more of the vm
This commit is contained in:
@@ -56,9 +56,9 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtNop -> VmCodeChunk()
|
||||
is PtReturn -> translate(node)
|
||||
is PtJump -> translate(node)
|
||||
is PtWhen -> TODO()
|
||||
is PtWhen -> TODO("when")
|
||||
is PtPipe -> expressionEval.translate(node, regUsage.nextFree(), regUsage)
|
||||
is PtForLoop -> TODO()
|
||||
is PtForLoop -> TODO("for-loop")
|
||||
is PtIfElse -> translate(node, regUsage)
|
||||
is PtPostIncrDecr -> translate(node, regUsage)
|
||||
is PtRepeatLoop -> translate(node, regUsage)
|
||||
@@ -219,7 +219,19 @@ class CodeGen(internal val program: PtProgram,
|
||||
code += VmCodeInstruction(ins)
|
||||
}
|
||||
else if(array!=null) {
|
||||
TODO("assign to array")
|
||||
val variable = array.variable.targetName
|
||||
var variableAddr = allocations.get(variable)
|
||||
val itemsize = program.memsizer.memorySize(array.type)
|
||||
val fixedIndex = (array.index as? PtNumber)?.number?.toInt()
|
||||
val vmDtArrayIdx = vmType(array.type)
|
||||
if(fixedIndex!=null) {
|
||||
variableAddr += fixedIndex*itemsize
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOADM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr))
|
||||
} else {
|
||||
val indexReg = regUsage.nextFree()
|
||||
code += expressionEval.translateExpression(array.index, indexReg, regUsage)
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOADX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr))
|
||||
}
|
||||
}
|
||||
else if(memory!=null) {
|
||||
val ins =
|
||||
|
||||
@@ -365,16 +365,58 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
val name = (call.args[0] as PtString).value
|
||||
val size = (call.args[1] as PtNumber).number.toUInt()
|
||||
val align = (call.args[2] as PtNumber).number.toUInt()
|
||||
TODO("Memory($name, $size, $align)")
|
||||
val existing = codeGen.allocations.getMemorySlab(name)
|
||||
val address = if(existing==null)
|
||||
codeGen.allocations.allocateMemorySlab(name, size, align)
|
||||
else if(existing.second!=size || existing.third!=align) {
|
||||
codeGen.errors.err("memory slab '$name' already exists with a different size or alignment", call.position)
|
||||
return VmCodeChunk()
|
||||
}
|
||||
else
|
||||
existing.first
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, value=address.toInt()))
|
||||
}
|
||||
"rnd" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=Syscall.RND.ordinal))
|
||||
if(resultRegister!=0)
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0))
|
||||
}
|
||||
"peek" -> {
|
||||
val addressReg = regUsage.nextFree()
|
||||
code += translateExpression(call.args.single(), addressReg, regUsage)
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg))
|
||||
}
|
||||
"peekw" -> {
|
||||
val addressReg = regUsage.nextFree()
|
||||
code += translateExpression(call.args.single(), addressReg, regUsage)
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg))
|
||||
}
|
||||
"memory" -> {
|
||||
val memname = (call.args[0] as PtString).value
|
||||
val size = (call.args[1] as PtNumber).number.toInt()
|
||||
val align = (call.args[2] as PtNumber).number.toInt()
|
||||
TODO("memory '$memname', $size, $align")
|
||||
}
|
||||
else -> {
|
||||
// TODO builtin functions...
|
||||
TODO("builtinfunc ${call.name}")
|
||||
// code += VmCodeInstruction(Instruction(Opcode.NOP))
|
||||
// for (arg in call.args) {
|
||||
// code += translateExpression(arg, resultRegister, regUsage)
|
||||
// code += when(arg.type) {
|
||||
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1=resultRegister))
|
||||
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1=resultRegister))
|
||||
// else -> throw AssemblyError("weird arg dt")
|
||||
// }
|
||||
// }
|
||||
// code += VmCodeInstruction(Instruction(Opcode.CALL), labelArg = listOf("_prog8_builtin", call.name))
|
||||
// for (arg in call.args) {
|
||||
// code += when(arg.type) {
|
||||
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1=resultRegister))
|
||||
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1=resultRegister))
|
||||
// else -> throw AssemblyError("weird arg dt")
|
||||
// }
|
||||
// }
|
||||
// code += VmCodeInstruction(Instruction(Opcode.NOP))
|
||||
}
|
||||
}
|
||||
return code
|
||||
|
||||
@@ -7,7 +7,10 @@ import prog8.code.core.*
|
||||
class VariableAllocator(private val st: SymbolTable, private val program: PtProgram, errors: IErrorReporter) {
|
||||
|
||||
private val allocations = mutableMapOf<List<String>, Int>()
|
||||
val freeStart: Int
|
||||
private var freeMemoryStart: Int
|
||||
|
||||
val freeMem: Int
|
||||
get() = freeMemoryStart
|
||||
|
||||
init {
|
||||
var nextLocation = 0
|
||||
@@ -24,7 +27,7 @@ class VariableAllocator(private val st: SymbolTable, private val program: PtProg
|
||||
nextLocation += memsize
|
||||
}
|
||||
|
||||
freeStart = nextLocation
|
||||
freeMemoryStart = nextLocation
|
||||
}
|
||||
|
||||
fun get(name: List<String>) = allocations.getValue(name)
|
||||
@@ -68,4 +71,21 @@ class VariableAllocator(private val st: SymbolTable, private val program: PtProg
|
||||
}
|
||||
return mm
|
||||
}
|
||||
|
||||
private val memorySlabsInternal = mutableMapOf<String, Triple<UInt, UInt, UInt>>()
|
||||
internal val memorySlabs: Map<String, Triple<UInt, UInt, UInt>> = memorySlabsInternal
|
||||
|
||||
fun allocateMemorySlab(name: String, size: UInt, align: UInt): UInt {
|
||||
val address =
|
||||
if(align==0u || align==1u)
|
||||
freeMemoryStart.toUInt()
|
||||
else
|
||||
(freeMemoryStart.toUInt() + align-1u) and (0xffffffffu xor (align-1u))
|
||||
|
||||
memorySlabsInternal[name] = Triple(address, size, align)
|
||||
freeMemoryStart = (address + size).toInt()
|
||||
return address
|
||||
}
|
||||
|
||||
fun getMemorySlab(name: String): Triple<UInt, UInt, UInt>? = memorySlabsInternal[name]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user