From 4be7bc832330b399c6feb2764dd56da0e7d6e2d3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Wed, 11 May 2022 22:09:46 +0200 Subject: [PATCH] vm: limit float instructions to just 2 register args --- .../prog8/codegen/virtual/AssemblyProgram.kt | 7 +--- .../src/prog8/codegen/virtual/CodeGen.kt | 4 +- .../prog8/codegen/virtual/ExpressionGen.kt | 8 ++-- compiler/res/prog8lib/virtual/floats.p8 | 2 +- examples/test.p8 | 1 + virtualmachine/src/prog8/vm/Assembler.kt | 6 ++- virtualmachine/src/prog8/vm/Instructions.kt | 39 +++++++------------ virtualmachine/src/prog8/vm/VirtualMachine.kt | 20 +++++----- 8 files changed, 39 insertions(+), 48 deletions(-) diff --git a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt index 166608239..774d5fd0b 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt @@ -80,12 +80,11 @@ internal class VmCodeInstruction( reg3: Int?=null, // 0-$ffff fpReg1: Int?=null, // 0-$ffff fpReg2: Int?=null, // 0-$ffff - fpReg3: Int?=null, // 0-$ffff value: Int?=null, // 0-$ffff fpValue: Float?=null, symbol: List?=null // alternative to value ): VmCodeLine() { - val ins = Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, fpReg3, value, fpValue, symbol) + val ins = Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, value, fpValue, symbol) init { if(reg1!=null && (reg1<0 || reg1>65536)) @@ -98,9 +97,7 @@ internal class VmCodeInstruction( throw IllegalArgumentException("fpReg1 out of bounds") if(fpReg2!=null && (fpReg2<0 || fpReg2>65536)) throw IllegalArgumentException("fpReg2 out of bounds") - if(fpReg3!=null && (fpReg3<0 || fpReg3>65536)) - throw IllegalArgumentException("fpReg3 out of bounds") - + if(value!=null && opcode !in OpcodesWithAddress) { when (type) { VmDataType.BYTE -> { diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index 9cbd0db51..22fe2e645 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -389,7 +389,7 @@ class CodeGen(internal val program: PtProgram, } else { val factorReg = vmRegisters.nextFreeFloat() code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor) - code += VmCodeInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = fpReg, fpReg3 = factorReg) + code += VmCodeInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = factorReg) } return code } @@ -432,7 +432,7 @@ class CodeGen(internal val program: PtProgram, } else { val factorReg = vmRegisters.nextFreeFloat() code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor) - code += VmCodeInstruction(Opcode.DIV, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = fpReg, fpReg3 = factorReg) + code += VmCodeInstruction(Opcode.DIV, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = factorReg) } return code } diff --git a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt index d72d712e2..3dfb8eb2d 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/ExpressionGen.kt @@ -487,7 +487,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.right, -1, rightResultFpReg) - code += VmCodeInstruction(Opcode.DIV, vmDt, fpReg1 = resultFpRegister, fpReg2=resultFpRegister, fpReg3=rightResultFpReg) + code += VmCodeInstruction(Opcode.DIV, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg) } } else { if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { @@ -521,7 +521,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.right, -1, rightResultFpReg) - code += VmCodeInstruction(Opcode.MUL, vmDt, fpReg1 = resultFpRegister, fpReg2 = resultFpRegister, fpReg3 = rightResultFpReg) + code += VmCodeInstruction(Opcode.MUL, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg) } } else { if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) { @@ -553,7 +553,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.right, -1, rightResultFpReg) - code += VmCodeInstruction(Opcode.SUB, vmDt, fpReg1=resultFpRegister, fpReg2=resultFpRegister, fpReg3=rightResultFpReg) + code += VmCodeInstruction(Opcode.SUB, vmDt, fpReg1=resultFpRegister, fpReg2=rightResultFpReg) } } else { if((binExpr.right as? PtNumber)?.number==1.0) { @@ -585,7 +585,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) { val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.right, -1, rightResultFpReg) - code += VmCodeInstruction(Opcode.ADD, vmDt, fpReg1=resultFpRegister, fpReg2=resultFpRegister, fpReg3=rightResultFpReg) + code += VmCodeInstruction(Opcode.ADD, vmDt, fpReg1=resultFpRegister, fpReg2=rightResultFpReg) } } else { if((binExpr.left as? PtNumber)?.number==1.0) { diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index da739f115..691e9d702 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -22,7 +22,7 @@ sub pow(float value, float power) -> float { %asm {{ loadm.f fr0,{floats.pow.value} loadm.f fr1,{floats.pow.power} - fpow.f fr0,fr0,fr1 + fpow.f fr0,fr1 return }} } diff --git a/examples/test.p8 b/examples/test.p8 index beebe38eb..29e0b32cd 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -27,6 +27,7 @@ main { float fl1 = 1.1 float fl2 = 2.2 + floats.print_f(floats.pow(fl1,fl2)) if fl1==fl2 txt.print("equals!?\n") diff --git a/virtualmachine/src/prog8/vm/Assembler.kt b/virtualmachine/src/prog8/vm/Assembler.kt index 5cdec251e..ce05cf9fe 100644 --- a/virtualmachine/src/prog8/vm/Assembler.kt +++ b/virtualmachine/src/prog8/vm/Assembler.kt @@ -157,6 +157,10 @@ class Assembler { fpReg2 = fpReg3 fpReg3 = null } + if(fpReg3!=null) + throw IllegalArgumentException("too many fpreg arguments $line") + // TODO also check reg3 + if(type!=null && type !in formats) throw IllegalArgumentException("invalid type code for $line") @@ -196,7 +200,7 @@ class Assembler { if(format.fpValue) floatValue = value!! - program.add(Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, fpReg3, value = intValue, fpValue = floatValue)) + program.add(Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, value = intValue, fpValue = floatValue)) } } diff --git a/virtualmachine/src/prog8/vm/Instructions.kt b/virtualmachine/src/prog8/vm/Instructions.kt index 3ee9425e4..77c518806 100644 --- a/virtualmachine/src/prog8/vm/Instructions.kt +++ b/virtualmachine/src/prog8/vm/Instructions.kt @@ -138,7 +138,7 @@ ftoub reg1, fpreg1 - reg1 = fpreg1 as unsigned byte ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte 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 +fpow fpreg1, fpreg2 - fpreg1 = fpreg1 to the power of fpreg2 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 @@ -292,7 +292,6 @@ data class Instruction( val reg3: Int?=null, // 0-$ffff val fpReg1: Int?=null, // 0-$ffff val fpReg2: Int?=null, // 0-$ffff - val fpReg3: Int?=null, // 0-$ffff val value: Int?=null, // 0-$ffff val fpValue: Float?=null, val symbol: List?=null // alternative to value @@ -308,9 +307,7 @@ data class Instruction( format.reg3 && reg3==null) throw IllegalArgumentException("missing a register (int)") - if(format.fpReg1 && fpReg1==null || - format.fpReg2 && fpReg2==null || - format.fpReg3 && fpReg3==null) + if(format.fpReg1 && fpReg1==null || format.fpReg2 && fpReg2==null) throw IllegalArgumentException("missing a register (float)") if(!format.reg1 && reg1!=null || @@ -318,9 +315,7 @@ data class Instruction( !format.reg3 && reg3!=null) throw IllegalArgumentException("too many registers (int)") - if(!format.fpReg1 && fpReg1!=null || - !format.fpReg2 && fpReg2!=null || - !format.fpReg3 && fpReg3!=null) + if(!format.fpReg1 && fpReg1!=null || !format.fpReg2 && fpReg2!=null) throw IllegalArgumentException("too many registers (float)") if (type==VmDataType.FLOAT) { @@ -329,7 +324,7 @@ data class Instruction( } else { if(format.value && (value==null && symbol==null)) throw IllegalArgumentException("$opcode: missing a value or symbol") - if (fpReg1 != null || fpReg2 != null || fpReg3 != null) + if (fpReg1 != null || fpReg2 != null) throw java.lang.IllegalArgumentException("$opcode: integer point instruction can't use floating point registers") } } @@ -363,10 +358,6 @@ data class Instruction( result.add("fr$it") result.add(",") } - fpReg3?.let { - result.add("fr$it") - result.add(",") - } value?.let { result.add(it.toString()) result.add(",") @@ -386,7 +377,7 @@ data class Instruction( data class InstructionFormat(val datatype: VmDataType?, val reg1: Boolean, val reg2: Boolean, val reg3: Boolean, - val fpReg1: Boolean, val fpReg2: Boolean, val fpReg3: Boolean, + val fpReg1: Boolean, val fpReg2: Boolean, val value: Boolean, val fpValue: Boolean) { companion object { @@ -398,7 +389,6 @@ data class InstructionFormat(val datatype: VmDataType?, var reg3 = false var fpreg1 = false var fpreg2 = false - var fpreg3 = false var value = false var fpvalue = false val splits = part.splitToSequence(',').iterator() @@ -410,20 +400,19 @@ data class InstructionFormat(val datatype: VmDataType?, "r3" -> reg3=true "fr1" -> fpreg1=true "fr2" -> fpreg2=true - "fr3" -> fpreg3=true "v" -> value = true "fv" -> fpvalue = true else -> throw IllegalArgumentException(spec) } } if(typespec=="N") - result[null] = InstructionFormat(null, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue) + result[null] = InstructionFormat(null, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue) if('B' in typespec) - result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue) + result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue) if('W' in typespec) - result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue) + result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue) if('F' in typespec) - result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue) + result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue) } return result } @@ -482,10 +471,10 @@ val instructionFormats = mutableMapOf( Opcode.DEC to InstructionFormat.from("BW,r1"), Opcode.DECM to InstructionFormat.from("BW,v"), Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"), - Opcode.ADD to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"), - Opcode.SUB to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"), - Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"), - Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"), + Opcode.ADD to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), + Opcode.SUB to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), + Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), + Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"), Opcode.SQRT to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"), Opcode.SGN to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"), Opcode.RND to InstructionFormat.from("BW,r1 | F,fr1"), @@ -515,7 +504,7 @@ val instructionFormats = mutableMapOf( Opcode.FTOSB to InstructionFormat.from("F,r1,fr1"), Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"), Opcode.FTOSW to InstructionFormat.from("F,r1,fr1"), - Opcode.FPOW to InstructionFormat.from("F,fr1,fr2,fr3"), + Opcode.FPOW to InstructionFormat.from("F,fr1,fr2"), Opcode.FABS to InstructionFormat.from("F,fr1,fr2"), Opcode.FSIN to InstructionFormat.from("F,fr1,fr2"), Opcode.FCOS to InstructionFormat.from("F,fr1,fr2"), diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 0d15065ff..985fff97c 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -647,7 +647,7 @@ class VirtualMachine(val memory: Memory, program: List) { when(i.type!!) { VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("+", i.reg1!!, i.reg2!!, i.reg3!!) - VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!, i.fpReg3!!) + VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!) } pc++ } @@ -656,7 +656,7 @@ class VirtualMachine(val memory: Memory, program: List) { when(i.type!!) { VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("-", i.reg1!!, i.reg2!!, i.reg3!!) - VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!, i.fpReg3!!) + VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!) } pc++ } @@ -664,7 +664,7 @@ class VirtualMachine(val memory: Memory, program: List) { when(i.type!!) { VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("*", i.reg1!!, i.reg2!!, i.reg3!!) - VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!, i.fpReg3!!) + VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!) } pc++ } @@ -673,7 +673,7 @@ class VirtualMachine(val memory: Memory, program: List) { when(i.type!!) { VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.WORD -> arithWord("/", i.reg1!!, i.reg2!!, i.reg3!!) - VmDataType.FLOAT -> arithFloat("/", i.fpReg1!!, i.fpReg2!!, i.fpReg3!!) + VmDataType.FLOAT -> arithFloat("/", i.fpReg1!!, i.fpReg2!!) } pc++ } @@ -784,9 +784,9 @@ class VirtualMachine(val memory: Memory, program: List) { registers.setUW(reg1, result.toUShort()) } - private fun arithFloat(operator: String, fpReg1: Int, fpReg2: Int, fpReg3: Int) { - val left = registers.getFloat(fpReg2) - val right = registers.getFloat(fpReg3) + private fun arithFloat(operator: String, fpReg1: Int, fpReg2: Int) { + val left = registers.getFloat(fpReg1) + val right = registers.getFloat(fpReg2) val result = when(operator) { "+" -> left + right "-" -> left - right @@ -1070,9 +1070,9 @@ class VirtualMachine(val memory: Memory, program: List) { } private fun InsFPOW(i: Instruction) { - val value = registers.getFloat(i.fpReg2!!) - val exponent = registers.getFloat(i.fpReg3!!) - registers.setFloat(i.fpReg1!!, value.pow(exponent)) + val value = registers.getFloat(i.fpReg1!!) + val exponent = registers.getFloat(i.fpReg2!!) + registers.setFloat(i.fpReg1, value.pow(exponent)) pc++ }