optimized neg(x) and abs(x)

This commit is contained in:
Irmen de Jong 2020-09-29 03:58:17 +02:00
parent 96ef7ba55d
commit 448c934cba
4 changed files with 77 additions and 52 deletions

View File

@ -355,19 +355,19 @@ mul_f .proc
.pend .pend
neg_f .proc neg_f .proc
; -- push -flt back on stack ; -- toggle the sign bit on the stack
jsr pop_float_fac1 lda P8ESTACK_LO+3,x
stx P8ZP_SCRATCH_REG eor #$80
jsr NEGOP sta P8ESTACK_LO+3,x
jmp push_fac1_as_result rts
.pend .pend
abs_f .proc abs_f .proc
; -- push abs(float) on stack (as float) ; -- strip the sign bit on the stack
jsr pop_float_fac1 lda P8ESTACK_LO+3,x
stx P8ZP_SCRATCH_REG and #$7f
jsr ABS sta P8ESTACK_LO+3,x
jmp push_fac1_as_result rts
.pend .pend
equal_f .proc equal_f .proc

View File

@ -84,7 +84,7 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> { override fun before(assignment: Assignment, parent: Node): Iterable<IAstModification> {
val valueType = assignment.value.inferType(program) val valueType = assignment.value.inferType(program)
val targetType = assignment.target.inferType(program, assignment) 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) { val assignments = if (assignment.value is ArrayLiteralValue) {
flattenStructAssignmentFromStructLiteral(assignment, program) // 'structvar = [ ..... ] ' flattenStructAssignmentFromStructLiteral(assignment, program) // 'structvar = [ ..... ] '
} else { } else {
@ -179,26 +179,34 @@ internal class StatementReorderer(val program: Program) : AstWalker() {
when (structAssignment.value) { when (structAssignment.value) {
is IdentifierReference -> { is IdentifierReference -> {
val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!! val sourceVar = (structAssignment.value as IdentifierReference).targetVarDecl(program.namespace)!!
if (sourceVar.struct == null) when {
throw FatalAstException("can only assign arrays or structs to structs") sourceVar.struct!=null -> {
// struct memberwise copy // struct memberwise copy
val sourceStruct = sourceVar.struct!! val sourceStruct = sourceVar.struct!!
if(sourceStruct!==targetVar.struct) { if(sourceStruct!==targetVar.struct) {
// structs are not the same in assignment // structs are not the same in assignment
return listOf() // error will be printed elsewhere return listOf() // error will be printed elsewhere
} }
return struct.statements.zip(sourceStruct.statements).map { member -> return struct.statements.zip(sourceStruct.statements).map { member ->
val targetDecl = member.first as VarDecl val targetDecl = member.first as VarDecl
val sourceDecl = member.second as VarDecl val sourceDecl = member.second as VarDecl
if(targetDecl.name != sourceDecl.name) if(targetDecl.name != sourceDecl.name)
throw FatalAstException("struct member mismatch") throw FatalAstException("struct member mismatch")
val mangled = mangledStructMemberName(identifierName, targetDecl.name) val mangled = mangledStructMemberName(identifierName, targetDecl.name)
val idref = IdentifierReference(listOf(mangled), structAssignment.position) val idref = IdentifierReference(listOf(mangled), structAssignment.position)
val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name) val sourcemangled = mangledStructMemberName(sourceVar.name, sourceDecl.name)
val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position) val sourceIdref = IdentifierReference(listOf(sourcemangled), structAssignment.position)
val assign = Assignment(AssignTarget(idref, null, null, structAssignment.position), sourceIdref, member.second.position) val assign = Assignment(AssignTarget(idref, null, null, structAssignment.position), sourceIdref, member.second.position)
assign.linkParents(structAssignment) assign.linkParents(structAssignment)
assign assign
}
}
sourceVar.isArray -> {
TODO("assign struct array $structAssignment")
}
else -> {
throw FatalAstException("can only assign arrays or structs to structs")
}
} }
} }
is ArrayLiteralValue -> { is ArrayLiteralValue -> {

View File

@ -1680,15 +1680,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
DataType.FLOAT -> { DataType.FLOAT -> {
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {
asmgen.saveRegister(CpuRegister.X) // simply flip the sign bit in the float
asmgen.out(""" asmgen.out("""
lda #<${target.asmVarname} lda ${target.asmVarname}+1
ldy #>${target.asmVarname} eor #$80
jsr floats.MOVFM sta ${target.asmVarname}+1
jsr floats.NEGOP
ldx #<${target.asmVarname}
ldy #>${target.asmVarname}
jsr floats.MOVMF
""") """)
asmgen.restoreRegister(CpuRegister.X) asmgen.restoreRegister(CpuRegister.X)
} }

View File

@ -1,15 +1,11 @@
%import textio %import textio
%import syslib %import syslib
%import floats
%zeropage basicsafe %zeropage basicsafe
main { main {
struct Color {
ubyte red
ubyte green
ubyte blue
}
; Color c1 = [11,22,33] ; TODO fix crash ; Color c1 = [11,22,33] ; TODO fix crash
; Color c2 = [11,22,33] ; TODO fix crash ; Color c2 = [11,22,33] ; TODO fix crash
@ -24,15 +20,40 @@ main {
sub start() { sub start() {
Color c1 = [11,22,33] byte bb = 100
Color c2 = [11,22,33] word ww = 30000
Color c3 = [11,22,33] float ff1 = 12345
uword[] colors = [ c1, c2, c3] ; TODO should contain pointers to (the first element) of each struct float ff2 = -99999
c1.red = 100 floats.print_f(ff1)
c1.green = 100 txt.chrout('\n')
c1.blue = 100 ;ff = 1+((-ff) *3) ; TODO fix invalid splitting (can't split because it references ff itself)
; c1 = [11,22,33] ; TODO rewrite into individual struct member assignments ;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 uword s