vm: use memory load instruction better

This commit is contained in:
Irmen de Jong 2022-04-11 20:55:06 +02:00
parent ec6ac5bf24
commit a2c7273801
5 changed files with 108 additions and 75 deletions

View File

@ -18,11 +18,11 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
"msb" -> funcMsb(call, resultRegister) "msb" -> funcMsb(call, resultRegister)
"lsb" -> funcLsb(call, resultRegister) "lsb" -> funcLsb(call, resultRegister)
"memory" -> funcMemory(call, resultRegister) "memory" -> funcMemory(call, resultRegister)
"rnd" -> funcRnd(call, resultRegister) "rnd" -> funcRnd(resultRegister)
"peek" -> funcPeek(call, resultRegister) "peek" -> funcPeek(call, resultRegister)
"peekw" -> funcPeekW(call, resultRegister) "peekw" -> funcPeekW(call, resultRegister)
"poke" -> funcPoke(call, resultRegister) "poke" -> funcPoke(call)
"pokew" -> funcPokeW(call, resultRegister) "pokew" -> funcPokeW(call)
"pokemon" -> VmCodeChunk() "pokemon" -> VmCodeChunk()
"mkword" -> funcMkword(call, resultRegister) "mkword" -> funcMkword(call, resultRegister)
"sin8u" -> funcSin8u(call, resultRegister) "sin8u" -> funcSin8u(call, resultRegister)
@ -136,47 +136,65 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
return code return code
} }
private fun funcPokeW(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcPokeW(call: PtBuiltinFunctionCall): VmCodeChunk {
val addressReg = codeGen.vmRegisters.nextFree()
val valueReg = codeGen.vmRegisters.nextFree()
val code = VmCodeChunk() val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], addressReg) val valueReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[1], valueReg) if(call.args[0] is PtNumber) {
// TODO use STOREM if constant address val address = (call.args[0] as PtNumber).number.toInt()
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2=addressReg) code += exprGen.translateExpression(call.args[1], valueReg)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg)
code += exprGen.translateExpression(call.args[1], valueReg)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
}
return code return code
} }
private fun funcPoke(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcPoke(call: PtBuiltinFunctionCall): VmCodeChunk {
val addressReg = codeGen.vmRegisters.nextFree()
val valueReg = codeGen.vmRegisters.nextFree()
val code = VmCodeChunk() val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], addressReg) val valueReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[1], valueReg) if(call.args[0] is PtNumber) {
// TODO use STOREM if constant address val address = (call.args[0] as PtNumber).number.toInt()
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2=addressReg) code += exprGen.translateExpression(call.args[1], valueReg)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg)
code += exprGen.translateExpression(call.args[1], valueReg)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
}
return code return code
} }
private fun funcPeekW(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcPeekW(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val addressReg = codeGen.vmRegisters.nextFree()
val code = VmCodeChunk() val code = VmCodeChunk()
code += exprGen.translateExpression(call.args.single(), addressReg) if(call.args[0] is PtNumber) {
// TODO use LOADM if constant address val address = (call.args[0] as PtNumber).number.toInt()
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg) code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg)
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg)
}
return code return code
} }
private fun funcPeek(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcPeek(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk() val code = VmCodeChunk()
val addressReg = codeGen.vmRegisters.nextFree() if(call.args[0] is PtNumber) {
code += exprGen.translateExpression(call.args.single(), addressReg) val address = (call.args[0] as PtNumber).number.toInt()
// TODO use LOADM if constant address code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address)
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg) } else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg)
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg)
}
return code return code
} }
private fun funcRnd(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcRnd(resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk() val code = VmCodeChunk()
code += VmCodeInstruction(Opcode.SYSCALL, value= Syscall.RND.ordinal) code += VmCodeInstruction(Opcode.SYSCALL, value= Syscall.RND.ordinal)
if(resultRegister!=0) if(resultRegister!=0)
@ -203,7 +221,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
} }
private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
// TODO optimized code gen
val code = VmCodeChunk() val code = VmCodeChunk()
code += exprGen.translateExpression(call.args.single(), resultRegister) code += exprGen.translateExpression(call.args.single(), resultRegister)
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here. // note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
@ -211,7 +228,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
} }
private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk { private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
// TODO optimized code gen
val code = VmCodeChunk() val code = VmCodeChunk()
code += exprGen.translateExpression(call.args.single(), resultRegister) code += exprGen.translateExpression(call.args.single(), resultRegister)
code += VmCodeInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister) code += VmCodeInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister)

View File

