vm: added swap()

This commit is contained in:
Irmen de Jong 2022-04-11 01:31:34 +02:00
parent ec7501782d
commit ec6ac5bf24
7 changed files with 90 additions and 31 deletions

View File

@ -188,5 +188,13 @@ class PtTypeCast(type: DataType, position: Position) : PtExpression(type, positi
}
// special node that isn't created from compiling user code, but used internally
class PtMachineRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position) {
override fun printProperties() {
print("reg=$register $type")
}
}
fun constValue(expr: PtExpression): Double? = if(expr is PtNumber) expr.number else null
fun constIntValue(expr: PtExpression): Int? = if(expr is PtNumber) expr.number.toInt() else null

View File

@ -62,7 +62,7 @@ class PtAssignTarget(position: Position) : PtNode(position) {
is PtIdentifier -> tgt.type
is PtArrayIndexer -> tgt.type // TODO array to elt type?
is PtMemoryByte -> tgt.type
else -> throw AssemblyError("weird dt")
else -> throw AssemblyError("weird target $tgt")
}
}

View File

@ -29,6 +29,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
"cos8u" -> funcCos8u(call, resultRegister)
"sort" -> funcSort(call)
"reverse" -> funcReverse(call)
"swap" -> funcSwap(call)
"rol" -> funcRolRor2(Opcode.ROXL, call, resultRegister)
"ror" -> funcRolRor2(Opcode.ROXR, call, resultRegister)
"rol2" -> funcRolRor2(Opcode.ROL, call, resultRegister)
@ -57,6 +58,19 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
}
}
private fun funcSwap(call: PtBuiltinFunctionCall): VmCodeChunk {
val left = call.args[0]
val right = call.args[1]
val leftReg = codeGen.vmRegisters.nextFree()
val rightReg = codeGen.vmRegisters.nextFree()
val code = VmCodeChunk()
code += exprGen.translateExpression(left, leftReg)
code += exprGen.translateExpression(right, rightReg)
code += assignRegisterTo(left, rightReg)
code += assignRegisterTo(right, leftReg)
return code
}
private fun funcReverse(call: PtBuiltinFunctionCall): VmCodeChunk {
val arrayName = call.args[0] as PtIdentifier
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
@ -128,7 +142,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], addressReg)
code += exprGen.translateExpression(call.args[1], valueReg)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = addressReg, reg2=valueReg)
// TODO use STOREM if constant address
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2=addressReg)
return code
}
@ -138,7 +153,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], addressReg)
code += exprGen.translateExpression(call.args[1], valueReg)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = addressReg, reg2=valueReg)
// TODO use STOREM if constant address
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2=addressReg)
return code
}
@ -146,6 +162,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val addressReg = codeGen.vmRegisters.nextFree()
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args.single(), addressReg)
// TODO use LOADM if constant address
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg)
return code
}
@ -154,6 +171,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val code = VmCodeChunk()
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg)
// TODO use LOADM if constant address
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg)
return code
}
@ -252,11 +270,17 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
val code = VmCodeChunk()
code += exprGen.translateExpression(call.args[0], resultRegister)
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister)
val assignment = PtAssignment(call.position)
val target = PtAssignTarget(call.position)
target.children.add(call.args[0])
assignment.children.add(target)
assignment.children.add(PtIdentifier(listOf(":vmreg-$resultRegister"), listOf(":vmreg-$resultRegister"), call.args[0].type, call.position))
code += assignRegisterTo(call.args[0], resultRegister)
return code
}
private fun assignRegisterTo(target: PtExpression, register: Int): VmCodeChunk {
val code = VmCodeChunk()
val assignment = PtAssignment(target.position)
val assignTarget = PtAssignTarget(target.position)
assignTarget.children.add(target)
assignment.children.add(assignTarget)
assignment.children.add(PtMachineRegister(register, target.type, target.position))
code += codeGen.translateNode(assignment)
return code
}

View File

