mirror of
https://github.com/irmen/prog8.git
synced 2025-01-26 19:30:59 +00:00
vm: more optimal code for loops ending on 0
This commit is contained in:
parent
036d9dbe59
commit
2b7c09e6ee
@ -64,6 +64,22 @@ internal class VmCodeInstruction(
|
|||||||
symbol: List<String>?=null // alternative to value
|
symbol: List<String>?=null // alternative to value
|
||||||
): VmCodeLine() {
|
): VmCodeLine() {
|
||||||
val ins = Instruction(opcode, type, reg1, reg2, reg3, value, symbol)
|
val ins = Instruction(opcode, type, reg1, reg2, reg3, value, symbol)
|
||||||
|
|
||||||
|
init {
|
||||||
|
if(value!=null) {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
null -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
|
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
|
||||||
internal class VmCodeComment(val comment: String): VmCodeLine()
|
internal class VmCodeComment(val comment: String): VmCodeLine()
|
||||||
|
@ -231,36 +231,44 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): VmCodeChunk {
|
private fun translateForInConstantRange(forLoop: PtForLoop, loopvar: StStaticVariable): VmCodeChunk {
|
||||||
val iterable = forLoop.iterable as PtRange
|
|
||||||
val step = iterable.step.number.toInt()
|
|
||||||
val range = IntProgression.fromClosedRange(
|
|
||||||
(iterable.from as PtNumber).number.toInt(),
|
|
||||||
(iterable.to as PtNumber).number.toInt() + step,
|
|
||||||
step)
|
|
||||||
if (range.isEmpty() || range.step==0)
|
|
||||||
throw AssemblyError("empty range or step 0")
|
|
||||||
|
|
||||||
val loopLabel = createLabelName()
|
val loopLabel = createLabelName()
|
||||||
val loopvarAddress = allocations.get(loopvar.scopedName)
|
val loopvarAddress = allocations.get(loopvar.scopedName)
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
val endvalueReg = vmRegisters.nextFree()
|
|
||||||
val loopvarDt = vmType(loopvar.dt)
|
val loopvarDt = vmType(loopvar.dt)
|
||||||
|
val iterable = forLoop.iterable as PtRange
|
||||||
|
val step = iterable.step.number.toInt()
|
||||||
|
val rangeStart = (iterable.from as PtNumber).number.toInt()
|
||||||
|
val rangeEndUntyped = (iterable.to as PtNumber).number.toInt() + step
|
||||||
|
if(step==0)
|
||||||
|
throw AssemblyError("step 0")
|
||||||
|
if(step>0 && rangeEndUntyped<rangeStart || step<0 && rangeEndUntyped>rangeStart)
|
||||||
|
throw AssemblyError("empty range")
|
||||||
|
val rangeEndWrapped = if(loopvarDt==VmDataType.BYTE) rangeEndUntyped and 255 else rangeEndUntyped and 65535
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += VmCodeInstruction(Opcode.LOAD, loopvarDt, reg1=endvalueReg, value=range.last)
|
val endvalueReg: Int
|
||||||
code += VmCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=range.first)
|
if(rangeEndWrapped!=0) {
|
||||||
|
endvalueReg = vmRegisters.nextFree()
|
||||||
|
code += VmCodeInstruction(Opcode.LOAD, loopvarDt, reg1 = endvalueReg, value = rangeEndWrapped)
|
||||||
|
} else {
|
||||||
|
endvalueReg = 0
|
||||||
|
}
|
||||||
|
code += VmCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
||||||
code += VmCodeLabel(loopLabel)
|
code += VmCodeLabel(loopLabel)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
if(range.step<3) {
|
if(step<3) {
|
||||||
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), range.step)
|
code += addConstMem(loopvarDt, loopvarAddress.toUInt(), step)
|
||||||
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
||||||
} else {
|
} else {
|
||||||
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
code += VmCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
||||||
code += addConstReg(loopvarDt, indexReg, range.step)
|
code += addConstReg(loopvarDt, indexReg, step)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1 = indexReg, value = loopvarAddress)
|
||||||
}
|
}
|
||||||
// TODO more optimal loop instruction for loops ending on 0 (BNZ?)
|
code += if(rangeEndWrapped==0) {
|
||||||
code += VmCodeInstruction(Opcode.BNE, loopvarDt, reg1=indexReg, reg2=endvalueReg, symbol=loopLabel)
|
VmCodeInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, symbol = loopLabel)
|
||||||
|
} else {
|
||||||
|
VmCodeInstruction(Opcode.BNE, loopvarDt, reg1 = indexReg, reg2 = endvalueReg, symbol = loopLabel)
|
||||||
|
}
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
- vm: codegen: more optimal code for loops ending on 0 (BNZ?)
|
|
||||||
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
||||||
- writeAssembly(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
- writeAssembly(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||||
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
main {
|
main {
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
ubyte value1 = 99
|
ubyte counter
|
||||||
ubyte value2 = 222
|
|
||||||
|
|
||||||
uword @shared result = $ffff
|
repeat 256 {
|
||||||
result = value1 != value2
|
txt.print_ub(counter)
|
||||||
|
txt.spc()
|
||||||
txt.print_uwhex(result, true)
|
counter ++
|
||||||
|
}
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
; a "pixelshader":
|
; a "pixelshader":
|
||||||
|
@ -132,6 +132,19 @@ class Assembler {
|
|||||||
throw IllegalArgumentException("invalid reg3 for $line")
|
throw IllegalArgumentException("invalid reg3 for $line")
|
||||||
if(!format.value && value!=null)
|
if(!format.value && value!=null)
|
||||||
throw IllegalArgumentException("invalid value for $line")
|
throw IllegalArgumentException("invalid value for $line")
|
||||||
|
if(value!=null) {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
null -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
program.add(Instruction(opcode, type, reg1, reg2, reg3, value))
|
program.add(Instruction(opcode, type, reg1, reg2, reg3, value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user