optimize /256 more, and fixed a unsigned byte word cast error

This commit is contained in:
Irmen de Jong 2024-01-07 00:01:00 +01:00
parent 7dd758a753
commit d85c347a6c
6 changed files with 103 additions and 55 deletions

View File

@ -2092,20 +2092,20 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
} }
if(valueDt==DataType.UBYTE || valueDt==DataType.BOOL) { if(valueDt in ByteDatatypes) {
when(target.register) { when(target.register) {
RegisterOrPair.A, RegisterOrPair.A,
RegisterOrPair.X, RegisterOrPair.X,
RegisterOrPair.Y -> { RegisterOrPair.Y -> {
// 'cast' an ubyte value to a byte register; no cast needed at all // 'cast' an ubyte value to a byte register; no cast needed at all
return assignExpressionToRegister(value, target.register, false) return assignExpressionToRegister(value, target.register, valueDt in SignedDatatypes)
} }
RegisterOrPair.AX, RegisterOrPair.AX,
RegisterOrPair.AY, RegisterOrPair.AY,
RegisterOrPair.XY, RegisterOrPair.XY,
in Cx16VirtualRegisters -> { in Cx16VirtualRegisters -> {
assignExpressionToRegister(value, RegisterOrPair.A, false) assignExpressionToRegister(value, RegisterOrPair.A, false)
assignRegisterByte(target, CpuRegister.A, false, true) assignRegisterByte(target, CpuRegister.A, valueDt in SignedDatatypes, true)
return return
} }
else -> {} else -> {}
@ -2124,7 +2124,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
RegisterOrPair.XY, RegisterOrPair.XY,
in Cx16VirtualRegisters -> { in Cx16VirtualRegisters -> {
// 'cast' uword into a 16 bits register, just assign it // 'cast' uword into a 16 bits register, just assign it
return assignExpressionToRegister(value, target.register!!, false) return assignExpressionToRegister(value, target.register!!, targetDt in SignedDatatypes)
} }
else -> {} else -> {}
} }

View File

@ -626,10 +626,25 @@ class ExpressionSimplifier(private val program: Program,
return expr.left return expr.left
} }
} }
256.0 -> {
when(leftDt) {
DataType.UBYTE -> return NumericLiteral(DataType.UBYTE, 0.0, expr.position)
DataType.BYTE -> return null // is either 0 or -1 we cannot tell here
DataType.UWORD, DataType.WORD -> {
// just use: msb(value) as type
val msb = BuiltinFunctionCall(IdentifierReference(listOf("msb"), expr.position), mutableListOf(expr.left), expr.position)
return if(leftDt==DataType.WORD)
TypecastExpression(msb, DataType.BYTE, true, expr.position)
else
TypecastExpression(msb, DataType.UWORD, true, expr.position)
}
else -> return null
}
}
in powersOfTwo -> { in powersOfTwo -> {
if (leftDt==DataType.UBYTE || leftDt==DataType.UWORD) { if (leftDt==DataType.UBYTE || leftDt==DataType.UWORD) {
// Unsigned number divided by a power of two => shift right // Unsigned number divided by a power of two => shift right
// Signed number can't simply be bitshifted in this case (due to rounding issues for negative values), // Signed number can't simply be bitshifted in this case (due to rounding issues for negative values), TODO is this correct???
// so we leave that as is and let the code generator deal with it. // so we leave that as is and let the code generator deal with it.
val numshifts = log2(cv).toInt() val numshifts = log2(cv).toInt()
return BinaryExpression(expr.left, ">>", NumericLiteral.optimalInteger(numshifts, expr.position), expr.position) return BinaryExpression(expr.left, ">>", NumericLiteral.optimalInteger(numshifts, expr.position), expr.position)
@ -791,8 +806,8 @@ class ExpressionSimplifier(private val program: Program,
} }
DataType.UWORD -> { DataType.UWORD -> {
if (amount >= 16) { if (amount >= 16) {
errors.warn("shift always results in 0", expr.position) errors.err("useless to shift by more than 15 bits", expr.position)
return NumericLiteral.optimalInteger(0, expr.position) return null
} }
else if(amount==8) { else if(amount==8) {
// shift right by 8 bits is just a byte operation: msb(X) as uword // shift right by 8 bits is just a byte operation: msb(X) as uword
@ -806,11 +821,20 @@ class ExpressionSimplifier(private val program: Program,
} }
} }
DataType.WORD -> { DataType.WORD -> {
// bit-shifting a signed value shouldn't be allowed by the compiler but here we go... if (amount >= 16) {
if (amount > 16) { errors.err("useless to shift by more than 15 bits", expr.position)
expr.right = NumericLiteral.optimalInteger(16, expr.right.position)
return null return null
} }
else if(amount == 8) {
// shift right by 8 bits is just a byte operation: msb(X) as byte
val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.position), mutableListOf(expr.left), expr.position)
return TypecastExpression(msb, DataType.BYTE, true, expr.position)
}
else if(amount > 8) {
// same as above but with residual shifts.
val msb = FunctionCallExpression(IdentifierReference(listOf("msb"), expr.position), mutableListOf(expr.left), expr.position)
return TypecastExpression(BinaryExpression(msb, ">>", NumericLiteral.optimalInteger(amount - 8, expr.position), expr.position), DataType.BYTE, true, expr.position)
}
} }
else -> { else -> {
} }

View File

@ -679,6 +679,29 @@ main {
stmts.size shouldBe 3 stmts.size shouldBe 3
} }
test("ubyte to word casts") {
var src="""
main {
sub start() {
ubyte @shared bb = 255
cx16.r0s = (bb as byte) as word ; should result in -1 word value
cx16.r1s = (bb as word) ; should result in 255 word value
}
}"""
val result = compileText(C64Target(), true, src, writeAssembly = false)!!
val stmts = result.compilerAst.entrypoint.statements
stmts.size shouldBe 4
val assign1tc = (stmts[2] as Assignment).value as TypecastExpression
val assign2tc = (stmts[3] as Assignment).value as TypecastExpression
assign1tc.type shouldBe DataType.WORD
assign2tc.type shouldBe DataType.WORD
assign2tc.expression shouldBe instanceOf<IdentifierReference>()
val assign1subtc = (assign1tc.expression as TypecastExpression)
assign1subtc.type shouldBe DataType.BYTE
assign1subtc.expression shouldBe instanceOf<IdentifierReference>()
}
test("add missing & to function arguments") { test("add missing & to function arguments") {
val text=""" val text="""
main { main {

View File

@ -1,6 +1,7 @@
TODO TODO
==== ====
... ...

View File

@ -1,3 +1,4 @@
%import textio
%import syslib %import syslib
%import test_stack %import test_stack
%import conv %import conv
@ -29,7 +30,7 @@ main {
draw_lines_hiddenremoval() draw_lines_hiddenremoval()
; draw_lines() ; draw_lines()
anglex += 217 anglex += 317
angley -= 505 angley -= 505
anglez += 452 anglez += 452
@ -58,25 +59,10 @@ main {
cx16.GRAPH_put_next_char(c) cx16.GRAPH_put_next_char(c)
} }
asmsub print_number_gfx(ubyte num @ A) clobbers(A,X,Y) { sub print_number_gfx(ubyte num) {
%asm {{ conv.str_ub(num)
jsr conv.ubyte2decimal for cx16.r9L in conv.string_out
phx cx16.GRAPH_put_next_char(cx16.r9L)
pha
cpy #'0'
beq +
tya
jsr cx16.GRAPH_put_char
pla
jsr cx16.GRAPH_put_char
bra _ones
+ pla
cmp #'0'
beq _ones
jsr cx16.GRAPH_put_char
_ones pla
jmp cx16.GRAPH_put_char
}}
} }
const uword screen_width = 320 const uword screen_width = 320

View File

@ -1,42 +1,56 @@
%import textio %import textio
%import string %import math
%zeropage basicsafe %zeropage basicsafe
%option no_sysinit %option no_sysinit
main { main {
sub start() { sub start() {
uword @shared uw = $3f2f
if uw & $0800 ubyte @shared bb = 255
txt.print("ok1\n") txt.print_w((bb as byte) as word) ; should print -1 !
txt.nl()
txt.print_w((bb as word)) ; should print 255 !
txt.nl()
txt.nl()
if uw & 8 bb= 30
txt.print("ok2\n") word @shared offset=1000
cx16.r2s = (math.sin8u(bb) as word) + offset ; 1213
txt.print_w(cx16.r2s)
txt.nl()
txt.nl()
if uw & $0800 ==0 ; expected results:
txt.print("fail1\n") ; -96
; -96
; 947
; 947
if uw & $0800 !=0 word @shared wcosa = 1111
txt.print("ok3\n") word @shared wsinb = -22
if uw & 8 ==0 txt.print_w(wcosa*wsinb / 256)
txt.print("fail2\n") txt.nl()
txt.print_w((wcosa*wsinb) >>8)
txt.nl()
if uw & 8 !=0 word[] rotatedz = [-11111,-12222,-13333,-14444,-15555]
txt.print("ok4\n")
word @shared persp1 = 1000 + rotatedz[2]/256
txt.print_w(persp1)
txt.nl()
persp1 = 1000 + (rotatedz[2]>>8)
txt.print_w(persp1)
txt.nl()
; ubyte[3] cycle_reverseflags
;
; ubyte @shared flags=2
; bool @shared b1
; bool @shared b2
;
; cycle_reverseflags[1]= b1 and b2 ; flags & 2 != 0 as bool
if uw & $ff00 == $3f00
txt.print("ok5\n")
if uw & $ff00 != $3f00
txt.print("fail5\n")
if uw & $00ff == $002f
txt.print("ok6\n")
if uw & $00ff != $002f
txt.print("fail6\n")
} }
} }