vm: implemented in-memory bit shift instructions

This commit is contained in:
Irmen de Jong
2022-05-23 20:10:37 +02:00
parent 0a48ef3030
commit b646f50265
11 changed files with 226 additions and 101 deletions
@@ -90,6 +90,8 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
"|" -> return expressionEval.operatorOrInplace(address, vmDt, operand)
"&" -> return expressionEval.operatorAndInplace(address, vmDt, operand)
"^" -> return expressionEval.operatorXorInplace(address, vmDt, operand)
"<<" -> return expressionEval.operatorShiftLeftInplace(address, vmDt, operand)
">>" -> return expressionEval.operatorShiftRightInplace(address, vmDt, signed, operand)
else -> {}
}
return fallbackAssign(origAssign)
@@ -446,21 +446,13 @@ class CodeGen(internal val program: PtProgram,
val pow2 = powersOfTwo.indexOf(factor)
if(pow2==1) {
// just shift 1 bit
// TODO use a memory shift instruction?
val reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address)
code += VmCodeInstruction(Opcode.LSL, dt, reg1=reg)
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address)
code += VmCodeInstruction(Opcode.LSLM, dt, value = address)
}
else if(pow2>=1) {
// just shift multiple bits
// TODO use a memory shift instruction?
val reg = vmRegisters.nextFree()
val pow2reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address)
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address)
code += VmCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=address)
} else {
if (factor == 0) {
code += VmCodeInstruction(Opcode.STOREZM, dt, value=address)
@@ -547,27 +539,19 @@ class CodeGen(internal val program: PtProgram,
val pow2 = powersOfTwo.indexOf(factor)
if(pow2==1) {
// just shift 1 bit
// TODO use memory-shift instruction?
val reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address)
code += if(signed)
VmCodeInstruction(Opcode.ASR, dt, reg1=reg)
VmCodeInstruction(Opcode.ASRM, dt, value=address)
else
VmCodeInstruction(Opcode.LSR, dt, reg1=reg)
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address)
VmCodeInstruction(Opcode.LSRM, dt, value=address)
}
else if(pow2>=1) {
// just shift multiple bits
// TODO use memory-shift instruction?
val reg = vmRegisters.nextFree()
val pow2reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOADM, dt, reg1=reg, value=address)
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
code += if(signed)
VmCodeInstruction(Opcode.ASRN, dt, reg1=reg, reg2=pow2reg)
VmCodeInstruction(Opcode.ASRNM, dt, reg1=pow2reg, value=address)
else
VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
code += VmCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=address)
VmCodeInstruction(Opcode.LSRNM, dt, reg1=pow2reg, value=address)
} else {
if (factor == 0) {
val reg = vmRegisters.nextFree()
@@ -454,6 +454,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
internal fun operatorShiftRightInplace(address: Int, vmDt: VmDataType, signed: Boolean, operand: PtExpression): VmCodeChunk {
val code = VmCodeChunk()
if(codeGen.isOne(operand)) {
val opc = if (signed) Opcode.ASRM else Opcode.LSRM
code += VmCodeInstruction(opc, vmDt, value=address)
} else {
val operandReg = codeGen.vmRegisters.nextFree()
code += translateExpression(operand, operandReg, -1)
val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM
code += VmCodeInstruction(opc, vmDt, reg1 = operandReg, value=address)
}
return code
}
private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
if(codeGen.isOne(binExpr.right)){
@@ -468,6 +482,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
internal fun operatorShiftLeftInplace(address: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk {
val code = VmCodeChunk()
if(codeGen.isOne(operand)){
code += VmCodeInstruction(Opcode.LSLM, vmDt, value=address)
} else {
val operandReg = codeGen.vmRegisters.nextFree()
code += translateExpression(operand, operandReg, -1)
code += VmCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=address)
}
return code
}
private fun operatorXor(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
val rightResultReg = codeGen.vmRegisters.nextFree()