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)
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
val andReg = codeGen.vmRegisters.nextFree()
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=andReg, value=0x80)
|
||||
code += VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=andReg, reg2=resultRegister)
|
||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=andReg, labelSymbol = notNegativeLabel)
|
||||
val compareReg = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=compareReg, reg2=resultRegister)
|
||||
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.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += VmCodeLabel(notNegativeLabel)
|
||||
}
|
||||
DataType.WORD -> {
|
||||
val andReg = codeGen.vmRegisters.nextFree()
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=andReg, value=0x8000)
|
||||
code += VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=andReg, reg2=resultRegister)
|
||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=andReg, labelSymbol = notNegativeLabel)
|
||||
val compareReg = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOADR, VmDataType.WORD, reg1=compareReg, reg2=resultRegister)
|
||||
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 += VmCodeLabel(notNegativeLabel)
|
||||
}
|
||||
|
@ -149,10 +149,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Opcode.NEG, vmDt, reg1=resultRegister)
|
||||
}
|
||||
"~" -> {
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
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, reg2=regMask)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, value=mask)
|
||||
}
|
||||
else -> throw AssemblyError("weird prefix operator")
|
||||
}
|
||||
@ -390,9 +388,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
if(!notEquals)
|
||||
code += VmCodeInstruction(Opcode.INV, vmDt, reg1=resultRegister)
|
||||
val maskReg = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=maskReg, value=1)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=maskReg)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
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 {
|
||||
val code = VmCodeChunk()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} 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
|
||||
}
|
||||
|
||||
@ -479,10 +480,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
|
||||
private fun operatorAnd(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} 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
|
||||
}
|
||||
|
||||
@ -496,10 +502,15 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
|
||||
private fun operatorOr(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=rightResultReg)
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} 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
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,8 @@ TODO
|
||||
|
||||
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 floats
|
||||
%zeropage basicsafe
|
||||
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
bool @shared zz
|
||||
ubyte xx
|
||||
ubyte yy
|
||||
|
||||
while xx<42 {
|
||||
xx = yy+99
|
||||
xx = yy*5
|
||||
}
|
||||
|
||||
txt.print_ub(xx)
|
||||
float fl
|
||||
fl = -3.14
|
||||
floats.print_f(abs(fl)) ; WHY IS THIS GETTING A BOOLEAN CAST???
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
@ -126,9 +126,12 @@ LOGICAL/BITWISE
|
||||
---------------
|
||||
All have type b or w.
|
||||
|
||||
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||
andr reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||
and reg1, value - reg1 = reg1 bitwise and value
|
||||
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)
|
||||
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
|
||||
@ -265,10 +268,13 @@ enum class Opcode {
|
||||
EXT,
|
||||
EXTS,
|
||||
|
||||
ANDR,
|
||||
AND,
|
||||
ANDM,
|
||||
ORR,
|
||||
OR,
|
||||
ORM,
|
||||
XORR,
|
||||
XOR,
|
||||
XORM,
|
||||
INV,
|
||||
@ -567,11 +573,14 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.EXT 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.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.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.INV to InstructionFormat.from("BW,r1"),
|
||||
Opcode.INVM to InstructionFormat.from("BW,v"),
|
||||
|
@ -163,10 +163,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.SQRT -> InsSQRT(ins)
|
||||
Opcode.EXT -> InsEXT(ins)
|
||||
Opcode.EXTS -> InsEXTS(ins)
|
||||
Opcode.ANDR -> InsANDR(ins)
|
||||
Opcode.AND -> InsAND(ins)
|
||||
Opcode.ANDM -> InsANDM(ins)
|
||||
Opcode.ORR -> InsORR(ins)
|
||||
Opcode.OR -> InsOR(ins)
|
||||
Opcode.ORM -> InsORM(ins)
|
||||
Opcode.XORR -> InsXORR(ins)
|
||||
Opcode.XOR -> InsXOR(ins)
|
||||
Opcode.XORM ->InsXORM(ins)
|
||||
Opcode.INV -> InsINV(ins)
|
||||
@ -1295,7 +1298,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsAND(i: Instruction) {
|
||||
private fun InsANDR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left and right).toUByte())
|
||||
@ -1305,6 +1308,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
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) {
|
||||
val address = i.value!!
|
||||
when(i.type!!) {
|
||||
@ -1323,7 +1335,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsOR(i: Instruction) {
|
||||
private fun InsORR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left or right).toUByte())
|
||||
@ -1333,6 +1345,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
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) {
|
||||
val address = i.value!!
|
||||
when(i.type!!) {
|
||||
@ -1351,7 +1372,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsXOR(i: Instruction) {
|
||||
private fun InsXORR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left xor right).toUByte())
|
||||
@ -1361,6 +1382,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
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) {
|
||||
val address = i.value!!
|
||||
when(i.type!!) {
|
||||
|
Loading…
Reference in New Issue
Block a user