@ -96,7 +96,7 @@ class CodeGen(internal val program: PtProgram,
is PtSubroutineParameter,
is PtNumber,
is PtArray,
is PtString -> throw AssemblyError("strings should not occur as separate statement node ${node.position}")
is PtString -> throw AssemblyError("should not occur as separate statement node ${node.position}")
is PtAsmSub -> throw AssemblyError("asmsub not supported on virtual machine target ${node.position}")
is PtInlineAssembly -> throw AssemblyError("inline assembly not supported on virtual machine target ${node.position}")
is PtIncludeBinary -> throw AssemblyError("inline binary data not supported on virtual machine target ${node.position}")
@ -461,6 +461,7 @@ class CodeGen(internal val program: PtProgram,
} else if(memory!=null) {
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(memory.address, addressReg)
// TODO use LOADM/STOREM if address is constant
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultReg, reg2=addressReg)
code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultReg, reg2=addressReg)
@ -533,10 +534,16 @@ class CodeGen(internal val program: PtProgram,
private fun translate(assignment: PtAssignment): VmCodeChunk {
// TODO can in-place assignments be optimized more?
if(assignment.target.children.single() is PtMachineRegister)
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
val code = VmCodeChunk()
val resultRegister = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, resultRegister)
val resultRegister = if(assignment.value is PtMachineRegister) {
(assignment.value as PtMachineRegister).register
} else {
val reg = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, reg)
reg
}
val ident = assignment.target.identifier
val memory = assignment.target.memory
val array = assignment.target.array
@ -561,12 +568,13 @@ class CodeGen(internal val program: PtProgram,
}
}
else if(memory!=null) {
require(vmDt==VmDataType.BYTE)
if(memory.address is PtNumber) {
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
} else {
val addressRegister = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, addressRegister)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressRegister)
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, addressReg)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
}
}
else

View File

@ -18,17 +18,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val code = VmCodeChunk()
when (expr) {
is PtMachineRegister -> {
if(resultRegister!=expr.register) {
val vmDt = codeGen.vmType(expr.type)
code += VmCodeInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=expr.register)
}
}
is PtNumber -> {
val vmDt = codeGen.vmType(expr.type)
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt())
}
is PtIdentifier -> {
val vmDt = codeGen.vmType(expr.type)
if(expr.targetName[0].startsWith(":vmreg-")) {
// special direct reference to a register in the VM
val reg = expr.targetName[0].substring(7).toInt()
code += VmCodeInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=reg)
} else {
val mem = codeGen.allocations.get(expr.targetName)
code += if (expr.type in PassByValueDatatypes) {
VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, value = mem)
@ -37,7 +38,6 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
VmCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, value = mem)
}
}
}
is PtAddressOf -> {
val vmDt = codeGen.vmType(expr.type)
val mem = codeGen.allocations.get(expr.identifier.targetName)
@ -45,8 +45,9 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
}
is PtMemoryByte -> {
val addressRegister = codeGen.vmRegisters.nextFree()
val addressExprCode = translateExpression(expr.address, addressRegister)
code += addressExprCode
code += translateExpression(expr.address, addressRegister)
// TODO use LOADM if adress is constant
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
}
is PtTypeCast -> code += translate(expr, resultRegister)
is PtPrefix -> code += translate(expr, resultRegister)
@ -73,12 +74,12 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return when (segment) {
is PtFunctionCall -> {
val segWithArg = PtFunctionCall(segment.functionName, segment.void, segment.type, segment.position)
segWithArg.children.add(0, PtIdentifier(listOf(":vmreg-$sourceReg"), listOf(":vmreg-$sourceReg"), sourceDt, segment.position))
segWithArg.children.add(0, PtMachineRegister(sourceReg, sourceDt, segment.position))
segWithArg
}
is PtBuiltinFunctionCall -> {
val segWithArg = PtBuiltinFunctionCall(segment.name, segment.void, segment.hasNoSideEffects, segment.type, segment.position)
segWithArg.children.add(0, PtIdentifier(listOf(":vmreg-$sourceReg"), listOf(":vmreg-$sourceReg"), sourceDt, segment.position))
segWithArg.children.add(0, PtMachineRegister(sourceReg, sourceDt, segment.position))
segWithArg
}
else -> throw AssemblyError("weird segment type")

View File

@ -7,6 +7,7 @@
main {
sub start() {
uword other = $fe4a
uword value = $ea31
uword[] warray = [$aa44, $bb55, $cc66]
ubyte upperb = msb(value)
@ -28,6 +29,23 @@ main {
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":
; void syscall1(8, 0) ; enable lo res creen

View File

@ -39,7 +39,7 @@ storem reg1, address - store reg1 in memory address
storei reg1, reg2 - store reg1 in memory indirect, memory pointed to by reg2
storex reg1, reg2, address - store reg1 in memory address, indexed by value in reg2
storez address - store zero in memory address
storezi reg1 - store zero in memory pointed to by reg
storezi reg1 - store zero in memory pointed to by reg1
storezx reg1, address - store zero in memory address, indexed by value in reg