mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
added immediate value vm logical instructions because these are so common
This commit is contained in:
parent
314398ba4c
commit
ff1fc28287
@ -111,21 +111,21 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||||
}
|
}
|
||||||
DataType.BYTE -> {
|
DataType.BYTE -> {
|
||||||
val andReg = codeGen.vmRegisters.nextFree()
|
|
||||||
val notNegativeLabel = codeGen.createLabelName()
|
val notNegativeLabel = codeGen.createLabelName()
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=andReg, value=0x80)
|
val compareReg = codeGen.vmRegisters.nextFree()
|
||||||
code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=andReg, reg2=resultRegister)
|
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=compareReg, reg2=resultRegister)
|
||||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=andReg, labelSymbol = notNegativeLabel)
|
code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=compareReg, value=0x80)
|
||||||
|
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=compareReg, labelSymbol = notNegativeLabel)
|
||||||
code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister)
|
||||||
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||||
code += VmCodeLabel(notNegativeLabel)
|
code += VmCodeLabel(notNegativeLabel)
|
||||||
}
|
}
|
||||||
DataType.WORD -> {
|
DataType.WORD -> {
|
||||||
val andReg = codeGen.vmRegisters.nextFree()
|
|
||||||
val notNegativeLabel = codeGen.createLabelName()
|
val notNegativeLabel = codeGen.createLabelName()
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=andReg, value=0x8000)
|
val compareReg = codeGen.vmRegisters.nextFree()
|
||||||
code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=andReg, reg2=resultRegister)
|
code += VmCodeInstruction(Opcode.LOADR, VmDataType.WORD, reg1=compareReg, reg2=resultRegister)
|
||||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=andReg, labelSymbol = notNegativeLabel)
|
code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=compareReg, value=0x8000)
|
||||||
|
code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=compareReg, labelSymbol = notNegativeLabel)
|
||||||
code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister)
|
||||||
code += VmCodeLabel(notNegativeLabel)
|
code += VmCodeLabel(notNegativeLabel)
|
||||||
}
|
}
|
||||||
|
@ -149,10 +149,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
code += VmCodeInstruction(Opcode.NEG, vmDt, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.NEG, vmDt, reg1=resultRegister)
|
||||||
}
|
}
|
||||||
"~" -> {
|
"~" -> {
|
||||||
val regMask = codeGen.vmRegisters.nextFree()
|
|
||||||
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
||||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=mask)
|
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, value=mask)
|
||||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=regMask)
|
|
||||||
}
|
}
|
||||||
else -> throw AssemblyError("weird prefix operator")
|
else -> throw AssemblyError("weird prefix operator")
|
||||||
}
|
}
|
||||||
@ -390,9 +388,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
code += translate(comparisonCall, resultRegister, -1)
|
code += translate(comparisonCall, resultRegister, -1)
|
||||||
if(!notEquals)
|
if(!notEquals)
|
||||||
code += VmCodeInstruction(Opcode.INV, vmDt, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.INV, vmDt, reg1=resultRegister)
|
||||||
val maskReg = codeGen.vmRegisters.nextFree()
|
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1)
|
||||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=maskReg, value=1)
|
|
||||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=maskReg)
|
|
||||||
} else {
|
} else {
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
@ -462,10 +458,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
|
|
||||||
private fun operatorXor(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
private fun operatorXor(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
if(binExpr.right is PtNumber) {
|
||||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
} else {
|
||||||
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
|
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||||
|
code += VmCodeInstruction(Opcode.XORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||||
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,10 +480,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
|
|
||||||
private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
if(binExpr.right is PtNumber) {
|
||||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
code += VmCodeInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
} else {
|
||||||
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
|
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||||
|
code += VmCodeInstruction(Opcode.ANDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||||
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,10 +502,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
|
|
||||||
private fun operatorOr(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
private fun operatorOr(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
if(binExpr.right is PtNumber) {
|
||||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
code += VmCodeInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
} else {
|
||||||
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||||
|
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||||
|
code += VmCodeInstruction(Opcode.ORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||||
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- vm: add logical instructions taking immediate value as well
|
- fix compiler crash (abs(fl)) ; WHY IS THIS GETTING A BOOLEAN CAST???
|
||||||
|
- vm why is bb = bb2 and true generating so large code?
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,18 +1,13 @@
|
|||||||
%import textio
|
%import textio
|
||||||
|
%import floats
|
||||||
%zeropage basicsafe
|
%zeropage basicsafe
|
||||||
|
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
bool @shared zz
|
float fl
|
||||||
ubyte xx
|
fl = -3.14
|
||||||
ubyte yy
|
floats.print_f(abs(fl)) ; WHY IS THIS GETTING A BOOLEAN CAST???
|
||||||
|
txt.nl()
|
||||||
while xx<42 {
|
|
||||||
xx = yy+99
|
|
||||||
xx = yy*5
|
|
||||||
}
|
|
||||||
|
|
||||||
txt.print_ub(xx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,9 +126,12 @@ LOGICAL/BITWISE
|
|||||||
---------------
|
---------------
|
||||||
All have type b or w.
|
All have type b or w.
|
||||||
|
|
||||||
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
andr reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||||
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
and reg1, value - reg1 = reg1 bitwise and value
|
||||||
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
orr reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||||
|
or reg1, value - reg1 = reg1 bitwise or value
|
||||||
|
xorr reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||||
|
xor reg1, value - reg1 = reg1 bitwise xor value
|
||||||
inv reg1 - reg1 = bitwise invert of reg1 (all bits flipped)
|
inv reg1 - reg1 = bitwise invert of reg1 (all bits flipped)
|
||||||
lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
|
lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
|
||||||
asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit
|
asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit
|
||||||
@ -265,10 +268,13 @@ enum class Opcode {
|
|||||||
EXT,
|
EXT,
|
||||||
EXTS,
|
EXTS,
|
||||||
|
|
||||||
|
ANDR,
|
||||||
AND,
|
AND,
|
||||||
ANDM,
|
ANDM,
|
||||||
|
ORR,
|
||||||
OR,
|
OR,
|
||||||
ORM,
|
ORM,
|
||||||
|
XORR,
|
||||||
XOR,
|
XOR,
|
||||||
XORM,
|
XORM,
|
||||||
INV,
|
INV,
|
||||||
@ -567,11 +573,14 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
|
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
|
||||||
Opcode.EXT to InstructionFormat.from("BW,r1"),
|
Opcode.EXT to InstructionFormat.from("BW,r1"),
|
||||||
Opcode.EXTS to InstructionFormat.from("BW,r1"),
|
Opcode.EXTS to InstructionFormat.from("BW,r1"),
|
||||||
Opcode.AND to InstructionFormat.from("BW,r1,r2"),
|
Opcode.ANDR to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.AND to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.ANDM to InstructionFormat.from("BW,r1,v"),
|
Opcode.ANDM to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.OR to InstructionFormat.from("BW,r1,r2"),
|
Opcode.ORR to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.OR to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.ORM to InstructionFormat.from("BW,r1,v"),
|
Opcode.ORM to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
|
Opcode.XORR to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.XOR to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.XORM to InstructionFormat.from("BW,r1,v"),
|
Opcode.XORM to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.INV to InstructionFormat.from("BW,r1"),
|
Opcode.INV to InstructionFormat.from("BW,r1"),
|
||||||
Opcode.INVM to InstructionFormat.from("BW,v"),
|
Opcode.INVM to InstructionFormat.from("BW,v"),
|
||||||
|
@ -163,10 +163,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.SQRT -> InsSQRT(ins)
|
Opcode.SQRT -> InsSQRT(ins)
|
||||||
Opcode.EXT -> InsEXT(ins)
|
Opcode.EXT -> InsEXT(ins)
|
||||||
Opcode.EXTS -> InsEXTS(ins)
|
Opcode.EXTS -> InsEXTS(ins)
|
||||||
|
Opcode.ANDR -> InsANDR(ins)
|
||||||
Opcode.AND -> InsAND(ins)
|
Opcode.AND -> InsAND(ins)
|
||||||
Opcode.ANDM -> InsANDM(ins)
|
Opcode.ANDM -> InsANDM(ins)
|
||||||
|
Opcode.ORR -> InsORR(ins)
|
||||||
Opcode.OR -> InsOR(ins)
|
Opcode.OR -> InsOR(ins)
|
||||||
Opcode.ORM -> InsORM(ins)
|
Opcode.ORM -> InsORM(ins)
|
||||||
|
Opcode.XORR -> InsXORR(ins)
|
||||||
Opcode.XOR -> InsXOR(ins)
|
Opcode.XOR -> InsXOR(ins)
|
||||||
Opcode.XORM ->InsXORM(ins)
|
Opcode.XORM ->InsXORM(ins)
|
||||||
Opcode.INV -> InsINV(ins)
|
Opcode.INV -> InsINV(ins)
|
||||||
@ -1295,7 +1298,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsAND(i: Instruction) {
|
private fun InsANDR(i: Instruction) {
|
||||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left and right).toUByte())
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left and right).toUByte())
|
||||||
@ -1305,6 +1308,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsAND(i: Instruction) {
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1) and i.value!!.toUByte())
|
||||||
|
VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1) and i.value!!.toUShort())
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsANDM(i: Instruction) {
|
private fun InsANDM(i: Instruction) {
|
||||||
val address = i.value!!
|
val address = i.value!!
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
@ -1323,7 +1335,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsOR(i: Instruction) {
|
private fun InsORR(i: Instruction) {
|
||||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left or right).toUByte())
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left or right).toUByte())
|
||||||
@ -1333,6 +1345,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsOR(i: Instruction) {
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1) or i.value!!.toUByte())
|
||||||
|
VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1) or i.value!!.toUShort())
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsORM(i: Instruction) {
|
private fun InsORM(i: Instruction) {
|
||||||
val address = i.value!!
|
val address = i.value!!
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
@ -1351,7 +1372,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsXOR(i: Instruction) {
|
private fun InsXORR(i: Instruction) {
|
||||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left xor right).toUByte())
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left xor right).toUByte())
|
||||||
@ -1361,6 +1382,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsXOR(i: Instruction) {
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1) xor i.value!!.toUByte())
|
||||||
|
VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1) xor i.value!!.toUShort())
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsXORM(i: Instruction) {
|
private fun InsXORM(i: Instruction) {
|
||||||
val address = i.value!!
|
val address = i.value!!
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
|
Loading…
Reference in New Issue
Block a user