vm: limit float instructions to just 2 register args

This commit is contained in:
Irmen de Jong 2022-05-11 22:09:46 +02:00
parent 74c05d00a9
commit 4be7bc8323
8 changed files with 39 additions and 48 deletions

View File

@ -80,12 +80,11 @@ internal class VmCodeInstruction(
reg3: Int?=null, // 0-$ffff reg3: Int?=null, // 0-$ffff
fpReg1: Int?=null, // 0-$ffff fpReg1: Int?=null, // 0-$ffff
fpReg2: Int?=null, // 0-$ffff fpReg2: Int?=null, // 0-$ffff
fpReg3: Int?=null, // 0-$ffff
value: Int?=null, // 0-$ffff value: Int?=null, // 0-$ffff
fpValue: Float?=null, fpValue: Float?=null,
symbol: List<String>?=null // alternative to value symbol: List<String>?=null // alternative to value
): VmCodeLine() { ): 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 { init {
if(reg1!=null && (reg1<0 || reg1>65536)) if(reg1!=null && (reg1<0 || reg1>65536))
@ -98,9 +97,7 @@ internal class VmCodeInstruction(
throw IllegalArgumentException("fpReg1 out of bounds") throw IllegalArgumentException("fpReg1 out of bounds")
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536)) if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
throw IllegalArgumentException("fpReg2 out of bounds") 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) { if(value!=null && opcode !in OpcodesWithAddress) {
when (type) { when (type) {
VmDataType.BYTE -> { VmDataType.BYTE -> {

View File

@ -389,7 +389,7 @@ class CodeGen(internal val program: PtProgram,
} else { } else {
val factorReg = vmRegisters.nextFreeFloat() val factorReg = vmRegisters.nextFreeFloat()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor) 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 return code
} }
@ -432,7 +432,7 @@ class CodeGen(internal val program: PtProgram,
} else { } else {
val factorReg = vmRegisters.nextFreeFloat() val factorReg = vmRegisters.nextFreeFloat()
code += VmCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor) 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 return code
} }

View File

@ -487,7 +487,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg) 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 { } else {
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) { if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
@ -521,7 +521,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg) 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 { } else {
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) { if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
@ -553,7 +553,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg) 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 { } else {
if((binExpr.right as? PtNumber)?.number==1.0) { if((binExpr.right as? PtNumber)?.number==1.0) {
@ -585,7 +585,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat() val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(binExpr.left, -1, resultFpRegister) code += translateExpression(binExpr.left, -1, resultFpRegister)
code += translateExpression(binExpr.right, -1, rightResultFpReg) 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 { } else {
if((binExpr.left as? PtNumber)?.number==1.0) { if((binExpr.left as? PtNumber)?.number==1.0) {

View File

@ -22,7 +22,7 @@ sub pow(float value, float power) -> float {
%asm {{ %asm {{
loadm.f fr0,{floats.pow.value} loadm.f fr0,{floats.pow.value}
loadm.f fr1,{floats.pow.power} loadm.f fr1,{floats.pow.power}
fpow.f fr0,fr0,fr1 fpow.f fr0,fr1
return return
}} }}
} }

View File

@ -27,6 +27,7 @@ main {
float fl1 = 1.1 float fl1 = 1.1
float fl2 = 2.2 float fl2 = 2.2
floats.print_f(floats.pow(fl1,fl2))
if fl1==fl2 if fl1==fl2
txt.print("equals!?\n") txt.print("equals!?\n")

View File

@ -157,6 +157,10 @@ class Assembler {
fpReg2 = fpReg3 fpReg2 = fpReg3
fpReg3 = null fpReg3 = null
} }
if(fpReg3!=null)
throw IllegalArgumentException("too many fpreg arguments $line")
// TODO also check reg3
if(type!=null && type !in formats) if(type!=null && type !in formats)
throw IllegalArgumentException("invalid type code for $line") throw IllegalArgumentException("invalid type code for $line")
@ -196,7 +200,7 @@ class Assembler {
if(format.fpValue) if(format.fpValue)
floatValue = value!! 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))
} }
} }

View File

@ -138,7 +138,7 @@ ftoub reg1, fpreg1 - reg1 = fpreg1 as unsigned byte
ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte
ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word
ftosw reg1, fpreg1 - reg1 = fpreg1 as signed 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) 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 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 reg3: Int?=null, // 0-$ffff
val fpReg1: Int?=null, // 0-$ffff val fpReg1: Int?=null, // 0-$ffff
val fpReg2: Int?=null, // 0-$ffff val fpReg2: Int?=null, // 0-$ffff
val fpReg3: Int?=null, // 0-$ffff
val value: Int?=null, // 0-$ffff val value: Int?=null, // 0-$ffff
val fpValue: Float?=null, val fpValue: Float?=null,
val symbol: List<String>?=null // alternative to value val symbol: List<String>?=null // alternative to value
@ -308,9 +307,7 @@ data class Instruction(
format.reg3 && reg3==null) format.reg3 && reg3==null)
throw IllegalArgumentException("missing a register (int)") throw IllegalArgumentException("missing a register (int)")
if(format.fpReg1 && fpReg1==null || if(format.fpReg1 && fpReg1==null || format.fpReg2 && fpReg2==null)
format.fpReg2 && fpReg2==null ||
format.fpReg3 && fpReg3==null)
throw IllegalArgumentException("missing a register (float)") throw IllegalArgumentException("missing a register (float)")
if(!format.reg1 && reg1!=null || if(!format.reg1 && reg1!=null ||
@ -318,9 +315,7 @@ data class Instruction(
!format.reg3 && reg3!=null) !format.reg3 && reg3!=null)
throw IllegalArgumentException("too many registers (int)") throw IllegalArgumentException("too many registers (int)")
if(!format.fpReg1 && fpReg1!=null || if(!format.fpReg1 && fpReg1!=null || !format.fpReg2 && fpReg2!=null)
!format.fpReg2 && fpReg2!=null ||
!format.fpReg3 && fpReg3!=null)
throw IllegalArgumentException("too many registers (float)") throw IllegalArgumentException("too many registers (float)")
if (type==VmDataType.FLOAT) { if (type==VmDataType.FLOAT) {
@ -329,7 +324,7 @@ data class Instruction(
} else { } else {
if(format.value && (value==null && symbol==null)) if(format.value && (value==null && symbol==null))
throw IllegalArgumentException("$opcode: missing a value or symbol") 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") 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("fr$it")
result.add(",") result.add(",")
} }
fpReg3?.let {
result.add("fr$it")
result.add(",")
}
value?.let { value?.let {
result.add(it.toString()) result.add(it.toString())
result.add(",") result.add(",")
@ -386,7 +377,7 @@ data class Instruction(
data class InstructionFormat(val datatype: VmDataType?, data class InstructionFormat(val datatype: VmDataType?,
val reg1: Boolean, val reg2: Boolean, val reg3: Boolean, 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 value: Boolean,
val fpValue: Boolean) { val fpValue: Boolean) {
companion object { companion object {
@ -398,7 +389,6 @@ data class InstructionFormat(val datatype: VmDataType?,
var reg3 = false var reg3 = false
var fpreg1 = false var fpreg1 = false
var fpreg2 = false var fpreg2 = false
var fpreg3 = false
var value = false var value = false
var fpvalue = false var fpvalue = false
val splits = part.splitToSequence(',').iterator() val splits = part.splitToSequence(',').iterator()
@ -410,20 +400,19 @@ data class InstructionFormat(val datatype: VmDataType?,
"r3" -> reg3=true "r3" -> reg3=true
"fr1" -> fpreg1=true "fr1" -> fpreg1=true
"fr2" -> fpreg2=true "fr2" -> fpreg2=true
"fr3" -> fpreg3=true
"v" -> value = true "v" -> value = true
"fv" -> fpvalue = true "fv" -> fpvalue = true
else -> throw IllegalArgumentException(spec) else -> throw IllegalArgumentException(spec)
} }
} }
if(typespec=="N") 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) 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) 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) 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 return result
} }
@ -482,10 +471,10 @@ val instructionFormats = mutableMapOf(
Opcode.DEC to InstructionFormat.from("BW,r1"), Opcode.DEC to InstructionFormat.from("BW,r1"),
Opcode.DECM to InstructionFormat.from("BW,v"), Opcode.DECM to InstructionFormat.from("BW,v"),
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"), Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
Opcode.ADD 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,fr3"), Opcode.SUB to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"), Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"), Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2"),
Opcode.SQRT to InstructionFormat.from("BW,r1,r2 | 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.SGN to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.RND to InstructionFormat.from("BW,r1 | F,fr1"), 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.FTOSB to InstructionFormat.from("F,r1,fr1"),
Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"), Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"),
Opcode.FTOSW 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.FABS to InstructionFormat.from("F,fr1,fr2"),
Opcode.FSIN to InstructionFormat.from("F,fr1,fr2"), Opcode.FSIN to InstructionFormat.from("F,fr1,fr2"),
Opcode.FCOS to InstructionFormat.from("F,fr1,fr2"), Opcode.FCOS to InstructionFormat.from("F,fr1,fr2"),

View File

@ -647,7 +647,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!, i.reg3!!)
VmDataType.WORD -> arithWord("+", 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++ pc++
} }
@ -656,7 +656,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!, i.reg3!!)
VmDataType.WORD -> arithWord("-", 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++ pc++
} }
@ -664,7 +664,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!, i.reg3!!)
VmDataType.WORD -> arithWord("*", 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++ pc++
} }
@ -673,7 +673,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) { when(i.type!!) {
VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!, i.reg3!!) VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!, i.reg3!!)
VmDataType.WORD -> arithWord("/", 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++ pc++
} }
@ -784,9 +784,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUW(reg1, result.toUShort()) registers.setUW(reg1, result.toUShort())
} }
private fun arithFloat(operator: String, fpReg1: Int, fpReg2: Int, fpReg3: Int) { private fun arithFloat(operator: String, fpReg1: Int, fpReg2: Int) {
val left = registers.getFloat(fpReg2) val left = registers.getFloat(fpReg1)
val right = registers.getFloat(fpReg3) val right = registers.getFloat(fpReg2)
val result = when(operator) { val result = when(operator) {
"+" -> left + right "+" -> left + right
"-" -> left - right "-" -> left - right
@ -1070,9 +1070,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
} }
private fun InsFPOW(i: Instruction) { private fun InsFPOW(i: Instruction) {
val value = registers.getFloat(i.fpReg2!!) val value = registers.getFloat(i.fpReg1!!)
val exponent = registers.getFloat(i.fpReg3!!) val exponent = registers.getFloat(i.fpReg2!!)
registers.setFloat(i.fpReg1!!, value.pow(exponent)) registers.setFloat(i.fpReg1, value.pow(exponent))
pc++ pc++
} }