mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 16:29:21 +00:00
vm: loadix instruction added for indirect addressing via pointer
This commit is contained in:
parent
2002412026
commit
3c8c44155d
@ -78,6 +78,8 @@ internal class AssignmentAsmGen(private val program: Program,
|
||||
// indexing a pointer var instead of a real array or string
|
||||
if(elementDt !in ByteDatatypes)
|
||||
throw AssemblyError("non-array var indexing requires bytes dt")
|
||||
if(value.inferType(program) isnot DataType.UBYTE)
|
||||
throw AssemblyError("non-array var indexing requires bytes index")
|
||||
asmgen.loadScaledArrayIndexIntoRegister(value, elementDt, CpuRegister.Y)
|
||||
if(asmgen.isZpVar(value.arrayvar)) {
|
||||
asmgen.out(" lda ($arrayVarName),y")
|
||||
|
@ -82,34 +82,34 @@ internal class VmCodeInstruction(
|
||||
value: Int?=null, // 0-$ffff
|
||||
fpValue: Float?=null,
|
||||
labelSymbol: List<String>?=null // alternative to value for branch/call/jump labels
|
||||
): VmCodeLine() {
|
||||
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, labelSymbol)
|
||||
): VmCodeLine() {
|
||||
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, labelSymbol)
|
||||
|
||||
init {
|
||||
if(reg1!=null && (reg1<0 || reg1>65536))
|
||||
throw IllegalArgumentException("reg1 out of bounds")
|
||||
if(reg2!=null && (reg2<0 || reg2>65536))
|
||||
throw IllegalArgumentException("reg2 out of bounds")
|
||||
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
|
||||
throw IllegalArgumentException("fpReg1 out of bounds")
|
||||
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
|
||||
throw IllegalArgumentException("fpReg2 out of bounds")
|
||||
init {
|
||||
if(reg1!=null && (reg1<0 || reg1>65536))
|
||||
throw IllegalArgumentException("reg1 out of bounds")
|
||||
if(reg2!=null && (reg2<0 || reg2>65536))
|
||||
throw IllegalArgumentException("reg2 out of bounds")
|
||||
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
|
||||
throw IllegalArgumentException("fpReg1 out of bounds")
|
||||
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
|
||||
throw IllegalArgumentException("fpReg2 out of bounds")
|
||||
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
throw IllegalArgumentException("value out of range for byte: $value")
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
if (value < -32768 || value > 65535)
|
||||
throw IllegalArgumentException("value out of range for word: $value")
|
||||
}
|
||||
VmDataType.FLOAT, null -> {}
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
throw IllegalArgumentException("value out of range for byte: $value")
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
if (value < -32768 || value > 65535)
|
||||
throw IllegalArgumentException("value out of range for word: $value")
|
||||
}
|
||||
VmDataType.FLOAT, null -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
|
||||
internal class VmCodeComment(val comment: String): VmCodeLine()
|
||||
|
@ -154,12 +154,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
// indexing a pointer var instead of a real array or string
|
||||
if(eltSize!=1)
|
||||
throw AssemblyError("non-array var indexing requires bytes dt")
|
||||
val pointerReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||
// TODO introduce LOADIX instruction to skip the ADD (requires 3 registers)
|
||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1=pointerReg, value=arrayLocation)
|
||||
code += VmCodeInstruction(Opcode.ADD, VmDataType.WORD, reg1=pointerReg, reg2=idxReg)
|
||||
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultRegister, reg2=pointerReg)
|
||||
code += VmCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
||||
return code
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,8 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- optimize pointervar indexing codegen: reading (expressions) via optimized codegen instead of @(pointer+idx)
|
||||
- optimize pointervar indexing codegen: writing (all sorts of things)
|
||||
- why is this code so much larger:
|
||||
- fix pointervar indexing 6502 codegen (AssignmentAsmGen translateNormalAssignment) -> gridcommander worm doesn't move
|
||||
- is this code still so much larger:
|
||||
uword xx
|
||||
for xx in 0 to size-1 {
|
||||
gfx2.next_pixel(bitmapbuf[xx])
|
||||
@ -16,8 +15,8 @@ For next release
|
||||
gfx2.next_pixel(@(srcptr))
|
||||
srcptr++
|
||||
}
|
||||
any difference between 6502 codegen and vm codegen?
|
||||
|
||||
- optimize pointervar indexing codegen: writing (all sorts of things)
|
||||
- pipe operator: (targets other than 'Virtual'): allow non-unary function calls in the pipe that specify the other argument(s) in the calls. Already working for VM target.
|
||||
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?
|
||||
- Inliner: also inline function call expressions, and remove it from the StatementOptimizer
|
||||
|
@ -24,8 +24,9 @@ All have type b or w or f.
|
||||
load reg1, value - load immediate value into register
|
||||
loadm reg1, address - load reg1 with value at memory address
|
||||
loadi reg1, reg2 - load reg1 with value at memory indirect, memory pointed to by reg2
|
||||
loadx reg1, reg2, address - load reg1 with value at memory address, indexed by value in reg2
|
||||
loadr reg1, reg2 - load reg1 with value at register reg2
|
||||
loadx reg1, reg2, address - load reg1 with value at memory address indexed by value in reg2
|
||||
loadix reg1, reg2, pointeraddr - load reg1 with value at memory indirect, pointed to by pointeraddr indexed by value in reg2
|
||||
loadr reg1, reg2 - load reg1 with value in register reg2
|
||||
|
||||
storem reg1, address - store reg1 at memory address
|
||||
storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2
|
||||
@ -184,6 +185,7 @@ enum class Opcode {
|
||||
LOADM,
|
||||
LOADI,
|
||||
LOADX,
|
||||
LOADIX,
|
||||
LOADR,
|
||||
STOREM,
|
||||
STOREI,
|
||||
@ -313,6 +315,7 @@ enum class Opcode {
|
||||
val OpcodesWithAddress = setOf(
|
||||
Opcode.LOADM,
|
||||
Opcode.LOADX,
|
||||
Opcode.LOADIX,
|
||||
Opcode.STOREM,
|
||||
Opcode.STOREX,
|
||||
Opcode.STOREZM,
|
||||
@ -481,6 +484,7 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.LOADM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.LOADI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
|
||||
Opcode.LOADX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||
Opcode.LOADIX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||
Opcode.LOADR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.STOREM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.STOREI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
|
||||
|
@ -91,6 +91,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.LOADM -> InsLOADM(ins)
|
||||
Opcode.LOADX -> InsLOADX(ins)
|
||||
Opcode.LOADI -> InsLOADI(ins)
|
||||
Opcode.LOADIX -> InsLOADIX(ins)
|
||||
Opcode.LOADR -> InsLOADR(ins)
|
||||
Opcode.STOREM -> InsSTOREM(ins)
|
||||
Opcode.STOREX -> InsSTOREX(ins)
|
||||
@ -308,6 +309,24 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsLOADIX(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val pointer = memory.getUW(i.value!!) + registers.getUB(i.reg2!!)
|
||||
registers.setUB(i.reg1!!, memory.getUB(pointer.toInt()))
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
val pointer = memory.getUW(i.value!!) + registers.getUB(i.reg2!!)
|
||||
registers.setUW(i.reg1!!, memory.getUW(pointer.toInt()))
|
||||
}
|
||||
VmDataType.FLOAT -> {
|
||||
val pointer = memory.getUW(i.value!!) + registers.getUB(i.reg1!!)
|
||||
registers.setFloat(i.fpReg1!!, memory.getFloat(pointer.toInt()))
|
||||
}
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsLOADR(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg2!!))
|
||||
|
Loading…
Reference in New Issue
Block a user