@ -459,12 +459,18 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeInstruction(operation, vmDt, reg1=resultReg) code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultReg, value = address) code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultReg, value = address)
} else if(memory!=null) { } else if(memory!=null) {
val addressReg = vmRegisters.nextFree() if(memory.address is PtNumber) {
code += expressionEval.translateExpression(memory.address, addressReg) val address = (memory.address as PtNumber).number.toInt()
// TODO use LOADM/STOREM if address is constant code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultReg, value = address)
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultReg, reg2=addressReg) code += VmCodeInstruction(operation, vmDt, reg1 = resultReg)
code += VmCodeInstruction(operation, vmDt, reg1=resultReg) code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value=address)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultReg, reg2=addressReg) } else {
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(memory.address, addressReg)
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = addressReg)
code += VmCodeInstruction(operation, vmDt, reg1 = resultReg)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = resultReg, reg2 = addressReg)
}
} else if (array!=null) { } else if (array!=null) {
val variable = array.variable.targetName val variable = array.variable.targetName
var variableAddr = allocations.get(variable) var variableAddr = allocations.get(variable)

View File

@ -44,10 +44,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem) code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem)
} }
is PtMemoryByte -> { is PtMemoryByte -> {
val addressRegister = codeGen.vmRegisters.nextFree() if(expr.address is PtNumber) {
code += translateExpression(expr.address, addressRegister) val address = (expr.address as PtNumber).number.toInt()
// TODO use LOADM if adress is constant code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address)
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister) } else {
val addressRegister = codeGen.vmRegisters.nextFree()
code += translateExpression(expr.address, addressRegister)
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
}
} }
is PtTypeCast -> code += translate(expr, resultRegister) is PtTypeCast -> code += translate(expr, resultRegister)
is PtPrefix -> code += translate(expr, resultRegister) is PtPrefix -> code += translate(expr, resultRegister)

View File

@ -3,5 +3,5 @@
; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 ; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
math { math {
; TODO ; required by the compiler, but the vm implements all math operations as instructions.
} }

View File

@ -7,45 +7,52 @@
main { main {
sub start() { sub start() {
uword other = $fe4a pokew($1000, $ea31)
uword value = $ea31 poke($1001, $44)
uword[] warray = [$aa44, $bb55, $cc66] txt.print_uwhex(peekw($1000), true)
ubyte upperb = msb(value)
ubyte lowerb = lsb(value)
txt.print_ubhex(upperb, true)
txt.print_ubhex(lowerb, false)
txt.nl()
value = mkword(upperb, lowerb)
txt.print_uwhex(value, true)
txt.nl()
upperb = msb(warray[1])
lowerb = lsb(warray[1])
txt.print_ubhex(upperb, true)
txt.print_ubhex(lowerb, false)
txt.nl()
ubyte index=1
upperb = msb(warray[index])
lowerb = lsb(warray[index])
txt.print_ubhex(upperb, true)
txt.print_ubhex(lowerb, false)
txt.nl()
swap(other, value)
txt.print_uwhex(value,true)
txt.nl() txt.nl()
txt.print_ubhex(peek($1001), true)
txt.nl() txt.nl()
pokew($1000, $ab98) ; uword other = $fe4a
txt.print_ubhex(@($1000),true) ; uword value = $ea31
txt.print_ubhex(@($1001),false) ; uword[] warray = [$aa44, $bb55, $cc66]
txt.nl() ; ubyte upperb = msb(value)
txt.print_uwhex(peekw($1000),true) ; ubyte lowerb = lsb(value)
txt.nl() ; txt.print_ubhex(upperb, true)
swap(@($1000), @($1001)) ; txt.print_ubhex(lowerb, false)
txt.print_uwhex(peekw($1000),true) ; txt.nl()
txt.nl() ; value = mkword(upperb, lowerb)
swap(warray[0], warray[1]) ; txt.print_uwhex(value, true)
txt.print_uwhex(warray[1],true) ; txt.nl()
txt.nl() ; upperb = msb(warray[1])
; lowerb = lsb(warray[1])
; txt.print_ubhex(upperb, true)
; txt.print_ubhex(lowerb, false)
; txt.nl()
; ubyte index=1
; upperb = msb(warray[index])
; lowerb = lsb(warray[index])
; txt.print_ubhex(upperb, true)
; txt.print_ubhex(lowerb, false)
; txt.nl()
; swap(other, value)
; txt.print_uwhex(value,true)
; txt.nl()
; txt.nl()
;
; pokew($1000, $ab98)
; txt.print_ubhex(@($1000),true)
; txt.print_ubhex(@($1001),false)
; txt.nl()
; txt.print_uwhex(peekw($1000),true)
; txt.nl()
; swap(@($1000), @($1001))
; txt.print_uwhex(peekw($1000),true)
; txt.nl()
; swap(warray[0], warray[1])
; txt.print_uwhex(warray[1],true)
; txt.nl()
; ; a "pixelshader": ; ; a "pixelshader":
; void syscall1(8, 0) ; enable lo res creen ; void syscall1(8, 0) ; enable lo res creen