mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
vm: add in-place bitwise or,and,xor
This commit is contained in:
parent
c9e8c7a290
commit
26ea1da146
@ -87,9 +87,9 @@ internal class AssignmentGen(private val codeGen: CodeGen, private val expressio
|
|||||||
"-" -> return expressionEval.operatorMinusInplace(address, vmDt, operand)
|
"-" -> return expressionEval.operatorMinusInplace(address, vmDt, operand)
|
||||||
"*" -> return expressionEval.operatorMultiplyInplace(address, vmDt, operand)
|
"*" -> return expressionEval.operatorMultiplyInplace(address, vmDt, operand)
|
||||||
"/" -> return expressionEval.operatorDivideInplace(address, vmDt, signed, operand)
|
"/" -> return expressionEval.operatorDivideInplace(address, vmDt, signed, operand)
|
||||||
"|" -> { /* TODO */ }
|
"|" -> return expressionEval.operatorOrInplace(address, vmDt, operand)
|
||||||
"&" -> { /* TODO */ }
|
"&" -> return expressionEval.operatorAndInplace(address, vmDt, operand)
|
||||||
"^" -> { /* TODO */ }
|
"^" -> return expressionEval.operatorXorInplace(address, vmDt, operand)
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
return fallbackAssign(origAssign)
|
return fallbackAssign(origAssign)
|
||||||
|
@ -477,6 +477,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun operatorXorInplace(address: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk {
|
||||||
|
val code = VmCodeChunk()
|
||||||
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += translateExpression(operand, operandReg, -1)
|
||||||
|
code += VmCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = address)
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
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()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
@ -486,6 +494,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun operatorAndInplace(address: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk {
|
||||||
|
val code = VmCodeChunk()
|
||||||
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += translateExpression(operand, operandReg, -1)
|
||||||
|
code += VmCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=address)
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
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()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
@ -495,6 +511,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun operatorOrInplace(address: Int, vmDt: VmDataType, operand: PtExpression): VmCodeChunk {
|
||||||
|
val code = VmCodeChunk()
|
||||||
|
val operandReg = codeGen.vmRegisters.nextFree()
|
||||||
|
code += translateExpression(operand, operandReg, -1)
|
||||||
|
code += VmCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = address)
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
private fun operatorModulo(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||||
if(vmDt==VmDataType.FLOAT)
|
if(vmDt==VmDataType.FLOAT)
|
||||||
throw IllegalArgumentException("floating-point modulo not supported")
|
throw IllegalArgumentException("floating-point modulo not supported")
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- vm: implement the missing in-place operators in inplaceBinexpr()
|
|
||||||
- complete the Inliner
|
- complete the Inliner
|
||||||
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
||||||
|
|
||||||
@ -27,6 +26,7 @@ Compiler:
|
|||||||
- vm: don't store symbol names in instructions to make optimizing the IR easier? but what about jumps to labels. And it's no longer readable by humans.
|
- vm: don't store symbol names in instructions to make optimizing the IR easier? but what about jumps to labels. And it's no longer readable by humans.
|
||||||
- vm: how to remove all unused subroutines? (in the assembly codegen, we let 64tass solve this for us)
|
- vm: how to remove all unused subroutines? (in the assembly codegen, we let 64tass solve this for us)
|
||||||
- vm: rather than being able to jump to any 'address' (IPTR), use 'blocks' that have entry and exit points -> even better dead code elimination possible too
|
- vm: rather than being able to jump to any 'address' (IPTR), use 'blocks' that have entry and exit points -> even better dead code elimination possible too
|
||||||
|
- vm: add more assignments to translateInplaceAssign()
|
||||||
- when the vm is stable and *if* its language can get promoted to prog8 IL, the variable allocation should be changed.
|
- when the vm is stable and *if* its language can get promoted to prog8 IL, the variable allocation should be changed.
|
||||||
It's now done before the vm code generation, but the IL should probably not depend on the allocations already performed.
|
It's now done before the vm code generation, but the IL should probably not depend on the allocations already performed.
|
||||||
So the CodeGen doesn't do VariableAlloc *before* the codegen, but as a last step.
|
So the CodeGen doesn't do VariableAlloc *before* the codegen, but as a last step.
|
||||||
|
@ -1,51 +1,14 @@
|
|||||||
%import textio
|
|
||||||
%import math
|
|
||||||
%zeropage dontuse
|
%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 @shared xx = 11
|
ubyte @shared xx = 11
|
||||||
byte @shared yy = 62
|
uword addr = $5000
|
||||||
byte @shared yy2 = 15
|
@(addr) = @(addr) + xx
|
||||||
byte @shared yy3 = 127
|
xx = xx ^ 44
|
||||||
ubyte @shared ubx = 3
|
xx = xx | 44
|
||||||
|
xx = xx & 44
|
||||||
xx = xx + 9
|
|
||||||
txt.print_b(xx) ; 20
|
|
||||||
txt.nl()
|
|
||||||
xx = xx * 8
|
|
||||||
txt.print_b(xx) ; -96
|
|
||||||
txt.nl()
|
|
||||||
xx = xx - 7
|
|
||||||
txt.print_b(xx) ; -103
|
|
||||||
txt.nl()
|
|
||||||
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
|
|
||||||
; 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ Virtual machine:
|
|||||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||||
Value stack, max 128 entries of 1 byte each.
|
Value stack, max 128 entries of 1 byte each.
|
||||||
Status registers: Carry, Zero, Negative.
|
Status registers: Carry, Zero, Negative.
|
||||||
|
Program to execute is not stored in this memory, it's just a separate list of instructions.
|
||||||
|
|
||||||
Most instructions have an associated data type 'b','w','f'. (omitting it means 'b'/byte).
|
Most instructions have an associated data type 'b','w','f'. (omitting it means 'b'/byte).
|
||||||
Currently NO support for 24 or 32 bits integers.
|
Currently NO support for 24 or 32 bits integers.
|
||||||
@ -119,7 +120,9 @@ LOGICAL/BITWISE
|
|||||||
All have type b or w.
|
All have type b or w.
|
||||||
|
|
||||||
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||||
|
andm reg1 address - memory = memory bitwise and reg1
|
||||||
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||||
|
orm reg1, address - memory = memory bitwise or reg1
|
||||||
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||||
xorm reg1, address - memory = memory bitwise xor reg1
|
xorm reg1, address - memory = memory bitwise xor reg1
|
||||||
not reg1 - reg1 = boolean not of reg1 (0->1 , ~0 -> 0)
|
not reg1 - reg1 = boolean not of reg1 (0->1 , ~0 -> 0)
|
||||||
@ -240,7 +243,9 @@ enum class Opcode {
|
|||||||
EXTS,
|
EXTS,
|
||||||
|
|
||||||
AND,
|
AND,
|
||||||
|
ANDM,
|
||||||
OR,
|
OR,
|
||||||
|
ORM,
|
||||||
XOR,
|
XOR,
|
||||||
XORM,
|
XORM,
|
||||||
NOT,
|
NOT,
|
||||||
@ -303,7 +308,9 @@ val OpcodesWithAddress = setOf(
|
|||||||
Opcode.DIVM,
|
Opcode.DIVM,
|
||||||
Opcode.DIVSM,
|
Opcode.DIVSM,
|
||||||
Opcode.NOTM,
|
Opcode.NOTM,
|
||||||
Opcode.XORM
|
Opcode.ORM,
|
||||||
|
Opcode.XORM,
|
||||||
|
Opcode.ANDM
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -509,7 +516,9 @@ val instructionFormats = mutableMapOf(
|
|||||||
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.AND to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.ANDM to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.OR to InstructionFormat.from("BW,r1,r2"),
|
Opcode.OR to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.ORM to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
|
Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
|
||||||
Opcode.XORM to InstructionFormat.from("BW,r1,v"),
|
Opcode.XORM to InstructionFormat.from("BW,r1,v"),
|
||||||
Opcode.NOT to InstructionFormat.from("BW,r1"),
|
Opcode.NOT to InstructionFormat.from("BW,r1"),
|
||||||
|
@ -155,7 +155,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.EXT -> InsEXT(ins)
|
Opcode.EXT -> InsEXT(ins)
|
||||||
Opcode.EXTS -> InsEXTS(ins)
|
Opcode.EXTS -> InsEXTS(ins)
|
||||||
Opcode.AND -> InsAND(ins)
|
Opcode.AND -> InsAND(ins)
|
||||||
|
Opcode.ANDM -> InsANDM(ins)
|
||||||
Opcode.OR -> InsOR(ins)
|
Opcode.OR -> InsOR(ins)
|
||||||
|
Opcode.ORM -> InsORM(ins)
|
||||||
Opcode.XOR -> InsXOR(ins)
|
Opcode.XOR -> InsXOR(ins)
|
||||||
Opcode.XORM ->InsXORM(ins)
|
Opcode.XORM ->InsXORM(ins)
|
||||||
Opcode.NOT -> InsNOT(ins)
|
Opcode.NOT -> InsNOT(ins)
|
||||||
@ -977,7 +979,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
"*" -> memvalue * operand
|
"*" -> memvalue * operand
|
||||||
else -> throw IllegalArgumentException("operator word $operator")
|
else -> throw IllegalArgumentException("operator word $operator")
|
||||||
}
|
}
|
||||||
registers.setUW(reg1, result.toUShort())
|
memory.setUW(address, result.toUShort())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun divModWordUnsigned(operator: String, reg1: Int, reg2: Int) {
|
private fun divModWordUnsigned(operator: String, reg1: Int, reg2: Int) {
|
||||||
@ -1091,6 +1093,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsANDM(i: Instruction) {
|
||||||
|
val address = i.value!!
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> memory.setUB(address, (memory.getUB(address) and registers.getUB(i.reg1!!)))
|
||||||
|
VmDataType.WORD -> memory.setUW(address, (memory.getUW(address) and registers.getUW(i.reg1!!)))
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsOR(i: Instruction) {
|
private fun InsOR(i: Instruction) {
|
||||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
@ -1101,6 +1113,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsORM(i: Instruction) {
|
||||||
|
val address = i.value!!
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> memory.setUB(address, (memory.getUB(address) or registers.getUB(i.reg1!!)))
|
||||||
|
VmDataType.WORD -> memory.setUW(address, (memory.getUW(address) or registers.getUW(i.reg1!!)))
|
||||||
|
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsXOR(i: Instruction) {
|
private fun InsXOR(i: Instruction) {
|
||||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
|
Loading…
Reference in New Issue
Block a user