mirror of
https://github.com/irmen/prog8.git
synced 2026-04-19 20:16:51 +00:00
vm: implementing rol/ror
This commit is contained in:
@@ -1,10 +1,7 @@
|
||||
package prog8.codegen.virtual
|
||||
|
||||
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.ast.*
|
||||
import prog8.code.core.DataType
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.Syscall
|
||||
@@ -154,6 +151,10 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||
}
|
||||
"rol" -> RolRor2(Opcode.ROXL, call, resultRegister, code)
|
||||
"ror" -> RolRor2(Opcode.ROXR, call, resultRegister, code)
|
||||
"rol2" -> RolRor2(Opcode.ROL, call, resultRegister, code)
|
||||
"ror2" -> RolRor2(Opcode.ROR, call, resultRegister, code)
|
||||
else -> {
|
||||
TODO("builtinfunc ${call.name}")
|
||||
// code += VmCodeInstruction(Opcode.NOP))
|
||||
@@ -179,4 +180,17 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
return code
|
||||
}
|
||||
|
||||
private fun RolRor2(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int, code: VmCodeChunk) {
|
||||
// bit rotate left without carry, in-place
|
||||
val vmDt = codeGen.vmType(call.args[0].type)
|
||||
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 += codeGen.translateNode(assignment)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
}
|
||||
|
||||
|
||||
private fun translateNode(node: PtNode): VmCodeChunk {
|
||||
internal fun translateNode(node: PtNode): VmCodeChunk {
|
||||
val code = when(node) {
|
||||
is PtBlock -> translate(node)
|
||||
is PtSub -> translate(node)
|
||||
@@ -80,6 +80,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtRepeatLoop -> translate(node)
|
||||
is PtLabel -> VmCodeChunk(VmCodeLabel(node.scopedName))
|
||||
is PtBreakpoint -> VmCodeChunk(VmCodeInstruction(Opcode.BREAKPOINT))
|
||||
is PtConditionalBranch -> translate(node)
|
||||
is PtAddressOf,
|
||||
is PtContainmentCheck,
|
||||
is PtMemoryByte,
|
||||
@@ -99,7 +100,6 @@ class CodeGen(internal val program: PtProgram,
|
||||
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}")
|
||||
is PtConditionalBranch -> throw AssemblyError("conditional branches not supported in vm target due to lack of cpu flags ${node.position}")
|
||||
else -> TODO("missing codegen for $node")
|
||||
}
|
||||
if(code.lines.isNotEmpty() && node.position.line!=0)
|
||||
@@ -107,6 +107,33 @@ class CodeGen(internal val program: PtProgram,
|
||||
return code
|
||||
}
|
||||
|
||||
private fun translate(branch: PtConditionalBranch): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
val elseLabel = createLabelName()
|
||||
when(branch.condition) {
|
||||
BranchCondition.CS -> {
|
||||
code += VmCodeInstruction(Opcode.BSTCC, symbol = elseLabel)
|
||||
}
|
||||
BranchCondition.CC -> {
|
||||
code += VmCodeInstruction(Opcode.BSTCS, symbol = elseLabel)
|
||||
}
|
||||
else -> {
|
||||
throw AssemblyError("conditional branch ${branch.condition} not supported in vm target due to lack of cpu flags ${branch.position}")
|
||||
}
|
||||
}
|
||||
code += translateNode(branch.trueScope)
|
||||
if(branch.falseScope.children.isNotEmpty()) {
|
||||
val endLabel = createLabelName()
|
||||
code += VmCodeInstruction(Opcode.JUMP, symbol = endLabel)
|
||||
code += VmCodeLabel(elseLabel)
|
||||
code += translateNode(branch.falseScope)
|
||||
code += VmCodeLabel(endLabel)
|
||||
} else {
|
||||
code += VmCodeLabel(elseLabel)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
private fun translate(whenStmt: PtWhen): VmCodeChunk {
|
||||
if(whenStmt.choices.children.isEmpty())
|
||||
return VmCodeChunk()
|
||||
|
||||
Reference in New Issue
Block a user