From 448c934cbae15ec32cfc31cd281b82a8dd404b6f Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Tue, 29 Sep 2020 03:58:17 +0200 Subject: [PATCH] optimized neg(x) and abs(x) --- compiler/res/prog8lib/c64/floats.asm | 20 ++++---- .../ast/processing/StatementReorderer.kt | 50 +++++++++++-------- .../assignment/AugmentableAssignmentAsmGen.kt | 12 ++--- examples/test.p8 | 47 ++++++++++++----- 4 files changed, 77 insertions(+), 52 deletions(-) diff --git a/compiler/res/prog8lib/c64/floats.asm b/compiler/res/prog8lib/c64/floats.asm index 1ac131b50..940b89567 100644 --- a/compiler/res/prog8lib/c64/floats.asm +++ b/compiler/res/prog8lib/c64/floats.asm @@ -355,19 +355,19 @@ mul_f .proc .pend neg_f .proc - ; -- push -flt back on stack - jsr pop_float_fac1 - stx P8ZP_SCRATCH_REG - jsr NEGOP - jmp push_fac1_as_result + ; -- toggle the sign bit on the stack + lda P8ESTACK_LO+3,x + eor #$80 + sta P8ESTACK_LO+3,x + rts .pend abs_f .proc - ; -- push abs(float) on stack (as float) - jsr pop_float_fac1 - stx P8ZP_SCRATCH_REG - jsr ABS - jmp push_fac1_as_result + ; -- strip the sign bit on the stack + lda P8ESTACK_LO+3,x + and #$7f + sta P8ESTACK_LO+3,x + rts .pend equal_f .proc diff --git a/compiler/src/prog8/ast/processing/StatementReorderer.kt b/compiler/src/prog8/ast/processing/StatementReorderer.kt index 5810ad86e..5f0fed19b 100644 --- a/compiler/src/prog8/ast/processing/StatementReorderer.kt +++ b/compiler/src/prog8/ast/processing/StatementReorderer.kt @@ -84,7 +84,7 @@ internal class StatementReorderer(val program: Program) : AstWalker() { override fun before(assignment: Assignment, parent: Node): Iterable { val valueType = assignment.value.inferType(program) val targetType = assignment.target.inferType(program, assignment) - if(valueType.istype(DataType.STRUCT) && targetType.istype(DataType.STRUCT)) { + if(targetType.istype(DataType.STRUCT) && (valueType.istype(DataType.STRUCT) || valueType.typeOrElse(DataType.STRUCT) in ArrayDatatypes )) { val assignments = if (assignment.value is ArrayLiteralValue) { flattenStructAssignmentFromStructLiteral(assignment, program) // 'structvar = [ ..... ] ' } else { @@ -179,26 +179,34 @@ internal class StatementReorderer(val program: Program) : AstWalker() { when (structAssignment.value) { is IdentifierReference -> { val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!! - if (sourceVar.struct == null) - throw FatalAstException("can only assign arrays or structs to structs") - // struct memberwise copy - val sourceStruct = sourceVar.struct!! - if(sourceStruct!==targetVar.struct) { - // structs are not the same in assignment - return listOf() // error will be printed elsewhere - } - return struct.statements.zip(sourceStruct.statements).map { member -> - val targetDecl = member.first as VarDecl - val sourceDecl = member.second as VarDecl - if(targetDecl.name != sourceDecl.name) - throw FatalAstException("struct member mismatch") - val mangled = mangledStructMemberName(identifierName, targetDecl.name) - val idref = IdentifierReference(listOf(mangled), structAssignment.position) - val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name) - val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position) - val assign = Assignment(AssignTarget(idref, null, null, structAssignment.position), sourceIdref, member.second.position) - assign.linkParents(structAssignment) - assign + when { + sourceVar.struct!=null -> { + // struct memberwise copy + val sourceStruct = sourceVar.struct!! + if(sourceStruct!==targetVar.struct) { + // structs are not the same in assignment + return listOf() // error will be printed elsewhere + } + return struct.statements.zip(sourceStruct.statements).map { member -> + val targetDecl = member.first as VarDecl + val sourceDecl = member.second as VarDecl + if(targetDecl.name != sourceDecl.name) + throw FatalAstException("struct member mismatch") + val mangled = mangledStructMemberName(identifierName, targetDecl.name) + val idref = IdentifierReference(listOf(mangled), structAssignment.position) + val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name) + val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position) + val assign = Assignment(AssignTarget(idref, null, null, structAssignment.position), sourceIdref, member.second.position) + assign.linkParents(structAssignment) + assign + } + } + sourceVar.isArray -> { + TODO("assign struct array $structAssignment") + } + else -> { + throw FatalAstException("can only assign arrays or structs to structs") + } } } is ArrayLiteralValue -> { diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt index ef1626e47..ee79302cc 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -1680,15 +1680,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, DataType.FLOAT -> { when(target.kind) { TargetStorageKind.VARIABLE -> { - asmgen.saveRegister(CpuRegister.X) + // simply flip the sign bit in the float asmgen.out(""" - lda #<${target.asmVarname} - ldy #>${target.asmVarname} - jsr floats.MOVFM - jsr floats.NEGOP - ldx #<${target.asmVarname} - ldy #>${target.asmVarname} - jsr floats.MOVMF + lda ${target.asmVarname}+1 + eor #$80 + sta ${target.asmVarname}+1 """) asmgen.restoreRegister(CpuRegister.X) } diff --git a/examples/test.p8 b/examples/test.p8 index fe6c1b6d4..cfca6ed46 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,15 +1,11 @@ %import textio %import syslib +%import floats %zeropage basicsafe main { - struct Color { - ubyte red - ubyte green - ubyte blue - } ; Color c1 = [11,22,33] ; TODO fix crash ; Color c2 = [11,22,33] ; TODO fix crash @@ -24,15 +20,40 @@ main { sub start() { - Color c1 = [11,22,33] - Color c2 = [11,22,33] - Color c3 = [11,22,33] - uword[] colors = [ c1, c2, c3] ; TODO should contain pointers to (the first element) of each struct + byte bb = 100 + word ww = 30000 + float ff1 = 12345 + float ff2 = -99999 - c1.red = 100 - c1.green = 100 - c1.blue = 100 - ; c1 = [11,22,33] ; TODO rewrite into individual struct member assignments + floats.print_f(ff1) + txt.chrout('\n') + ;ff = 1+((-ff) *3) ; TODO fix invalid splitting (can't split because it references ff itself) + ;ff = 1+((-ff2) *3) ; TODO splitting should be okay here + ff1 = -ff2 * 3 + floats.print_f(ff1) + txt.chrout('\n') + floats.print_f(-ff2) + txt.chrout('\n') + floats.print_f(-ff1) + txt.chrout('\n') + return + + struct Color { + ubyte red + ubyte green + ubyte blue + } + + ;Color c1 = [11,22,33] ; TODO fix struct initializer crash + Color c1 + Color c2 + Color c3 + ;Color c2 = [11,22,33] + ;Color c3 = [11,22,33] + ;uword[] colors = [ c1, c2, c3] ; TODO should contain pointers to (the first element) of each struct + + c1 = c2 + ;c1 = [11,22,33] ; TODO rewrite into individual struct member assignments uword s