mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
vm: fix signed divide
This commit is contained in:
parent
181b98ef9e
commit
c769920b6e
@ -4,6 +4,7 @@ import prog8.code.ast.*
|
|||||||
import prog8.code.core.AssemblyError
|
import prog8.code.core.AssemblyError
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
import prog8.code.core.Position
|
import prog8.code.core.Position
|
||||||
|
import prog8.code.core.SignedDatatypes
|
||||||
import prog8.vm.Opcode
|
import prog8.vm.Opcode
|
||||||
import prog8.vm.VmDataType
|
import prog8.vm.VmDataType
|
||||||
|
|
||||||
@ -26,10 +27,10 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
|
|
||||||
return if(ident!=null) {
|
return if(ident!=null) {
|
||||||
val address = codeGen.allocations.get(ident.targetName)
|
val address = codeGen.allocations.get(ident.targetName)
|
||||||
assignSelfInMemory(address, assignment.value, assignment.position, assignment)
|
assignSelfInMemory(address, assignment.value, assignment)
|
||||||
} else if(memory != null) {
|
} else if(memory != null) {
|
||||||
if(memory.address is PtNumber) {
|
if(memory.address is PtNumber) {
|
||||||
assignSelfInMemory((memory.address as PtNumber).number.toInt(), assignment.value, assignment.position, assignment)
|
assignSelfInMemory((memory.address as PtNumber).number.toInt(), assignment.value, assignment)
|
||||||
} else {
|
} else {
|
||||||
fallbackAssign(assignment)
|
fallbackAssign(assignment)
|
||||||
}
|
}
|
||||||
@ -44,7 +45,6 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
private fun assignSelfInMemory(
|
private fun assignSelfInMemory(
|
||||||
targetAddress: Int,
|
targetAddress: Int,
|
||||||
value: PtExpression,
|
value: PtExpression,
|
||||||
position: Position,
|
|
||||||
origAssign: PtAssignment
|
origAssign: PtAssignment
|
||||||
): VmCodeChunk {
|
): VmCodeChunk {
|
||||||
val vmDt = codeGen.vmType(value.type)
|
val vmDt = codeGen.vmType(value.type)
|
||||||
@ -53,14 +53,14 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
is PtIdentifier -> return code // do nothing, x=x null assignment.
|
is PtIdentifier -> return code // do nothing, x=x null assignment.
|
||||||
is PtMachineRegister -> return code // do nothing, reg=reg null assignment
|
is PtMachineRegister -> return code // do nothing, reg=reg null assignment
|
||||||
is PtPrefix -> return inplacePrefix(value.operator, vmDt, targetAddress)
|
is PtPrefix -> return inplacePrefix(value.operator, vmDt, targetAddress)
|
||||||
is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, targetAddress, origAssign)
|
is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, targetAddress, origAssign)
|
||||||
is PtMemoryByte -> {
|
is PtMemoryByte -> {
|
||||||
return if (!codeGen.options.compTarget.machine.isIOAddress(targetAddress.toUInt()))
|
return if (!codeGen.options.compTarget.machine.isIOAddress(targetAddress.toUInt()))
|
||||||
code // do nothing, mem=mem null assignment.
|
code // do nothing, mem=mem null assignment.
|
||||||
else {
|
else {
|
||||||
// read and write a (i/o) memory location to itself.
|
// read and write a (i/o) memory location to itself.
|
||||||
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = 0, value = targetAddress.toInt())
|
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = 0, value = targetAddress)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = 0, value = targetAddress.toInt())
|
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = 0, value = targetAddress)
|
||||||
code
|
code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,6 +79,7 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
operator: String,
|
operator: String,
|
||||||
right: PtExpression,
|
right: PtExpression,
|
||||||
vmDt: VmDataType,
|
vmDt: VmDataType,
|
||||||
|
signed: Boolean,
|
||||||
targetAddress: Int,
|
targetAddress: Int,
|
||||||
origAssign: PtAssignment
|
origAssign: PtAssignment
|
||||||
): VmCodeChunk {
|
): VmCodeChunk {
|
||||||
|
@ -433,25 +433,31 @@ 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 = factorReg)
|
code += VmCodeInstruction(Opcode.DIVS, VmDataType.FLOAT, fpReg1 = fpReg, fpReg2 = factorReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun divideByConst(dt: VmDataType, reg: Int, factor: Int): VmCodeChunk {
|
internal fun divideByConst(dt: VmDataType, reg: Int, factor: Int, signed: Boolean): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
if(factor==1)
|
if(factor==1)
|
||||||
return code
|
return code
|
||||||
val pow2 = powersOfTwo.indexOf(factor)
|
val pow2 = powersOfTwo.indexOf(factor)
|
||||||
if(pow2==1) {
|
if(pow2==1) {
|
||||||
// just shift 1 bit
|
// just shift 1 bit
|
||||||
code += VmCodeInstruction(Opcode.LSR, dt, reg1=reg)
|
code += if(signed)
|
||||||
|
VmCodeInstruction(Opcode.ASR, dt, reg1=reg)
|
||||||
|
else
|
||||||
|
VmCodeInstruction(Opcode.LSR, dt, reg1=reg)
|
||||||
}
|
}
|
||||||
else if(pow2>=1) {
|
else if(pow2>=1) {
|
||||||
// just shift multiple bits
|
// just shift multiple bits
|
||||||
val pow2reg = vmRegisters.nextFree()
|
val pow2reg = vmRegisters.nextFree()
|
||||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||||
code += VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
|
code += if(signed)
|
||||||
|
VmCodeInstruction(Opcode.ASRN, dt, reg1=reg, reg2=pow2reg)
|
||||||
|
else
|
||||||
|
VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
|
||||||
} else {
|
} else {
|
||||||
if (factor == 0) {
|
if (factor == 0) {
|
||||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||||
@ -459,7 +465,10 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
else {
|
else {
|
||||||
val factorReg = vmRegisters.nextFree()
|
val factorReg = vmRegisters.nextFree()
|
||||||
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||||
code += VmCodeInstruction(Opcode.DIV, dt, reg1=reg, reg2=factorReg)
|
code += if(signed)
|
||||||
|
VmCodeInstruction(Opcode.DIVS, dt, reg1=reg, reg2=factorReg)
|
||||||
|
else
|
||||||
|
VmCodeInstruction(Opcode.DIV, dt, reg1=reg, reg2=factorReg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
|
@ -281,7 +281,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
"+" -> operatorPlus(binExpr, vmDt, resultRegister, resultFpRegister)
|
"+" -> operatorPlus(binExpr, vmDt, resultRegister, resultFpRegister)
|
||||||
"-" -> operatorMinus(binExpr, vmDt, resultRegister, resultFpRegister)
|
"-" -> operatorMinus(binExpr, vmDt, resultRegister, resultFpRegister)
|
||||||
"*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister)
|
"*" -> operatorMultiply(binExpr, vmDt, resultRegister, resultFpRegister)
|
||||||
"/" -> operatorDivide(binExpr, vmDt, resultRegister, resultFpRegister)
|
"/" -> operatorDivide(binExpr, vmDt, resultRegister, resultFpRegister, signed)
|
||||||
"%" -> operatorModulo(binExpr, vmDt, resultRegister)
|
"%" -> operatorModulo(binExpr, vmDt, resultRegister)
|
||||||
"|", "or" -> operatorOr(binExpr, vmDt, resultRegister)
|
"|", "or" -> operatorOr(binExpr, vmDt, resultRegister)
|
||||||
"&", "and" -> operatorAnd(binExpr, vmDt, resultRegister)
|
"&", "and" -> operatorAnd(binExpr, vmDt, resultRegister)
|
||||||
@ -506,7 +506,11 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun operatorDivide(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
|
private fun operatorDivide(binExpr: PtBinaryExpression,
|
||||||
|
vmDt: VmDataType,
|
||||||
|
resultRegister: Int,
|
||||||
|
resultFpRegister: Int,
|
||||||
|
signed: Boolean): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val constFactorRight = binExpr.right as? PtNumber
|
val constFactorRight = binExpr.right as? PtNumber
|
||||||
if(vmDt==VmDataType.FLOAT) {
|
if(vmDt==VmDataType.FLOAT) {
|
||||||
@ -518,18 +522,24 @@ 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=rightResultFpReg)
|
code += if(signed)
|
||||||
|
VmCodeInstruction(Opcode.DIVS, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
|
||||||
|
else
|
||||||
|
VmCodeInstruction(Opcode.DIV, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
val factor = constFactorRight.number.toInt()
|
val factor = constFactorRight.number.toInt()
|
||||||
code += codeGen.divideByConst(vmDt, resultRegister, factor)
|
code += codeGen.divideByConst(vmDt, resultRegister, factor, signed)
|
||||||
} else {
|
} else {
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||||
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
code += if(signed)
|
||||||
|
VmCodeInstruction(Opcode.DIVS, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||||
|
else
|
||||||
|
VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
|
@ -1,29 +1,48 @@
|
|||||||
|
%import textio
|
||||||
%import math
|
%import math
|
||||||
|
%zeropage dontuse
|
||||||
|
|
||||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
byte xx
|
byte @shared xx = 11
|
||||||
byte yy
|
byte @shared yy = 62
|
||||||
ubyte ubx
|
byte @shared yy2 = 15
|
||||||
|
byte @shared yy3 = 127
|
||||||
|
ubyte @shared ubx = 3
|
||||||
|
|
||||||
xx = xx
|
xx = xx + 9
|
||||||
xx = xx*9
|
txt.print_b(xx) ; 20
|
||||||
xx = yy*9
|
txt.nl()
|
||||||
xx = xx+3*yy
|
xx = xx * 8
|
||||||
xx = xx/yy
|
txt.print_b(xx) ; -96
|
||||||
xx = -xx
|
txt.nl()
|
||||||
@($4000) = @($4000)
|
xx = xx - 7
|
||||||
@($4000) = @($4000) + 2
|
txt.print_b(xx) ; -103
|
||||||
xx = xx | yy
|
txt.nl()
|
||||||
xx = xx & yy
|
xx = xx / 6
|
||||||
xx = xx ^ yy
|
txt.print_b(xx) ; -17
|
||||||
xx = (not xx) as byte
|
txt.nl()
|
||||||
xx = (~xx) as byte
|
txt.nl()
|
||||||
xx++
|
|
||||||
|
|
||||||
ubx = not ubx
|
; xx = xx+3*yy
|
||||||
ubx = ~ubx
|
; xx = xx/yy
|
||||||
|
; xx = -xx
|
||||||
|
; @($4000) = @($4000)
|
||||||
|
; @($4000) = @($4000) + 2
|
||||||
|
; xx = xx ^ yy
|
||||||
|
; xx = xx | yy2
|
||||||
|
; xx = xx & yy3
|
||||||
|
; txt.print_b(xx) ; 63
|
||||||
|
; txt.nl()
|
||||||
|
; xx = (not xx) as byte
|
||||||
|
; xx = (~xx) as byte
|
||||||
|
; xx++
|
||||||
|
; txt.print_b(xx) ; 0
|
||||||
|
; txt.nl()
|
||||||
|
;
|
||||||
|
; ubx = not ubx
|
||||||
|
; ubx = ~ubx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,8 @@ negm address - sign negate memory at address
|
|||||||
add reg1, reg2 - reg1 += reg2 (unsigned + signed)
|
add reg1, reg2 - reg1 += reg2 (unsigned + signed)
|
||||||
sub reg1, reg2 - reg1 -= reg2 (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!
|
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 signed int $ff/$ffff
|
div reg1, reg2 - unsigned division reg1 /= reg2 note: division by zero yields max int $ff/$ffff
|
||||||
|
divs reg1, reg2 - signed division reg1 /= reg2 note: division by zero yields max signed int 127 / 32767
|
||||||
mod reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
|
mod reg1, reg2 - remainder (modulo) of unsigned division reg1 %= reg2 note: division by zero yields max signed int $ff/$ffff
|
||||||
sqrt reg1, reg2 - reg1 is the square root of reg2
|
sqrt reg1, reg2 - reg1 is the square root of reg2
|
||||||
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
||||||
@ -217,6 +218,7 @@ enum class Opcode {
|
|||||||
SUB,
|
SUB,
|
||||||
MUL,
|
MUL,
|
||||||
DIV,
|
DIV,
|
||||||
|
DIVS,
|
||||||
MOD,
|
MOD,
|
||||||
SQRT,
|
SQRT,
|
||||||
SGN,
|
SGN,
|
||||||
@ -475,7 +477,8 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.ADD to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
Opcode.ADD to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
Opcode.SUB to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
Opcode.SUB to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
Opcode.MUL to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
Opcode.MUL to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
Opcode.DIV to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
Opcode.DIV to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.DIVS to InstructionFormat.from("BW,r1,r2 | 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"),
|
||||||
|
@ -136,10 +136,12 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.DEC -> InsDEC(ins)
|
Opcode.DEC -> InsDEC(ins)
|
||||||
Opcode.DECM -> InsDECM(ins)
|
Opcode.DECM -> InsDECM(ins)
|
||||||
Opcode.NEG -> InsNEG(ins)
|
Opcode.NEG -> InsNEG(ins)
|
||||||
|
Opcode.NEGM -> InsNEGM(ins)
|
||||||
Opcode.ADD -> InsADD(ins)
|
Opcode.ADD -> InsADD(ins)
|
||||||
Opcode.SUB -> InsSUB(ins)
|
Opcode.SUB -> InsSUB(ins)
|
||||||
Opcode.MUL -> InsMUL(ins)
|
Opcode.MUL -> InsMUL(ins)
|
||||||
Opcode.DIV -> InsDIV(ins)
|
Opcode.DIV -> InsDIV(ins)
|
||||||
|
Opcode.DIVS -> InsDIVS(ins)
|
||||||
Opcode.MOD -> InsMOD(ins)
|
Opcode.MOD -> InsMOD(ins)
|
||||||
Opcode.SGN -> InsSGN(ins)
|
Opcode.SGN -> InsSGN(ins)
|
||||||
Opcode.CMP -> InsCMP(ins)
|
Opcode.CMP -> InsCMP(ins)
|
||||||
@ -150,7 +152,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.AND -> InsAND(ins)
|
Opcode.AND -> InsAND(ins)
|
||||||
Opcode.OR -> InsOR(ins)
|
Opcode.OR -> InsOR(ins)
|
||||||
Opcode.XOR -> InsXOR(ins)
|
Opcode.XOR -> InsXOR(ins)
|
||||||
|
Opcode.XORM ->InsXORM(ins)
|
||||||
Opcode.NOT -> InsNOT(ins)
|
Opcode.NOT -> InsNOT(ins)
|
||||||
|
Opcode.NOTM -> InsNOTM(ins)
|
||||||
Opcode.ASRN -> InsASRM(ins)
|
Opcode.ASRN -> InsASRM(ins)
|
||||||
Opcode.LSRN -> InsLSRM(ins)
|
Opcode.LSRN -> InsLSRM(ins)
|
||||||
Opcode.LSLN -> InsLSLM(ins)
|
Opcode.LSLN -> InsLSLM(ins)
|
||||||
@ -190,7 +194,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.FFLOOR -> InsFFLOOR(ins)
|
Opcode.FFLOOR -> InsFFLOOR(ins)
|
||||||
Opcode.FCEIL -> InsFCEIL(ins)
|
Opcode.FCEIL -> InsFCEIL(ins)
|
||||||
Opcode.FCOMP -> InsFCOMP(ins)
|
Opcode.FCOMP -> InsFCOMP(ins)
|
||||||
else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
|
//else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,10 +648,20 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsNEGM(i: Instruction) {
|
||||||
|
val address = i.value!!
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> memory.setUB(address, (-memory.getUB(address).toInt()).toUByte())
|
||||||
|
VmDataType.WORD -> memory.setUW(address, (-memory.getUW(address).toInt()).toUShort())
|
||||||
|
VmDataType.FLOAT -> memory.setFloat(address, -memory.getFloat(address))
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsADD(i: Instruction) {
|
private fun InsADD(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> arithByte("+", i.reg1!!, i.reg2!!)
|
VmDataType.BYTE -> plusMinusMultAnyByte("+", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.WORD -> arithWord("+", i.reg1!!, i.reg2!!)
|
VmDataType.WORD -> plusMinusMultAnyWord("+", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!)
|
VmDataType.FLOAT -> arithFloat("+", i.fpReg1!!, i.fpReg2!!)
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
@ -655,16 +669,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
|
|
||||||
private fun InsSUB(i: Instruction) {
|
private fun InsSUB(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> arithByte("-", i.reg1!!, i.reg2!!)
|
VmDataType.BYTE -> plusMinusMultAnyByte("-", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.WORD -> arithWord("-", i.reg1!!, i.reg2!!)
|
VmDataType.WORD -> plusMinusMultAnyWord("-", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!)
|
VmDataType.FLOAT -> arithFloat("-", i.fpReg1!!, i.fpReg2!!)
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
private fun InsMUL(i: Instruction) {
|
private fun InsMUL(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> arithByte("*", i.reg1!!, i.reg2!!)
|
VmDataType.BYTE -> plusMinusMultAnyByte("*", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.WORD -> arithWord("*", i.reg1!!, i.reg2!!)
|
VmDataType.WORD -> plusMinusMultAnyWord("*", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!)
|
VmDataType.FLOAT -> arithFloat("*", i.fpReg1!!, i.fpReg2!!)
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
@ -672,8 +686,17 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
|
|
||||||
private fun InsDIV(i: Instruction) {
|
private fun InsDIV(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> arithByte("/", i.reg1!!, i.reg2!!)
|
VmDataType.BYTE -> divModByteUnsigned("/", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.WORD -> arithWord("/", i.reg1!!, i.reg2!!)
|
VmDataType.WORD -> divModWordUnsigned("/", i.reg1!!, i.reg2!!)
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun InsDIVS(i: 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 -> arithFloat("/", i.fpReg1!!, i.fpReg2!!)
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
@ -681,8 +704,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
|
|
||||||
private fun InsMOD(i: Instruction) {
|
private fun InsMOD(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> arithByte("%", i.reg1!!, i.reg2!!)
|
VmDataType.BYTE -> divModByteUnsigned("%", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.WORD -> arithWord("%", i.reg1!!, i.reg2!!)
|
VmDataType.WORD -> divModWordUnsigned("%", i.reg1!!, i.reg2!!)
|
||||||
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
@ -745,13 +768,39 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun arithByte(operator: String, reg1: Int, reg2: Int) {
|
private fun plusMinusMultAnyByte(operator: String, reg1: Int, reg2: Int) {
|
||||||
val left = registers.getUB(reg1)
|
val left = registers.getUB(reg1)
|
||||||
val right = registers.getUB(reg2)
|
val right = registers.getUB(reg2)
|
||||||
val result = when(operator) {
|
val result = when(operator) {
|
||||||
"+" -> left + right
|
"+" -> left + right
|
||||||
"-" -> left - right
|
"-" -> left - right
|
||||||
"*" -> left * right
|
"*" -> left * right
|
||||||
|
else -> throw IllegalArgumentException("operator byte $operator")
|
||||||
|
}
|
||||||
|
registers.setUB(reg1, result.toUByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun divModByteSigned(operator: String, reg1: Int, reg2: Int) {
|
||||||
|
val left = registers.getSB(reg1)
|
||||||
|
val right = registers.getSB(reg2)
|
||||||
|
val result = when(operator) {
|
||||||
|
"/" -> {
|
||||||
|
if(right==0.toByte()) 127
|
||||||
|
else left / right
|
||||||
|
}
|
||||||
|
"%" -> {
|
||||||
|
if(right==0.toByte()) 127
|
||||||
|
else left % right
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException("operator byte $operator")
|
||||||
|
}
|
||||||
|
registers.setSB(reg1, result.toByte())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun divModByteUnsigned(operator: String, reg1: Int, reg2: Int) {
|
||||||
|
val left = registers.getUB(reg1)
|
||||||
|
val right = registers.getUB(reg2)
|
||||||
|
val result = when(operator) {
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if(right==0.toUByte()) 0xffu
|
if(right==0.toUByte()) 0xffu
|
||||||
else left / right
|
else left / right
|
||||||
@ -765,13 +814,22 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
registers.setUB(reg1, result.toUByte())
|
registers.setUB(reg1, result.toUByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun arithWord(operator: String, reg1: Int, reg2: Int) {
|
private fun plusMinusMultAnyWord(operator: String, reg1: Int, reg2: Int) {
|
||||||
val left = registers.getUW(reg1)
|
val left = registers.getUW(reg1)
|
||||||
val right = registers.getUW(reg2)
|
val right = registers.getUW(reg2)
|
||||||
val result = when(operator) {
|
val result = when(operator) {
|
||||||
"+" -> left + right
|
"+" -> left + right
|
||||||
"-" -> left - right
|
"-" -> left - right
|
||||||
"*" -> left * right
|
"*" -> left * right
|
||||||
|
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)
|
||||||
|
val result = when(operator) {
|
||||||
"/" -> {
|
"/" -> {
|
||||||
if(right==0.toUShort()) 0xffffu
|
if(right==0.toUShort()) 0xffffu
|
||||||
else left / right
|
else left / right
|
||||||
@ -785,6 +843,23 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
registers.setUW(reg1, result.toUShort())
|
registers.setUW(reg1, result.toUShort())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun divModWordSigned(operator: String, reg1: Int, reg2: Int) {
|
||||||
|
val left = registers.getSW(reg1)
|
||||||
|
val right = registers.getSW(reg2)
|
||||||
|
val result = when(operator) {
|
||||||
|
"/" -> {
|
||||||
|
if(right==0.toShort()) 32767
|
||||||
|
else left / right
|
||||||
|
}
|
||||||
|
"%" -> {
|
||||||
|
if(right==0.toShort()) 32767
|
||||||
|
else left % right
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException("operator word $operator")
|
||||||
|
}
|
||||||
|
registers.setSW(reg1, result.toShort())
|
||||||
|
}
|
||||||
|
|
||||||
private fun arithFloat(operator: String, fpReg1: Int, fpReg2: Int) {
|
private fun arithFloat(operator: String, fpReg1: Int, fpReg2: Int) {
|
||||||
val left = registers.getFloat(fpReg1)
|
val left = registers.getFloat(fpReg1)
|
||||||
val right = registers.getFloat(fpReg2)
|
val right = registers.getFloat(fpReg2)
|
||||||
@ -853,6 +928,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsXORM(i: Instruction) {
|
||||||
|
val address = i.value!!
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> memory.setUB(address, (memory.getUB(address) xor registers.getUB(i.reg1!!)))
|
||||||
|
VmDataType.WORD -> memory.setUW(address, (memory.getUW(address) xor registers.getUW(i.reg1!!)))
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsNOT(i: Instruction) {
|
private fun InsNOT(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, if(registers.getUB(i.reg1)==0.toUByte()) 1u else 0u)
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, if(registers.getUB(i.reg1)==0.toUByte()) 1u else 0u)
|
||||||
@ -862,6 +947,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsNOTM(i: Instruction) {
|
||||||
|
val address = i.value!!
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> memory.setUB(address, if(memory.getUB(address)==0.toUByte()) 1u else 0u)
|
||||||
|
VmDataType.WORD -> memory.setUW(address, if(memory.getUW(address)==0.toUShort()) 1u else 0u)
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsASRM(i: Instruction) {
|
private fun InsASRM(i: Instruction) {
|
||||||
val (left: Int, right: Int) = getLogicalOperandsS(i)
|
val (left: Int, right: Int) = getLogicalOperandsS(i)
|
||||||
statusCarry = (left and 1)!=0
|
statusCarry = (left and 1)!=0
|
||||||
|
Loading…
Reference in New Issue
Block a user