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
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<String>?=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,8 +97,6 @@ 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) {

View File

@ -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
}

View File

@ -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) {

View File

@ -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
}}
}

View File

@ -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")

View File

@ -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))
}
}

View File

@ -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<String>?=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"),

View File

@ -647,7 +647,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
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<Instruction>) {
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<Instruction>) {
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<Instruction>) {
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<Instruction>) {
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<Instruction>) {
}
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++
}