mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
implementing more of the vm
This commit is contained in:
parent
4e33ab1e89
commit
30cbb6c9a8
@ -56,9 +56,9 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
is PtNop -> VmCodeChunk()
|
is PtNop -> VmCodeChunk()
|
||||||
is PtReturn -> translate(node)
|
is PtReturn -> translate(node)
|
||||||
is PtJump -> translate(node)
|
is PtJump -> translate(node)
|
||||||
is PtWhen -> TODO()
|
is PtWhen -> TODO("when")
|
||||||
is PtPipe -> expressionEval.translate(node, regUsage.nextFree(), regUsage)
|
is PtPipe -> expressionEval.translate(node, regUsage.nextFree(), regUsage)
|
||||||
is PtForLoop -> TODO()
|
is PtForLoop -> TODO("for-loop")
|
||||||
is PtIfElse -> translate(node, regUsage)
|
is PtIfElse -> translate(node, regUsage)
|
||||||
is PtPostIncrDecr -> translate(node, regUsage)
|
is PtPostIncrDecr -> translate(node, regUsage)
|
||||||
is PtRepeatLoop -> translate(node, regUsage)
|
is PtRepeatLoop -> translate(node, regUsage)
|
||||||
@ -219,7 +219,19 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
code += VmCodeInstruction(ins)
|
code += VmCodeInstruction(ins)
|
||||||
}
|
}
|
||||||
else if(array!=null) {
|
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) {
|
else if(memory!=null) {
|
||||||
val ins =
|
val ins =
|
||||||
|
@ -365,16 +365,58 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
|||||||
val name = (call.args[0] as PtString).value
|
val name = (call.args[0] as PtString).value
|
||||||
val size = (call.args[1] as PtNumber).number.toUInt()
|
val size = (call.args[1] as PtNumber).number.toUInt()
|
||||||
val align = (call.args[2] 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" -> {
|
"rnd" -> {
|
||||||
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=Syscall.RND.ordinal))
|
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=Syscall.RND.ordinal))
|
||||||
if(resultRegister!=0)
|
if(resultRegister!=0)
|
||||||
code += VmCodeInstruction(Instruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=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 -> {
|
else -> {
|
||||||
// TODO builtin functions...
|
|
||||||
TODO("builtinfunc ${call.name}")
|
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
|
return code
|
||||||
|
@ -7,7 +7,10 @@ import prog8.code.core.*
|
|||||||
class VariableAllocator(private val st: SymbolTable, private val program: PtProgram, errors: IErrorReporter) {
|
class VariableAllocator(private val st: SymbolTable, private val program: PtProgram, errors: IErrorReporter) {
|
||||||
|
|
||||||
private val allocations = mutableMapOf<List<String>, Int>()
|
private val allocations = mutableMapOf<List<String>, Int>()
|
||||||
val freeStart: Int
|
private var freeMemoryStart: Int
|
||||||
|
|
||||||
|
val freeMem: Int
|
||||||
|
get() = freeMemoryStart
|
||||||
|
|
||||||
init {
|
init {
|
||||||
var nextLocation = 0
|
var nextLocation = 0
|
||||||
@ -24,7 +27,7 @@ class VariableAllocator(private val st: SymbolTable, private val program: PtProg
|
|||||||
nextLocation += memsize
|
nextLocation += memsize
|
||||||
}
|
}
|
||||||
|
|
||||||
freeStart = nextLocation
|
freeMemoryStart = nextLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(name: List<String>) = allocations.getValue(name)
|
fun get(name: List<String>) = allocations.getValue(name)
|
||||||
@ -68,4 +71,21 @@ class VariableAllocator(private val st: SymbolTable, private val program: PtProg
|
|||||||
}
|
}
|
||||||
return mm
|
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]
|
||||||
}
|
}
|
||||||
|
@ -399,7 +399,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if (rightCv == 0.0) {
|
if (rightCv == 0.0) {
|
||||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
||||||
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..4.0) {
|
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..4.0 && compTarget.name!=VMTarget.NAME) {
|
||||||
// replace by several INCs if it's not a memory address (inc on a memory mapped register doesn't work very well)
|
// replace by several INCs if it's not a memory address (inc on a memory mapped register doesn't work very well)
|
||||||
val incs = AnonymousScope(mutableListOf(), assignment.position)
|
val incs = AnonymousScope(mutableListOf(), assignment.position)
|
||||||
repeat(rightCv.toInt()) {
|
repeat(rightCv.toInt()) {
|
||||||
@ -413,7 +413,7 @@ class StatementOptimizer(private val program: Program,
|
|||||||
if (rightCv == 0.0) {
|
if (rightCv == 0.0) {
|
||||||
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
return listOf(IAstModification.Remove(assignment, parent as IStatementContainer))
|
||||||
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
} else if (targetDt in IntegerDatatypes && floor(rightCv) == rightCv) {
|
||||||
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..4.0) {
|
if (vardeclDt != VarDeclType.MEMORY && rightCv in 1.0..4.0 && compTarget.name!=VMTarget.NAME) {
|
||||||
// replace by several DECs if it's not a memory address (dec on a memory mapped register doesn't work very well)
|
// replace by several DECs if it's not a memory address (dec on a memory mapped register doesn't work very well)
|
||||||
val decs = AnonymousScope(mutableListOf(), assignment.position)
|
val decs = AnonymousScope(mutableListOf(), assignment.position)
|
||||||
repeat(rightCv.toInt()) {
|
repeat(rightCv.toInt()) {
|
||||||
|
@ -8,33 +8,33 @@ prog8_lib {
|
|||||||
%option force_output
|
%option force_output
|
||||||
|
|
||||||
sub string_contains(ubyte needle, str haystack) -> ubyte {
|
sub string_contains(ubyte needle, str haystack) -> ubyte {
|
||||||
txt.print(">>>string elt check: ")
|
repeat {
|
||||||
txt.print_ub(needle)
|
if @(haystack)==0
|
||||||
txt.spc()
|
return false
|
||||||
txt.print_uwhex(haystack, true)
|
if @(haystack)==needle
|
||||||
txt.nl()
|
return true
|
||||||
return 0
|
haystack++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub bytearray_contains(ubyte needle, uword haystack_ptr, ubyte num_elements) -> ubyte {
|
sub bytearray_contains(ubyte needle, uword haystack_ptr, ubyte num_elements) -> ubyte {
|
||||||
txt.print(">>>bytearray elt check: ")
|
haystack_ptr--
|
||||||
txt.print_ub(needle)
|
while num_elements {
|
||||||
txt.spc()
|
if haystack_ptr[num_elements]==needle
|
||||||
txt.print_uwhex(haystack_ptr, true)
|
return true
|
||||||
txt.spc()
|
num_elements--
|
||||||
txt.print_ub(num_elements)
|
}
|
||||||
txt.nl()
|
return false
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub wordarray_contains(ubyte needle, uword haystack_ptr, ubyte num_elements) -> ubyte {
|
sub wordarray_contains(ubyte needle, uword haystack_ptr, ubyte num_elements) -> ubyte {
|
||||||
txt.print(">>>wordarray elt check: ")
|
haystack_ptr += (num_elements-1) * 2
|
||||||
txt.print_ub(needle)
|
while num_elements {
|
||||||
txt.spc()
|
if peekw(haystack_ptr)==needle
|
||||||
txt.print_uwhex(haystack_ptr, true)
|
return true
|
||||||
txt.spc()
|
haystack_ptr -= 2
|
||||||
txt.print_ub(num_elements)
|
num_elements--
|
||||||
txt.nl()
|
}
|
||||||
return 0
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import test_stack
|
; %import test_stack
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
; Note: this program is compatible with C64 and CX16.
|
; Note: this program is compatible with C64 and CX16.
|
||||||
|
103
examples/test.p8
103
examples/test.p8
@ -1,4 +1,3 @@
|
|||||||
%import floats
|
|
||||||
%import textio
|
%import textio
|
||||||
|
|
||||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||||
@ -8,67 +7,55 @@ main {
|
|||||||
txt.clear_screen()
|
txt.clear_screen()
|
||||||
txt.print("Welcome to a prog8 pixel shader :-)\n")
|
txt.print("Welcome to a prog8 pixel shader :-)\n")
|
||||||
|
|
||||||
float fl = 9.9
|
uword @shared chunk = memory("irmen", 4000, 256)
|
||||||
fl = floats.pow(fl, 3.3)
|
txt.print_uwhex(chunk,true)
|
||||||
floats.print_f(fl)
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
ubyte ww = 65
|
|
||||||
fl = ww
|
ubyte bb = 4
|
||||||
fl += 0.1
|
ubyte[] array = [1,2,3,4,5,6]
|
||||||
floats.print_f(fl)
|
uword[] warray = [1111,2222,3333]
|
||||||
|
str tekst = "test"
|
||||||
|
uword ww = 19
|
||||||
|
bb = bb in "teststring"
|
||||||
|
bb++
|
||||||
|
bb = bb in [1,2,3,4,5,6]
|
||||||
|
bb++
|
||||||
|
bb = bb in array
|
||||||
|
bb++
|
||||||
|
bb = bb in tekst
|
||||||
|
bb++
|
||||||
|
bb = ww in warray
|
||||||
|
bb++
|
||||||
|
bb = 666 in warray
|
||||||
|
bb ++
|
||||||
|
bb = '?' in tekst
|
||||||
|
bb++
|
||||||
|
txt.print("bb=")
|
||||||
|
txt.print_ub(bb)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
uword ww2 = 65432
|
sys.exit(99)
|
||||||
fl = ww2
|
|
||||||
fl += 0.1
|
|
||||||
floats.print_f(fl)
|
|
||||||
|
|
||||||
|
|
||||||
|
syscall1(8, 0) ; enable lo res creen
|
||||||
|
ubyte shifter
|
||||||
|
|
||||||
; ubyte bb = 4
|
shifter >>= 1
|
||||||
; ubyte[] array = [1,2,3,4,5,6]
|
|
||||||
; uword[] warray = [1111,2222,3333]
|
repeat {
|
||||||
; str tekst = "test"
|
uword xx
|
||||||
; uword ww = 19
|
uword yy = 0
|
||||||
; bb = bb in "teststring"
|
repeat 240 {
|
||||||
; bb++
|
xx = 0
|
||||||
; bb = bb in [1,2,3,4,5,6]
|
repeat 320 {
|
||||||
; bb++
|
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
||||||
; bb = bb in array
|
xx++
|
||||||
; bb++
|
}
|
||||||
; bb = bb in tekst
|
yy++
|
||||||
; bb++
|
}
|
||||||
; bb = ww in warray
|
shifter+=4
|
||||||
; bb++
|
|
||||||
; bb = 666 in warray
|
txt.print_ub(shifter)
|
||||||
; bb ++
|
txt.nl()
|
||||||
; bb = '?' in tekst
|
}
|
||||||
; bb++
|
|
||||||
; txt.print("bb=")
|
|
||||||
; txt.print_ub(bb)
|
|
||||||
; txt.nl()
|
|
||||||
; sys.exit(99)
|
|
||||||
;
|
|
||||||
;
|
|
||||||
; syscall1(8, 0) ; enable lo res creen
|
|
||||||
; ubyte shifter
|
|
||||||
;
|
|
||||||
; shifter >>= 1
|
|
||||||
;
|
|
||||||
; repeat {
|
|
||||||
; uword xx
|
|
||||||
; uword yy = 0
|
|
||||||
; repeat 240 {
|
|
||||||
; xx = 0
|
|
||||||
; repeat 320 {
|
|
||||||
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
|
||||||
; xx++
|
|
||||||
; }
|
|
||||||
; yy++
|
|
||||||
; }
|
|
||||||
; shifter+=4
|
|
||||||
;
|
|
||||||
; txt.print_ub(shifter)
|
|
||||||
; txt.nl()
|
|
||||||
; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ enum class Syscall {
|
|||||||
GFX_ENABLE,
|
GFX_ENABLE,
|
||||||
GFX_CLEAR,
|
GFX_CLEAR,
|
||||||
GFX_PLOT,
|
GFX_PLOT,
|
||||||
RND
|
RND,
|
||||||
}
|
}
|
||||||
|
|
||||||
object SysCalls {
|
object SysCalls {
|
||||||
@ -82,6 +82,7 @@ object SysCalls {
|
|||||||
Syscall.RND -> {
|
Syscall.RND -> {
|
||||||
vm.registers.setB(0, (Random.nextInt() ushr 3).toUByte())
|
vm.registers.setB(0, (Random.nextInt() ushr 3).toUByte())
|
||||||
}
|
}
|
||||||
|
else -> TODO("syscall ${call.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user