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.operatorMultiplyInplace(address, vmDt, operand)
|
||||
"/" -> return expressionEval.operatorDivideInplace(address, vmDt, signed, operand)
|
||||
"|" -> { /* TODO */ }
|
||||
"&" -> { /* TODO */ }
|
||||
"^" -> { /* TODO */ }
|
||||
"|" -> return expressionEval.operatorOrInplace(address, vmDt, operand)
|
||||
"&" -> return expressionEval.operatorAndInplace(address, vmDt, operand)
|
||||
"^" -> return expressionEval.operatorXorInplace(address, vmDt, operand)
|
||||
else -> {}
|
||||
}
|
||||
return fallbackAssign(origAssign)
|
||||
|
@ -477,6 +477,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
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 {
|
||||
val code = VmCodeChunk()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
@ -486,6 +494,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
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 {
|
||||
val code = VmCodeChunk()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
@ -495,6 +511,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
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 {
|
||||
if(vmDt==VmDataType.FLOAT)
|
||||
throw IllegalArgumentException("floating-point modulo not supported")
|
||||
|
@ -3,7 +3,6 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: implement the missing in-place operators in inplaceBinexpr()
|
||||
- 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?
|
||||
|
||||
@ -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: 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: 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.
|
||||
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.
|
||||
|
@ -1,51 +1,14 @@
|
||||
%import textio
|
||||
%import math
|
||||
%zeropage dontuse
|
||||
|
||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
byte @shared xx = 11
|
||||
byte @shared yy = 62
|
||||
byte @shared yy2 = 15
|
||||
byte @shared yy3 = 127
|
||||
ubyte @shared ubx = 3
|
||||
|
||||
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
|
||||
ubyte @shared xx = 11
|
||||
uword addr = $5000
|
||||
@(addr) = @(addr) + xx
|
||||
xx = xx ^ 44
|
||||
xx = xx | 44
|
||||
xx = xx & 44
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ Virtual machine:
|
||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||
Value stack, max 128 entries of 1 byte each.
|
||||
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).
|
||||
Currently NO support for 24 or 32 bits integers.
|
||||
@ -119,7 +120,9 @@ LOGICAL/BITWISE
|
||||
All have type b or w.
|
||||
|
||||
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||
andm reg1 address - memory = memory bitwise and reg1
|
||||
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||
orm reg1, address - memory = memory bitwise or reg1
|
||||
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||
xorm reg1, address - memory = memory bitwise xor reg1
|
||||
not reg1 - reg1 = boolean not of reg1 (0->1 , ~0 -> 0)
|
||||
@ -240,7 +243,9 @@ enum class Opcode {
|
||||
EXTS,
|
||||
|
||||
AND,
|
||||
ANDM,
|
||||
OR,
|
||||
ORM,
|
||||
XOR,
|
||||
XORM,
|
||||
NOT,
|
||||
@ -303,7 +308,9 @@ val OpcodesWithAddress = setOf(
|
||||
Opcode.DIVM,
|
||||
Opcode.DIVSM,
|
||||
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.EXTS to InstructionFormat.from("BW,r1"),
|
||||
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.ORM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.XORM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.NOT to InstructionFormat.from("BW,r1"),
|
||||
|
@ -155,7 +155,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.EXT -> InsEXT(ins)
|
||||
Opcode.EXTS -> InsEXTS(ins)
|
||||
Opcode.AND -> InsAND(ins)
|
||||
Opcode.ANDM -> InsANDM(ins)
|
||||
Opcode.OR -> InsOR(ins)
|
||||
Opcode.ORM -> InsORM(ins)
|
||||
Opcode.XOR -> InsXOR(ins)
|
||||
Opcode.XORM ->InsXORM(ins)
|
||||
Opcode.NOT -> InsNOT(ins)
|
||||
@ -977,7 +979,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
"*" -> memvalue * operand
|
||||
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) {
|
||||
@ -1091,6 +1093,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
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) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
@ -1101,6 +1113,16 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
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) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
|
Loading…
Reference in New Issue
Block a user