mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
vm: implement split incr/decr
This commit is contained in:
parent
1bdae53f4e
commit
380f557c45
@ -1361,44 +1361,87 @@ class IRCodeGen(
|
||||
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunks {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val array = postIncrDecr.target.array
|
||||
val operationMem: Opcode
|
||||
val operationRegister: Opcode
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
operationMem = Opcode.INCM
|
||||
operationRegister = Opcode.INC
|
||||
}
|
||||
"--" -> {
|
||||
operationMem = Opcode.DECM
|
||||
operationRegister = Opcode.DEC
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
|
||||
if(array?.splitWords==true) {
|
||||
val variable = array.variable.name
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
val iterable = symbolTable.flat.getValue(array.variable.name) as StStaticVariable
|
||||
val arrayLength = iterable.length!!
|
||||
if(fixedIndex!=null) {
|
||||
TODO("split incr decr")
|
||||
// addInstr(result, IRInstruction(operationMem, irDt, immediate = arrayLength, labelSymbol="$variable+$fixedIndex"), null)
|
||||
val skipLabel = createLabelName()
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = "${variable}_lsb+$fixedIndex")
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.INCM, IRDataType.BYTE, labelSymbol = "${variable}_msb+$fixedIndex")
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null)
|
||||
}
|
||||
"--" -> {
|
||||
val valueReg=registers.nextFree()
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=valueReg, labelSymbol = "${variable}_lsb+$fixedIndex")
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = "${variable}_msb+$fixedIndex")
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null).also {
|
||||
it += IRInstruction(Opcode.DECM, IRDataType.BYTE, labelSymbol = "${variable}_lsb+$fixedIndex")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
} else {
|
||||
val arrayLength = iterable.length!!
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
val incReg = registers.nextFree()
|
||||
TODO("load split")
|
||||
// chunk += IRInstruction(Opcode.LOADXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
|
||||
// chunk += IRInstruction(operationRegister, irDt, reg1=incReg)
|
||||
TODO("store split")
|
||||
// chunk += IRInstruction(Opcode.STOREXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
|
||||
result += chunk
|
||||
val skipLabel = createLabelName()
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
|
||||
it += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null)
|
||||
}
|
||||
"--" -> {
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.BSTNE, labelSymbol = skipLabel)
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
|
||||
it += IRInstruction(Opcode.DEC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
|
||||
}
|
||||
result += IRCodeChunk(skipLabel, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.DEC, IRDataType.BYTE, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val ident = postIncrDecr.target.identifier
|
||||
val memory = postIncrDecr.target.memory
|
||||
val irDt = irType(postIncrDecr.target.type)
|
||||
val operationMem: Opcode
|
||||
val operationRegister: Opcode
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
operationMem = Opcode.INCM
|
||||
operationRegister = Opcode.INC
|
||||
}
|
||||
"--" -> {
|
||||
operationMem = Opcode.DECM
|
||||
operationRegister = Opcode.DEC
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
if(ident!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null)
|
||||
} else if(memory!=null) {
|
||||
|
@ -14,7 +14,7 @@ Then you can choose a few ways to get a compiler:
|
||||
**Download a precompiled version from github:**
|
||||
|
||||
#. download a recent "fat-jar" (called something like "prog8compiler-all.jar") from `the releases on Github <https://github.com/irmen/prog8/releases>`_
|
||||
#. run the compiler with "java -jar prog8compiler-all.jar" to see how you can use it.
|
||||
#. run the compiler with "java -jar prog8compiler.jar" to see how you can use it (use the correct name and version of the jar file you've downloaded).
|
||||
|
||||
**Using the Gradle build system to build it yourself:**
|
||||
|
||||
@ -86,11 +86,12 @@ The compiler will link everything together into one output program at the end.
|
||||
If you start the compiler without arguments, it will print a short usage text.
|
||||
For normal use the compiler can be invoked with the command:
|
||||
|
||||
``$ java -jar prog8compiler-8.14-all.jar sourcefile.p8``
|
||||
``$ java -jar prog8compiler.jar -target cx16 sourcefile.p8``
|
||||
|
||||
(Use the appropriate name and version of the jar file downloaded from one of the Git releases.
|
||||
Other ways to invoke the compiler are also available: see the introduction page about how
|
||||
to build and run the compiler yourself)
|
||||
to build and run the compiler yourself. The -target option is required, in this case we
|
||||
tell it to compile a program for the Commander X16)
|
||||
|
||||
|
||||
By default, assembly code is generated and written to ``sourcefile.asm``.
|
||||
|
@ -1,8 +1,6 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- vm: fix the last replacement code for the now removed LOADSPLIT/STORESPLIT opcodes.
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
@ -15,12 +15,12 @@ main {
|
||||
; }
|
||||
; txt.nl()
|
||||
ubyte idx=1
|
||||
names[idx] = 2000
|
||||
txt.print_uw(names[1])
|
||||
names[idx] = $20ff
|
||||
txt.print_uwhex(names[1], true)
|
||||
names[idx]++
|
||||
txt.print_uw(names[1])
|
||||
txt.print_uwhex(names[1], true)
|
||||
names[idx]--
|
||||
txt.print_uw(names[1])
|
||||
txt.print_uwhex(names[1], true)
|
||||
|
||||
names = [1111,2222,3333]
|
||||
for ww in names {
|
||||
|
@ -15,7 +15,9 @@ Program to execute is not stored in the system memory, it's just a separate list
|
||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||
Value stack, max 128 entries of 1 byte each.
|
||||
Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by the CMP instruction or explicit CLC/SEC!!!
|
||||
logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
||||
LOAD instructions DO affect the Z and N flags
|
||||
INC/DEC instructions DO affect the Z and N flags
|
||||
other instructions such as logical or arithmetic operations DO NOT AFFECT THE STATUS FLAGS UNLESS EXPLICITLY NOTED!
|
||||
|
||||
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
|
||||
|
||||
|
@ -375,8 +375,11 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
if(i.type==IRDataType.FLOAT)
|
||||
registers.setFloat(i.fpReg1!!, i.immediateFp!!)
|
||||
else {
|
||||
if(i.immediate!=null)
|
||||
if(i.immediate!=null) {
|
||||
setResultReg(i.reg1!!, i.immediate!!, i.type!!)
|
||||
statusZero = i.immediate==0
|
||||
statusNegative = i.immediate!! <0
|
||||
}
|
||||
else {
|
||||
if(i.labelSymbol==null)
|
||||
throw IllegalArgumentException("expected LOAD of address of labelsymbol")
|
||||
@ -388,8 +391,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsLOADM(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.address!!))
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.address!!))
|
||||
IRDataType.BYTE -> {
|
||||
val value = memory.getUB(i.address!!)
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = memory.getUW(i.address!!)
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!!))
|
||||
}
|
||||
nextPc()
|
||||
@ -397,8 +410,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsLOADI(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(registers.getUW(i.reg2!!).toInt()))
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(registers.getUW(i.reg2!!).toInt()))
|
||||
IRDataType.BYTE -> {
|
||||
val value = memory.getUB(registers.getUW(i.reg2!!).toInt())
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = memory.getUW(registers.getUW(i.reg2!!).toInt())
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt()))
|
||||
}
|
||||
nextPc()
|
||||
@ -406,8 +429,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsLOADX(i: IRInstruction) {
|
||||
when (i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.address!! + registers.getUW(i.reg2!!).toInt()))
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.address!! + registers.getUW(i.reg2!!).toInt()))
|
||||
IRDataType.BYTE -> {
|
||||
val value = memory.getUB(i.address!! + registers.getUW(i.reg2!!).toInt())
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = memory.getUW(i.address!! + registers.getUW(i.reg2!!).toInt())
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!! + registers.getUW(i.reg1!!).toInt()))
|
||||
}
|
||||
nextPc()
|
||||
@ -417,11 +450,17 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
when (i.type!!) {
|
||||
IRDataType.BYTE -> {
|
||||
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
|
||||
registers.setUB(i.reg1!!, memory.getUB(pointer.toInt()))
|
||||
val value = memory.getUB(pointer.toInt())
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
|
||||
registers.setUW(i.reg1!!, memory.getUW(pointer.toInt()))
|
||||
val value = memory.getUW(pointer.toInt())
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> {
|
||||
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg1!!)
|
||||
@ -433,8 +472,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsLOADR(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg2!!))
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg2!!))
|
||||
IRDataType.BYTE -> {
|
||||
val value = registers.getUB(i.reg2!!)
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = registers.getUW(i.reg2!!)
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg2!!))
|
||||
}
|
||||
nextPc()
|
||||
@ -842,8 +891,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsINC(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1!!)+1u).toUByte())
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, (registers.getUW(i.reg1!!)+1u).toUShort())
|
||||
IRDataType.BYTE -> {
|
||||
val value = (registers.getUB(i.reg1!!)+1u).toUByte()
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = (registers.getUW(i.reg1!!)+1u).toUShort()
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value==0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg1!!)+1f)
|
||||
}
|
||||
nextPc()
|
||||
@ -852,8 +911,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
private fun InsINCM(i: IRInstruction) {
|
||||
val address = i.address!!
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> memory.setUB(address, (memory.getUB(address)+1u).toUByte())
|
||||
IRDataType.WORD -> memory.setUW(address, (memory.getUW(address)+1u).toUShort())
|
||||
IRDataType.BYTE -> {
|
||||
val value = (memory.getUB(address)+1u).toUByte()
|
||||
memory.setUB(address, value)
|
||||
statusZero = value==0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = (memory.getUW(address)+1u).toUShort()
|
||||
memory.setUW(address, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> memory.setFloat(address, memory.getFloat(address)+1f)
|
||||
}
|
||||
nextPc()
|
||||
@ -861,8 +930,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsDEC(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1!!)-1u).toUByte())
|
||||
IRDataType.WORD -> registers.setUW(i.reg1!!, (registers.getUW(i.reg1!!)-1u).toUShort())
|
||||
IRDataType.BYTE -> {
|
||||
val value = (registers.getUB(i.reg1!!)-1u).toUByte()
|
||||
registers.setUB(i.reg1!!, value)
|
||||
statusZero = value== 0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = (registers.getUW(i.reg1!!)-1u).toUShort()
|
||||
registers.setUW(i.reg1!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg1!!)-1f)
|
||||
}
|
||||
nextPc()
|
||||
@ -870,8 +949,18 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
|
||||
private fun InsDECM(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> memory.setUB(i.address!!, (memory.getUB(i.address!!)-1u).toUByte())
|
||||
IRDataType.WORD -> memory.setUW(i.address!!, (memory.getUW(i.address!!)-1u).toUShort())
|
||||
IRDataType.BYTE -> {
|
||||
val value = (memory.getUB(i.address!!)-1u).toUByte()
|
||||
memory.setUB(i.address!!, value)
|
||||
statusZero = value== 0.toUByte()
|
||||
statusNegative = value>=0x80u
|
||||
}
|
||||
IRDataType.WORD -> {
|
||||
val value = (memory.getUW(i.address!!)-1u).toUShort()
|
||||
memory.setUW(i.address!!, value)
|
||||
statusZero = value== 0.toUShort()
|
||||
statusNegative = value>=0x8000u
|
||||
}
|
||||
IRDataType.FLOAT -> memory.setFloat(i.address!!, memory.getFloat(i.address!!)-1f)
|
||||
}
|
||||
nextPc()
|
||||
|
Loading…
x
Reference in New Issue
Block a user