vm: fix comparison operator codegen for floats

This commit is contained in:
Irmen de Jong 2022-05-11 17:07:21 +02:00
parent 677613d30a
commit 74c05d00a9
5 changed files with 110 additions and 58 deletions

View File

@ -316,15 +316,31 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
greaterEquals: Boolean
): VmCodeChunk {
val code = VmCodeChunk()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val ins = if(signed) {
if(greaterEquals) Opcode.SGES else Opcode.SGTS
if(vmDt==VmDataType.FLOAT) {
val leftFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightFpReg = codeGen.vmRegisters.nextFreeFloat()
val zeroRegister = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, -1, leftFpReg)
code += translateExpression(binExpr.right, -1, rightFpReg)
code += VmCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
val ins = if (signed) {
if (greaterEquals) Opcode.SGES else Opcode.SGTS
} else {
if (greaterEquals) Opcode.SGE else Opcode.SGT
}
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = resultRegister, reg3 = zeroRegister)
} else {
if(greaterEquals) Opcode.SGE else Opcode.SGT
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val ins = if (signed) {
if (greaterEquals) Opcode.SGES else Opcode.SGTS
} else {
if (greaterEquals) Opcode.SGE else Opcode.SGT
}
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
}
code += VmCodeInstruction(ins, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
return code
}
@ -336,25 +352,58 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
lessEquals: Boolean
): VmCodeChunk {
val code = VmCodeChunk()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val ins = if(signed) {
if(lessEquals) Opcode.SLES else Opcode.SLTS
if(vmDt==VmDataType.FLOAT) {
val leftFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightFpReg = codeGen.vmRegisters.nextFreeFloat()
val zeroRegister = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, -1, leftFpReg)
code += translateExpression(binExpr.right, -1, rightFpReg)
code += VmCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
val ins = if (signed) {
if (lessEquals) Opcode.SLES else Opcode.SLTS
} else {
if (lessEquals) Opcode.SLE else Opcode.SLT
}
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = resultRegister, reg3 = zeroRegister)
} else {
if(lessEquals) Opcode.SLE else Opcode.SLT
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val ins = if (signed) {
if (lessEquals) Opcode.SLES else Opcode.SLTS
} else {
if (lessEquals) Opcode.SLE else Opcode.SLT
}
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
}
code += VmCodeInstruction(ins, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
return code
}
private fun operatorEquals(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, notEquals: Boolean): VmCodeChunk {
val code = VmCodeChunk()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val opcode = if(notEquals) Opcode.SNE else Opcode.SEQ
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=rightResultReg)
if(vmDt==VmDataType.FLOAT) {
val leftFpReg = codeGen.vmRegisters.nextFreeFloat()
val rightFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, leftFpReg)
code += translateExpression(binExpr.right, -1, rightFpReg)
code += VmCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
if(!notEquals) {
val label = codeGen.createLabelName()
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=resultRegister, symbol = label)
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=1)
code += VmCodeLabel(label)
val regMask = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=regMask, value=1)
code += VmCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=resultRegister, reg2=resultRegister, reg3=regMask)
}
} else {
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, resultRegister, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
code += VmCodeInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = resultRegister, reg3 = rightResultReg)
}
return code
}

View File

@ -3,7 +3,6 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- vm: comparison operator codegen with floating point values are wrong?
- vm: get rid of the 3-register instructions just make them 2 registers? Result register is always same as second?
- vm: use more instructions in codegen: branching
- vm: add more instructions operating directly on memory instead of only registers?

View File

@ -24,44 +24,30 @@ main {
sub start() {
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()
sys.set_carry()
ror(value)
ror(@($5000))
txt.print_ub(value)
txt.nl()
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()
float fl1 = 1.1
float fl2 = 2.2
if fl1==fl2
txt.print("equals!?\n")
if fl1!=fl2
txt.print("not equals.\n")
fl1 = fl2
if fl1==fl2
txt.print("equals.\n")
if fl1!=fl2
txt.print("not equals!?\n")
if fl1 <= fl2
txt.print("yup\n")
if fl1 > fl2
txt.print("nope\n")
fl1 = 3.3
if fl1 <= fl2
txt.print("yup\n")
if fl1 > fl2
txt.print("nope\n")
; txt.print_ub(inline_candidate())
; txt.nl()

View File

@ -140,6 +140,7 @@ ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word
ftosw reg1, fpreg1 - reg1 = fpreg1 as signed word
fpow fpreg1, fpreg2, fpreg3 - fpreg1 = fpreg2 to the power of fpreg3
fabs fpreg1, fpreg2 - fpreg1 = abs(fpreg2)
fcomp reg1, fpreg1, fpreg2 - reg1 = result of comparison of fpreg1 and fpreg2: 0=equal, 1=fpreg1 is greater, -1=fpreg1 is smaller
MISC
@ -255,6 +256,7 @@ enum class Opcode {
FROUND,
FFLOOR,
FCEIL,
FCOMP,
CLC,
SEC,
@ -525,6 +527,7 @@ val instructionFormats = mutableMapOf(
Opcode.FROUND to InstructionFormat.from("F,fr1,fr2"),
Opcode.FFLOOR to InstructionFormat.from("F,fr1,fr2"),
Opcode.FCEIL to InstructionFormat.from("F,fr1,fr2"),
Opcode.FCOMP to InstructionFormat.from("F,r1,fr1,fr2"),
Opcode.MSIG to InstructionFormat.from("BW,r1,r2"),
Opcode.PUSH to InstructionFormat.from("BW,r1"),

View File

@ -188,6 +188,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.FROUND -> InsFROUND(ins)
Opcode.FFLOOR -> InsFFLOOR(ins)
Opcode.FCEIL -> InsFCEIL(ins)
Opcode.FCOMP -> InsFCOMP(ins)
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
}
}
@ -1141,6 +1142,20 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsFCOMP(i: Instruction) {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
val result =
if(left<right)
255u // -1
else if(left>right)
1u
else
0u
registers.setUB(i.reg1!!, result.toUByte())
pc++
}
private fun getBranchOperands(i: Instruction): Pair<Int, Int> {
return when(i.type) {
VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())