mirror of
https://github.com/irmen/prog8.git
synced 2025-01-14 01:29:55 +00:00
vm: add in-place add/sub
This commit is contained in:
parent
c769920b6e
commit
461b6499ef
@ -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 */ }
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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"),
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user