mirror of
https://github.com/irmen/prog8.git
synced 2026-04-21 02:16:41 +00:00
fix IR long comparisons (used in for loops for instance)
This commit is contained in:
@@ -673,7 +673,12 @@ class IRCodeGen(
|
||||
if(iterable.step==0)
|
||||
throw AssemblyError("step 0")
|
||||
val rangeEndExclusiveUntyped = iterable.last + iterable.step
|
||||
val rangeEndExclusiveWrapped = if(loopvarDtIr==IRDataType.BYTE) rangeEndExclusiveUntyped and 255 else rangeEndExclusiveUntyped and 65535
|
||||
val rangeEndExclusiveWrapped =
|
||||
when (loopvarDtIr) {
|
||||
IRDataType.BYTE -> rangeEndExclusiveUntyped and 255
|
||||
IRDataType.WORD -> rangeEndExclusiveUntyped and 65535
|
||||
else -> rangeEndExclusiveUntyped and 0x7fffffff
|
||||
}
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
val indexReg = registers.next(loopvarDtIr)
|
||||
|
||||
@@ -186,19 +186,29 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("remove useless and/or/xor") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=42, immediate = 0),
|
||||
IRInstruction(Opcode.AND, IRDataType.WORD, reg1=42, immediate = 0),
|
||||
IRInstruction(Opcode.AND, IRDataType.LONG, reg1=42, immediate = 0),
|
||||
IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=42, immediate = 255),
|
||||
IRInstruction(Opcode.AND, IRDataType.WORD, reg1=42, immediate = 65535),
|
||||
IRInstruction(Opcode.AND, IRDataType.LONG, reg1=42, immediate = 2147483647),
|
||||
IRInstruction(Opcode.AND, IRDataType.LONG, reg1=42, immediate = -1),
|
||||
IRInstruction(Opcode.OR, IRDataType.BYTE, reg1=42, immediate = 0),
|
||||
IRInstruction(Opcode.OR, IRDataType.BYTE, reg1=42, immediate = 255),
|
||||
IRInstruction(Opcode.OR, IRDataType.WORD, reg1=42, immediate = 65535),
|
||||
IRInstruction(Opcode.OR, IRDataType.LONG, reg1=42, immediate = 2147483647),
|
||||
IRInstruction(Opcode.OR, IRDataType.LONG, reg1=42, immediate = -1),
|
||||
IRInstruction(Opcode.XOR, IRDataType.BYTE, reg1=42, immediate = 0),
|
||||
IRInstruction(Opcode.AND, IRDataType.BYTE, reg1=42, immediate = 200),
|
||||
IRInstruction(Opcode.AND, IRDataType.WORD, reg1=42, immediate = 60000),
|
||||
IRInstruction(Opcode.OR, IRDataType.BYTE, reg1=42, immediate = 1),
|
||||
IRInstruction(Opcode.XOR, IRDataType.BYTE, reg1=42, immediate = 1)
|
||||
))
|
||||
irProg.chunks().single().instructions.size shouldBe 8
|
||||
irProg.chunks().single().instructions.size shouldBe 17
|
||||
val opt = IRPeepholeOptimizer(irProg, false)
|
||||
opt.optimize(true, ErrorReporterForTests())
|
||||
irProg.chunks().single().instructions.size shouldBe 4
|
||||
irProg.chunks().single().instructions.size shouldBe 12
|
||||
irProg.chunks().single().instructions.count { it.opcode == Opcode.LOAD } shouldBe 6
|
||||
}
|
||||
|
||||
test("replace and/or/xor by constant number") {
|
||||
|
||||
@@ -466,8 +466,10 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
rightVal?.number==0.0 -> expr.left
|
||||
rightIDt.isBytes && rightVal?.number==255.0 -> NumericLiteral(BaseDataType.UBYTE, 255.0, rightVal.position)
|
||||
rightIDt.isWords && rightVal?.number==65535.0 -> NumericLiteral(BaseDataType.UWORD, 65535.0, rightVal.position)
|
||||
rightIDt.isLong && rightVal?.number==-1.0 -> NumericLiteral(BaseDataType.LONG, -1.0, rightVal.position)
|
||||
leftIDt.isBytes && leftVal?.number==255.0 -> NumericLiteral(BaseDataType.UBYTE, 255.0, leftVal.position)
|
||||
leftIDt.isWords && leftVal?.number==65535.0 -> NumericLiteral(BaseDataType.UWORD, 65535.0, leftVal.position)
|
||||
leftIDt.isLong && leftVal?.number==-1.0 -> NumericLiteral(BaseDataType.LONG, -1.0, leftVal.position)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -477,8 +479,10 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
rightVal?.number==0.0 -> expr.left
|
||||
rightIDt.isBytes && rightVal?.number==255.0 -> PrefixExpression("~", expr.left, expr.left.position)
|
||||
rightIDt.isWords && rightVal?.number==65535.0 -> PrefixExpression("~", expr.left, expr.left.position)
|
||||
rightIDt.isLong && rightVal?.number==-1.0 -> PrefixExpression("~", expr.left, expr.left.position)
|
||||
leftIDt.isBytes && leftVal?.number==255.0 -> PrefixExpression("~", expr.right, expr.right.position)
|
||||
leftIDt.isWords && leftVal?.number==65535.0 -> PrefixExpression("~", expr.right, expr.right.position)
|
||||
leftIDt.isLong && leftVal?.number==-1.0 -> PrefixExpression("~", expr.right, expr.right.position)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -488,8 +492,10 @@ class ExpressionSimplifier(private val program: Program, private val errors: IEr
|
||||
rightVal?.number==0.0 -> constFalse
|
||||
rightIDt.isBytes && rightVal?.number==255.0 -> expr.left
|
||||
rightIDt.isWords && rightVal?.number==65535.0 -> expr.left
|
||||
rightIDt.isLong && rightVal?.number==-1.0 -> expr.left
|
||||
leftIDt.isBytes && leftVal?.number==255.0 -> expr.right
|
||||
leftIDt.isWords && leftVal?.number==65535.0 -> expr.right
|
||||
leftIDt.isLong && leftVal?.number==-1.0 -> expr.right
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +187,11 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
||||
when(expr.operator) {
|
||||
">" -> {
|
||||
// X>N -> X>=N+1, easier to do in 6502
|
||||
val maximum = if(rightNum.type.isByte) 255 else 65535
|
||||
val maximum = when {
|
||||
rightNum.type.isByte -> 255
|
||||
rightNum.type.isWord -> 65535
|
||||
else -> 0x7fffffff
|
||||
}
|
||||
if(rightNum.number<maximum) {
|
||||
val numPlusOne = rightNum.number.toInt()+1
|
||||
val newExpr = BinaryExpression(expr.left, ">=", NumericLiteral(rightNum.type, numPlusOne.toDouble(), rightNum.position), expr.position)
|
||||
@@ -196,7 +200,11 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co
|
||||
}
|
||||
"<=" -> {
|
||||
// X<=N -> X<N+1, easier to do in 6502
|
||||
val maximum = if(rightNum.type.isByte) 255 else 65535
|
||||
val maximum = when {
|
||||
rightNum.type.isByte -> 255
|
||||
rightNum.type.isWord -> 65535
|
||||
else -> 0x7fffffff
|
||||
}
|
||||
if(rightNum.number<maximum) {
|
||||
val numPlusOne = rightNum.number.toInt()+1
|
||||
val newExpr = BinaryExpression(expr.left, "<", NumericLiteral(rightNum.type, numPlusOne.toDouble(), rightNum.position), expr.position)
|
||||
|
||||
+9
-22
@@ -1,32 +1,19 @@
|
||||
%import textio
|
||||
%import math
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
; Test the routine
|
||||
sub start() {
|
||||
str buffer = iso:"The Quick Brown Fox Jumps Over The Lazy Dog. 1234567890 abcdefghijklmnopqrstuvwxyz !@#$%^&*()_+=-[]{}|;':,./<>? Mary had a little lamb. It's fleece was white as snow. Qoth the raven, 'It's wedding day,"
|
||||
str buffer2 = iso:"Qoth the raven, nevermore. Qoth the raven, nevermore. The raven is not the raven, but the nightingale."
|
||||
str buffer3 = iso:"99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, 98 bottles of beer on the wall."
|
||||
|
||||
txt.print_uwhex(cx16.memory_crc(buffer, len(buffer)), true)
|
||||
txt.spc()
|
||||
txt.print_uwhex(math.crc16(buffer, len(buffer), $ffff, 0), true)
|
||||
txt.spc()
|
||||
txt.print_uwhex(math.crc16(buffer,len(buffer), 0, 0), true)
|
||||
txt.nl()
|
||||
txt.print_uwhex(cx16.memory_crc(buffer2, len(buffer2)), true)
|
||||
txt.spc()
|
||||
txt.print_uwhex(math.crc16(buffer2,len(buffer2), $ffff, 0), true)
|
||||
txt.spc()
|
||||
txt.print_uwhex(math.crc16(buffer2,len(buffer2), 0, 0), true)
|
||||
txt.nl()
|
||||
txt.print_uwhex(cx16.memory_crc(buffer3, len(buffer3)), true)
|
||||
txt.spc()
|
||||
txt.print_uwhex(math.crc16(buffer3,len(buffer3), $ffff, 0), true)
|
||||
txt.spc()
|
||||
txt.print_uwhex(math.crc16(buffer3,len(buffer3), 0, 0), true)
|
||||
long counter
|
||||
long lv
|
||||
for lv in 4000 to 94000-1 {
|
||||
counter++
|
||||
}
|
||||
for lv in 94000-1 downto 4000 {
|
||||
counter++
|
||||
}
|
||||
txt.print_l(counter)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user