mirror of
https://github.com/irmen/prog8.git
synced 2026-03-11 20:41:50 +00:00
vm: added 1-bit variants of lsr/lsl opcodes
This commit is contained in:
@@ -133,7 +133,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
}
|
||||
|
||||
private fun funcPoke(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
// should just be a memory write
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
val valueReg = codeGen.vmRegisters.nextFree()
|
||||
val code = VmCodeChunk()
|
||||
@@ -152,7 +151,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
}
|
||||
|
||||
private fun funcPeek(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
// should just be a memory read
|
||||
val code = VmCodeChunk()
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg)
|
||||
@@ -187,6 +185,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
}
|
||||
|
||||
private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
// TODO optimized code gen
|
||||
val code = VmCodeChunk()
|
||||
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.
|
||||
@@ -194,9 +193,10 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
}
|
||||
|
||||
private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
// TODO optimized code gen
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), resultRegister)
|
||||
code += VmCodeInstruction(Opcode.SWAP, VmDataType.BYTE, reg1 = resultRegister)
|
||||
code += VmCodeInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister)
|
||||
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
|
||||
return code
|
||||
}
|
||||
@@ -248,7 +248,6 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
}
|
||||
|
||||
private fun funcRolRor2(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
// bit rotate left without carry, in-place
|
||||
val vmDt = codeGen.vmType(call.args[0].type)
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister)
|
||||
|
||||
@@ -372,23 +372,29 @@ class CodeGen(internal val program: PtProgram,
|
||||
|
||||
private val powersOfTwo = (0..16).map { 2.0.pow(it.toDouble()).toInt() }
|
||||
|
||||
private fun multiplyByConst(dt: VmDataType, reg: Int, factor: UInt): VmCodeChunk {
|
||||
internal fun multiplyByConst(dt: VmDataType, reg: Int, factor: Int): VmCodeChunk {
|
||||
require(factor>=0)
|
||||
val code = VmCodeChunk()
|
||||
val pow2 = powersOfTwo.indexOf(factor.toInt())
|
||||
if(pow2>=1) {
|
||||
// just shift bits
|
||||
code += VmCodeInstruction(Opcode.LSL, dt, reg1=reg, reg2=reg, reg3=pow2)
|
||||
if(factor==1)
|
||||
return code
|
||||
val pow2 = powersOfTwo.indexOf(factor)
|
||||
if(pow2==1) {
|
||||
// just shift 1 bit
|
||||
code += VmCodeInstruction(Opcode.LSL, dt, reg1=reg)
|
||||
}
|
||||
else if(pow2>=1) {
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += VmCodeInstruction(Opcode.LSLM, dt, reg1=reg, reg2=reg, reg3=pow2reg)
|
||||
} else {
|
||||
when(factor) {
|
||||
0u -> {
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
|
||||
}
|
||||
1u -> { /* do nothing */ }
|
||||
else -> {
|
||||
val factorReg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value=factor.toInt())
|
||||
code += VmCodeInstruction(Opcode.MUL, dt, reg1=reg, reg2=reg, reg3=factorReg)
|
||||
}
|
||||
if (factor == 0) {
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
|
||||
}
|
||||
else {
|
||||
val factorReg = vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||
code += VmCodeInstruction(Opcode.MUL, dt, reg1=reg, reg2=reg, reg3=factorReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
|
||||
@@ -145,11 +145,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset)
|
||||
} else {
|
||||
code += translateExpression(arrayIx.index, idxReg)
|
||||
if(eltSize>1) {
|
||||
val factorReg = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize)
|
||||
code += VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=idxReg, reg3=factorReg)
|
||||
}
|
||||
if(eltSize>1)
|
||||
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize)
|
||||
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
||||
}
|
||||
return code
|
||||
@@ -267,6 +264,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
// TODO: optimized codegen when left or right operand is known 0 or 1 or whatever. But only if this would result in a different opcode such as ADD 1 -> INC, MUL 1 -> NOP
|
||||
// actually optimizing the code should not be done here but in a tailored code optimizer step.
|
||||
// multiplyByConst()
|
||||
val leftCode = translateExpression(binExpr.left, leftResultReg)
|
||||
val rightCode = translateExpression(binExpr.right, rightResultReg)
|
||||
code += leftCode
|
||||
@@ -299,10 +297,10 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
"<<" -> {
|
||||
code += VmCodeInstruction(Opcode.LSL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
code += VmCodeInstruction(Opcode.LSLM, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
">>" -> {
|
||||
val opc = if(signed) Opcode.ASR else Opcode.LSR
|
||||
val opc = if(signed) Opcode.ASRM else Opcode.LSRM
|
||||
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
"==" -> {
|
||||
|
||||
Reference in New Issue
Block a user