vm: use shift-one instructions in codegen

This commit is contained in:
Irmen de Jong 2022-05-11 15:50:51 +02:00
parent 14e36f1362
commit bacba629a5
5 changed files with 79 additions and 70 deletions

View File

@ -762,4 +762,6 @@ class CodeGen(internal val program: PtProgram,
builtinFuncGen.translate(call, resultRegister)
internal fun isZero(expression: PtExpression): Boolean = expression is PtNumber && expression.number==0.0
internal fun isOne(expression: PtExpression): Boolean = expression is PtNumber && expression.number==1.0
}

View File

@ -363,24 +363,33 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, signed: Boolean): VmCodeChunk {
val code = VmCodeChunk()
// TODO if shift is 1, use ASR/LSR instruction instead of multishift
if(codeGen.isOne(binExpr.right)) {
code += translateExpression(binExpr.left, resultRegister, -1)
val opc = if (signed) Opcode.ASR else Opcode.LSR
code += VmCodeInstruction(opc, vmDt, reg1 = resultRegister)
} else {
val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val opc = if(signed) Opcode.ASRN else Opcode.LSRN
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
val opc = if (signed) Opcode.ASRN else Opcode.LSRN
code += VmCodeInstruction(opc, vmDt, reg1 = resultRegister, reg2 = leftResultReg, reg3 = rightResultReg)
}
return code
}
private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
// TODO if shift is 1, use LSL instruction instead of multishift
if(codeGen.isOne(binExpr.right)){
code += translateExpression(binExpr.left, resultRegister, -1)
code += VmCodeInstruction(Opcode.LSL, vmDt, reg1=resultRegister)
} else {
val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
return code
}

View File

@ -3,7 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- vm: use more instructions in codegen: shift one
- vm: expressiongen: use resultRegister arg instead of allocating new leftResultReg
- vm: use more instructions in codegen: branching
- vm: add more instructions operating directly on memory instead of only registers?
- in-place modifiying functions (rol, ror, ..) don't accept a memory address but require a memory-read expression. that is weird.

View File

@ -7,63 +7,61 @@
; NOTE: meant to test to virtual machine output target (use -target vitual)
main {
; ubyte value = 42
;
; sub inline_candidate() -> ubyte {
; return math.sin8u(value)
; }
;
; sub add(ubyte first, ubyte second) -> ubyte {
; return first + second
; }
;
; sub mul(ubyte first, ubyte second) -> ubyte {
; return first * second
; }
ubyte value = 42
sub inline_candidate() -> ubyte {
return math.sin8u(value)
}
sub add(ubyte first, ubyte second) -> ubyte {
return first + second
}
sub mul(ubyte first, ubyte second) -> ubyte {
return first * second
}
sub start() {
uword[] arrayuw = [1111,2222,3333,4444]
txt.print_uw(arrayuw[1])
txt.nl()
arrayuw[1] = 9999
txt.print_uw(arrayuw[1])
txt.nl()
arrayuw[1] = 0
txt.print_uw(arrayuw[1])
txt.nl()
float[] array = [1.1, 2.2, 3.3, 4.4]
floats.print_f(array[1])
ubyte @shared value = inline_candidate()
value = %01011100
byte @shared svalue = 99
svalue = -svalue
@($5000) = not @($5000)
sys.set_carry()
rol(value)
rol(@($5000))
txt.print_ub(value)
txt.nl()
array[1] = 99.99
floats.print_f(array[1])
sys.set_carry()
ror(value)
ror(@($5000))
txt.print_ub(value)
txt.nl()
array[1] = 0
floats.print_f(array[1])
txt.nl()
; ubyte value = inline_candidate()
; byte svalue = 99
; svalue = -svalue
; @($5000) = not @($5000)
; rol(value)
; rol(@($5000))
; ror(value)
; ror(@($5000))
; rol2(value)
; rol2(@($5000))
; ror2(value)
; ror2(@($5000))
; @($5000) <<= 1
; @($5000) >>= 1
; value <<= 1
; value >>= 1
; @($5000) <<= 3
; @($5000) >>= 3
; value <<= 3
; value >>= 3
; txt.print_ub(value)
; txt.nl()
value = %01011100
sys.set_carry()
rol2(value)
rol2(@($5000))
txt.print_ub(value)
txt.nl()
sys.clear_carry()
ror2(value)
ror2(@($5000))
txt.print_ub(value)
txt.nl()
@($5000) <<= 1
@($5000) >>= 1
value <<= 1
value >>= 1
txt.print_ub(value)
txt.nl()
@($5000) <<= 3
@($5000) >>= 3
value <<= 3
value >>= 3
txt.print_ub(value)
txt.nl()
; txt.print_ub(inline_candidate())
; txt.nl()

View File

@ -124,8 +124,8 @@ asr reg1 - shift reg1 right by 1 bits (signe
lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit
ror reg1 - rotate reg1 right by 1 bits, not using carry + set Carry to shifted bit
roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit
rol reg1 - rotate reg1 left by 1bits, not using carry + set Carry to shifted bit
roxl reg1 - rotate reg1 left by 1bits, using carry, + set Carry to shifted bit
rol reg1 - rotate reg1 left by 1 bits, not using carry + set Carry to shifted bit
roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit
FLOATING POINT CONVERSIONS AND FUNCTIONS
@ -227,9 +227,9 @@ enum class Opcode {
ASRN,
LSRN,
LSLN,
ASR, // TODO not used in codegen of shift 1
LSR, // TODO not used in codegen of shift 1
LSL, // TODO not used in codegen of shift 1
ASR,
LSR,
LSL,
ROR,
ROXR,
ROL,