vm: add in-place add/sub

This commit is contained in:
Irmen de Jong 2022-05-19 22:54:50 +02:00
parent c769920b6e
commit 461b6499ef
5 changed files with 162 additions and 25 deletions

View File

@ -84,8 +84,8 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
origAssign: PtAssignment
): VmCodeChunk {
when(operator) {
"+" -> { /* TODO */ }
"-" -> { /* TODO */ }
"+" -> return expressionEval.operatorPlusInplace(targetAddress, vmDt, right)
"-" -> return expressionEval.operatorMinusInplace(targetAddress, vmDt, right)
"*" -> { /* TODO */ }
"/" -> { /* TODO */ }
"|" -> { /* TODO */ }

View File

@ -611,6 +611,30 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
internal fun operatorMinusInplace(targetAddress: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk {
val code = VmCodeChunk()
if(vmDt==VmDataType.FLOAT) {
if((operand as? PtNumber)?.number==1.0) {
code += VmCodeInstruction(Opcode.DECM, vmDt, value=targetAddress)
}
else {
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(operand, -1, operandFpReg)
code += VmCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=targetAddress)
}
} else {
if((operand as? PtNumber)?.number==1.0) {
code += VmCodeInstruction(Opcode.DECM, vmDt, value=targetAddress)
}
else {
val operandReg = codeGen.vmRegisters.nextFree()
code += translateExpression(operand, operandReg, -1)
code += VmCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = targetAddress)
}
}
return code
}
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
if(vmDt==VmDataType.FLOAT) {
@ -647,6 +671,30 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
return code
}
internal fun operatorPlusInplace(targetAddress: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk {
val code = VmCodeChunk()
if(vmDt==VmDataType.FLOAT) {
if((operand as? PtNumber)?.number==1.0) {
code += VmCodeInstruction(Opcode.INCM, vmDt, value = targetAddress)
}
else {
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(operand, -1, operandFpReg)
code += VmCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value=targetAddress)
}
} else {
if((operand as? PtNumber)?.number==1.0) {
code += VmCodeInstruction(Opcode.INCM, vmDt, value = targetAddress)
}
else {
val operandReg = codeGen.vmRegisters.nextFree()
code += translateExpression(operand, operandReg, -1)
code += VmCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=targetAddress)
}
}
return code
}
fun translate(fcall: PtFunctionCall, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
val subroutine = codeGen.symbolTable.flat.getValue(fcall.functionName) as StSub
val code = VmCodeChunk()

View File

@ -24,6 +24,9 @@ main {
xx = xx / 6
txt.print_b(xx) ; -17
txt.nl()
xx = xx * 5
txt.print_b(xx) ; -85
txt.nl()
txt.nl()
; xx = xx+3*yy

View File

@ -96,6 +96,7 @@ decm address - memory at address -= 1
neg reg1 - reg1 = sign negation of reg1
negm address - sign negate memory at address
add reg1, reg2 - reg1 += reg2 (unsigned + signed)
addm reg1, address - memory at address += reg1 (unsigned + signed)
sub reg1, reg2 - reg1 -= reg2 (unsigned + signed)
mul reg1, reg2 - unsigned multiply reg1 *= reg2 note: byte*byte->byte, no type extension to word!
div reg1, reg2 - unsigned division reg1 /= reg2 note: division by zero yields max int $ff/$ffff
@ -215,10 +216,15 @@ enum class Opcode {
NEG,
NEGM,
ADD,
ADDM,
SUB,
SUBM,
MUL,
MULM,
DIV,
DIVM,
DIVS,
DIVSM,
MOD,
SQRT,
SGN,
@ -475,10 +481,15 @@ val instructionFormats = mutableMapOf(
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
Opcode.NEGM to InstructionFormat.from("BW,v | F,v"),
Opcode.ADD to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.ADDM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.SUB to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.SUBM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.MUL to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.DIV to InstructionFormat.from("BW,r1,r2"),
Opcode.MULM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.DIV to InstructionFormat.from("BW,r1,r2"),
Opcode.DIVM to InstructionFormat.from("BW,r1,v"),
Opcode.DIVS to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.DIVSM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
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"),

View File

@ -138,10 +138,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.NEG -> InsNEG(ins)
Opcode.NEGM -> InsNEGM(ins)
Opcode.ADD -> InsADD(ins)
Opcode.ADDM -> InsADDM(ins)
Opcode.SUB -> InsSUB(ins)
Opcode.SUBM -> InsSUBM(ins)
Opcode.MUL -> InsMUL(ins)
Opcode.MULM -> TODO()
Opcode.DIV -> InsDIV(ins)
Opcode.DIVM -> TODO()
Opcode.DIVS -> InsDIVS(ins)
Opcode.DIVSM -> TODO()
Opcode.MOD -> InsMOD(ins)
Opcode.SGN -> InsSGN(ins)
Opcode.CMP -> InsCMP(ins)
@ -194,7 +199,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.FFLOOR -> InsFFLOOR(ins)
Opcode.FCEIL -> InsFCEIL(ins)
Opcode.FCOMP -> InsFCOMP(ins)
//else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
}
}
@ -662,7 +667,27 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByte("+", i.reg1!!, i.reg2!!)
VmDataType.WORD -> plusMinusMultAnyWord("+", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!)
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
val result = arithFloat(left, "+", right)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
private fun InsADDM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByteInplace("+", i.reg1!!, address)
VmDataType.WORD -> plusMinusMultAnyWordInplace("+", i.reg1!!, address)
VmDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "+", right)
memory.setFloat(address, result)
}
}
pc++
}
@ -671,15 +696,41 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByte("-", i.reg1!!, i.reg2!!)
VmDataType.WORD -> plusMinusMultAnyWord("-", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!)
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
val result = arithFloat(left, "-", right)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
private fun InsSUBM(i: Instruction) {
val address = i.value!!
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByteInplace("-", i.reg1!!, address)
VmDataType.WORD -> plusMinusMultAnyWordInplace("-", i.reg1!!, address)
VmDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "-", right)
memory.setFloat(address, result)
}
}
pc++
}
private fun InsMUL(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> plusMinusMultAnyByte("*", i.reg1!!, i.reg2!!)
VmDataType.WORD -> plusMinusMultAnyWord("*", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!)
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
val result = arithFloat(left, "*", right)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
@ -697,7 +748,12 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
when(i.type!!) {
VmDataType.BYTE -> divModByteSigned("/", i.reg1!!, i.reg2!!)
VmDataType.WORD -> divModWordSigned("/", i.reg1!!, i.reg2!!)
VmDataType.FLOAT -> arithFloat("/", i.fpReg1!!, i.fpReg2!!)
VmDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
val result = arithFloat(left, "/", right)
registers.setFloat(i.fpReg1, result)
}
}
pc++
}
@ -780,6 +836,18 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUB(reg1, result.toUByte())
}
private fun plusMinusMultAnyByteInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getUB(address)
val operand = registers.getUB(reg1)
val result = when(operator) {
"+" -> memvalue + operand
"-" -> memvalue - operand
"*" -> memvalue * operand
else -> throw IllegalArgumentException("operator byte $operator")
}
memory.setUB(address, result.toUByte())
}
private fun divModByteSigned(operator: String, reg1: Int, reg2: Int) {
val left = registers.getSB(reg1)
val right = registers.getSB(reg2)
@ -826,6 +894,18 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setUW(reg1, result.toUShort())
}
private fun plusMinusMultAnyWordInplace(operator: String, reg1: Int, address: Int) {
val memvalue = memory.getUW(address)
val operand = registers.getUW(reg1)
val result = when(operator) {
"+" -> memvalue + operand
"-" -> memvalue - operand
"*" -> memvalue * operand
else -> throw IllegalArgumentException("operator word $operator")
}
registers.setUW(reg1, result.toUShort())
}
private fun divModWordUnsigned(operator: String, reg1: Int, reg2: Int) {
val left = registers.getUW(reg1)
val right = registers.getUW(reg2)
@ -860,24 +940,19 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
registers.setSW(reg1, result.toShort())
}
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
"*" -> left * right
"/" -> {
if(right==0f) Float.MAX_VALUE
else left / right
}
"%" -> {
if(right==0f) Float.MAX_VALUE
else left % right
}
else -> throw IllegalArgumentException("operator word $operator")
private fun arithFloat(left: Float, operator: String, right: Float): Float = when(operator) {
"+" -> left + right
"-" -> left - right
"*" -> left * right
"/" -> {
if(right==0f) Float.MAX_VALUE
else left / right
}
registers.setFloat(fpReg1, result)
"%" -> {
if(right==0f) Float.MAX_VALUE
else left % right
}
else -> throw IllegalArgumentException("operator word $operator")
}
private fun InsEXT(i: Instruction) {