mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
some optimizations
This commit is contained in:
parent
334e6dca28
commit
8e6b91cb9e
@ -486,13 +486,24 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
return false
|
||||
}
|
||||
|
||||
private fun directIntoY(expr: PtExpression): Boolean {
|
||||
return when(expr) {
|
||||
is PtIdentifier -> true
|
||||
is PtMachineRegister -> true
|
||||
is PtNumber -> true
|
||||
is PtBuiltinFunctionCall -> expr.name in arrayOf("lsb", "msb")
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun optimizedRemainderExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
when(expr.type) {
|
||||
DataType.UBYTE -> {
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pha")
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
||||
asmgen.out(" pla | jsr math.divmod_ub_asm")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pla")
|
||||
asmgen.out(" jsr math.divmod_ub_asm")
|
||||
if(target.register==RegisterOrPair.A)
|
||||
asmgen.out(" cmp #0") // fix the status register
|
||||
else
|
||||
@ -513,17 +524,19 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
when(expr.type) {
|
||||
DataType.UBYTE -> {
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pha")
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
||||
asmgen.out(" pla | jsr math.divmod_ub_asm")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pla")
|
||||
asmgen.out(" jsr math.divmod_ub_asm")
|
||||
assignRegisterByte(target, CpuRegister.Y, false, true)
|
||||
return true
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, true)
|
||||
asmgen.out(" pha")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pha")
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, true)
|
||||
asmgen.out(" pla | jsr math.divmod_b_asm")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pla")
|
||||
asmgen.out(" jsr math.divmod_b_asm")
|
||||
assignRegisterByte(target, CpuRegister.Y, true, true)
|
||||
return true
|
||||
}
|
||||
@ -549,9 +562,10 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
when(expr.type) {
|
||||
in ByteDatatypes -> {
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, expr.type in SignedDatatypes)
|
||||
asmgen.out(" pha")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pha")
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, expr.type in SignedDatatypes)
|
||||
asmgen.out(" pla | jsr math.multiply_bytes")
|
||||
if(!directIntoY(expr.right)) asmgen.out(" pla")
|
||||
asmgen.out(" jsr math.multiply_bytes")
|
||||
assignRegisterByte(target, CpuRegister.A, false, true)
|
||||
return true
|
||||
}
|
||||
@ -814,9 +828,14 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
assignRegisterByte(target, CpuRegister.A, dt in SignedDatatypes, true)
|
||||
} else {
|
||||
assignExpressionToRegister(left, RegisterOrPair.A, left.type==DataType.BYTE)
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", right.type)
|
||||
asmgen.out(" pla")
|
||||
if(directIntoY(right)) {
|
||||
assignExpressionToRegister(right, RegisterOrPair.Y, left.type==DataType.BYTE)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||
} else {
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", right.type)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
if (expr.operator == "+")
|
||||
asmgen.out(" clc | adc P8ZP_SCRATCH_B1")
|
||||
else
|
||||
@ -1005,9 +1024,14 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla")
|
||||
if(directIntoY(expr.right)) {
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||
} else {
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
when (expr.operator) {
|
||||
"&" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"|" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
@ -1075,9 +1099,14 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
} else {
|
||||
// normal evaluation into A
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla")
|
||||
if(directIntoY(expr.right)) {
|
||||
assignExpressionToRegister(expr.right, RegisterOrPair.Y, false)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||
} else {
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(expr.right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
when (expr.operator) {
|
||||
"and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
@ -1783,9 +1812,14 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
private fun assignLogicalAndOrWithSimpleRightOperandByte(target: AsmAssignTarget, left: PtExpression, operator: String, right: PtExpression) {
|
||||
// normal evaluation, not worth to shortcircuit the simple right operand
|
||||
assignExpressionToRegister(left, RegisterOrPair.A, false)
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla")
|
||||
if(directIntoY(right)) {
|
||||
assignExpressionToRegister(right, RegisterOrPair.Y, false)
|
||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||
} else {
|
||||
asmgen.out(" pha")
|
||||
assignExpressionToVariable(right, "P8ZP_SCRATCH_B1", DataType.UBYTE)
|
||||
asmgen.out(" pla")
|
||||
}
|
||||
when (operator) {
|
||||
"and" -> asmgen.out(" and P8ZP_SCRATCH_B1")
|
||||
"or" -> asmgen.out(" ora P8ZP_SCRATCH_B1")
|
||||
|
@ -445,6 +445,14 @@ class ExpressionSimplifier(private val program: Program,
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr, cast, parent))
|
||||
}
|
||||
}
|
||||
else if(functionCallExpr.target.nameInSource == listOf("string", "contains")) {
|
||||
val target = (functionCallExpr.args[0] as? IdentifierReference)?.targetVarDecl(program)
|
||||
if(target?.value is StringLiteral) {
|
||||
errors.info("for actual strings, use a regular containment check instead: 'char in string'", functionCallExpr.position)
|
||||
val contains = ContainmentCheck(functionCallExpr.args[1], functionCallExpr.args[0], functionCallExpr.position)
|
||||
return listOf(IAstModification.ReplaceNode(functionCallExpr as Node, contains, parent))
|
||||
}
|
||||
}
|
||||
|
||||
return noModifications
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ romsub $fe00 = AYINT() clobbers(A,X,Y) ; fac1-> signed word in 100-101
|
||||
romsub $fe03 = GIVAYF(ubyte lo @ Y, ubyte hi @ A) clobbers(A,X,Y)
|
||||
|
||||
romsub $fe06 = FOUT() clobbers(X) -> uword @ AY ; fac1 -> string, address returned in AY
|
||||
romsub $fe09 = VAL_1(uword string @XY, ubyte length @A) clobbers(A,X,Y) -> float @FAC1 ; convert ASCII string in XY and length in A, to floating point in FAC1. WARNING: not implemented in the ROM yet!
|
||||
romsub $fe09 = VAL_1(uword string @XY, ubyte length @A) clobbers(A,X,Y) -> float @FAC1 ; convert ASCII string in XY and length in A, to floating point in FAC1. WARNING: only implemented in ROM 47+. Safer to use floats.parse() instead.
|
||||
|
||||
; GETADR: fac1 -> unsigned word in Y/A (might throw ILLEGAL QUANTITY) (result also in $14/15)
|
||||
; (tip: use GETADRAY to get A/Y output; lo/hi switched to normal little endian order)
|
||||
@ -139,7 +139,7 @@ asmsub parse(str value @AY) -> float @FAC1 {
|
||||
; -- parse a string value of a number to float in FAC1
|
||||
; warning: on older <R47 kernals it uses an internal BASIC routine that is ROM version dependent,
|
||||
; ($deb6 is inside the routine for VAL at $deb3) See basic.sym from x16-rom
|
||||
; TODO once VAL_1 is merged into the kernal properly, remove all the workarounds here
|
||||
; TODO once ROM v47 is released, all the workarounds here can be removed. But probably keep the kernal VAL_1 existance check
|
||||
%asm {{
|
||||
ldx VAL_1
|
||||
cpx #$4c ; is there an implementation in VAL_1? (test for JMP)
|
||||
|
@ -43,7 +43,7 @@ Compiler:
|
||||
|
||||
Libraries:
|
||||
|
||||
- once a VAL_1 implementation is merged into the X16 kernal properly, remove all the workarounds in cx16 floats.parse_f() . Prototype parse routine in examples/cx16/floatparse.p8
|
||||
- once kernal rom v47 is released, remove most of the workarounds in cx16 floats.parse_f() . Prototype parse routine in examples/cx16/floatparse.p8
|
||||
- fix the problems in atari target, and flesh out its libraries.
|
||||
- c128 target: make syslib more complete (missing kernal routines)?
|
||||
- pet32 target: make syslib more complete (missing kernal routines)?
|
||||
@ -51,7 +51,6 @@ Libraries:
|
||||
|
||||
Optimizations:
|
||||
|
||||
- the many pha/pla's in AssignmentAsmGen added to the code size. Can they be tweaked better? Maybe they are not always required, how to detect that/use another register/tempvar/etc?
|
||||
- VariableAllocator: can we think of a smarter strategy for allocating variables into zeropage, rather than first-come-first-served?
|
||||
for instance, vars used inside loops first, then loopvars, then uwords used as pointers, then the rest
|
||||
- various optimizers skip stuff if compTarget.name==VMTarget.NAME. Once 6502-codegen is done from IR code,
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
main {
|
||||
|
||||
; float parsing prototype (remember, there's no official kernal VAL_1 routine to do this yet...)
|
||||
; float parsing prototype
|
||||
|
||||
sub start() {
|
||||
f("")
|
||||
|
@ -5,56 +5,21 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
str s = "?"
|
||||
s[0] = 's'
|
||||
txt.print(s)
|
||||
str s = "the quick brown fox jumps over the lazy dog."
|
||||
uword sp = &s
|
||||
|
||||
cbm.SETTIM(0,0,0)
|
||||
repeat 5000 {
|
||||
cx16.r0L = 'v' in s
|
||||
}
|
||||
txt.print_uw(cbm.RDTIM16())
|
||||
txt.nl()
|
||||
|
||||
if 's' in s {
|
||||
txt.print("ok1\n")
|
||||
} else {
|
||||
txt.print("fail1\n")
|
||||
cbm.SETTIM(0,0,0)
|
||||
repeat 5000 {
|
||||
cx16.r0L = string.contains(s, 'v')
|
||||
}
|
||||
|
||||
void string.find(s, 's')
|
||||
if_cs {
|
||||
txt.print("ok2\n")
|
||||
} else {
|
||||
txt.print("fail2\n")
|
||||
}
|
||||
|
||||
if string.contains(s, 's') {
|
||||
txt.print("ok3\n")
|
||||
} else {
|
||||
txt.print("fail3\n")
|
||||
}
|
||||
|
||||
if 'q' in s {
|
||||
txt.print("ok1\n")
|
||||
} else {
|
||||
txt.print("fail1\n")
|
||||
}
|
||||
|
||||
void string.find(s, 'q')
|
||||
if_cs {
|
||||
txt.print("ok2\n")
|
||||
} else {
|
||||
txt.print("fail2\n")
|
||||
}
|
||||
|
||||
if string.contains(s, 'q') {
|
||||
txt.print("ok3\n")
|
||||
} else {
|
||||
txt.print("fail3\n")
|
||||
}
|
||||
|
||||
str buffer="?" * 20
|
||||
str name = "irmen de jong"
|
||||
string.left(name, 5, buffer)
|
||||
txt.print(buffer)
|
||||
txt.nl()
|
||||
string.right(name, 4, buffer)
|
||||
txt.print(buffer)
|
||||
txt.print_uw(cbm.RDTIM16())
|
||||
txt.nl()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user