mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
vm: fix comparison operator codegen for floats
This commit is contained in:
parent
677613d30a
commit
74c05d00a9
@ -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
|
||||
}
|
||||
|
||||
|
@ -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?
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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"),
|
||||
|
@ -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())
|
||||
|
Loading…
Reference in New Issue
Block a user