added start of optimized in-place assignment code (for prefix expressions)

This commit is contained in:
Irmen de Jong 2020-08-20 18:43:10 +02:00
parent e1812ce16c
commit cffb582568
2 changed files with 221 additions and 23 deletions

View File

@ -1,9 +1,11 @@
package prog8.compiler.target.c64.codegen package prog8.compiler.target.c64.codegen
import prog8.ast.Program import prog8.ast.Program
import prog8.ast.base.DataType
import prog8.ast.expressions.BinaryExpression import prog8.ast.expressions.BinaryExpression
import prog8.ast.expressions.PrefixExpression import prog8.ast.expressions.PrefixExpression
import prog8.ast.expressions.TypecastExpression import prog8.ast.expressions.TypecastExpression
import prog8.ast.statements.AssignTarget
import prog8.ast.statements.Assignment import prog8.ast.statements.Assignment
import prog8.compiler.AssemblyError import prog8.compiler.AssemblyError
@ -12,23 +14,182 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
private val asmgen: AsmGen) { private val asmgen: AsmGen) {
fun translate(assign: Assignment) { fun translate(assign: Assignment) {
require(assign.isAugmentable) require(assign.isAugmentable)
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
// when (assign.value) { when (assign.value) {
// is PrefixExpression -> { is PrefixExpression -> {
// TODO("aug prefix") // A = -A , A = +A, A = ~A
// } val px = assign.value as PrefixExpression
// is TypecastExpression -> { val type = px.inferType(program).typeOrElse(DataType.STRUCT)
// TODO("aug typecast") when(px.operator) {
// } "+" -> {}
// is BinaryExpression -> { "-" -> inplaceNegate(assign.target, type)
// TODO("aug binary") "~" -> inplaceInvert(assign.target, type)
// } "not" -> inplaceBooleanNot(assign.target, type)
// else -> { else -> throw AssemblyError("invalid prefix operator")
// throw AssemblyError("invalid aug assign value type") }
// } }
// } is TypecastExpression -> {
println("TODO optimize typecast assignment ${assign.position}")
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
}
is BinaryExpression -> {
println("TODO optimize binexpr assignment ${assign.position}")
assignmentAsmGen.translateOtherAssignment(assign) // TODO get rid of this fallback
}
else -> {
throw AssemblyError("invalid aug assign value type")
}
}
}
private fun inplaceBooleanNot(target: AssignTarget, dt: DataType) {
val arrayIdx = target.arrayindexed
val identifier = target.identifier
val memory = target.memoryAddress
when(dt) {
DataType.UBYTE -> {
when {
identifier!=null -> {
val name = asmgen.asmIdentifierName(identifier)
asmgen.out("""
lda $name
beq +
lda #1
+ eor #1
sta $name""")
}
memory!=null -> {
TODO()
}
arrayIdx!=null -> {
TODO()
}
}
}
DataType.UWORD -> {
when {
identifier!=null -> {
val name = asmgen.asmIdentifierName(identifier)
asmgen.out("""
lda $name
ora $name+1
beq +
lda #1
+ eor #1
sta $name
lsr a
sta $name+1""")
}
memory!=null -> {
TODO()
}
arrayIdx!=null -> {
TODO()
}
}
}
else -> throw AssemblyError("boolean-not of invalid type")
}
}
private fun inplaceInvert(target: AssignTarget, dt: DataType) {
val arrayIdx = target.arrayindexed
val identifier = target.identifier
val memory = target.memoryAddress
when(dt) {
DataType.UBYTE -> {
when {
identifier!=null -> {
val name = asmgen.asmIdentifierName(identifier)
asmgen.out("""
lda $name
eor #255
sta $name""")
}
memory!=null -> {
TODO()
}
arrayIdx!=null -> {
TODO()
}
}
}
DataType.UWORD -> {
when {
identifier!=null -> {
val name = asmgen.asmIdentifierName(identifier)
asmgen.out("""
lda $name
eor #255
sta $name
lda $name+1
eor #255
sta $name+1""")
}
memory!=null -> {
TODO()
}
arrayIdx!=null -> {
TODO()
}
}
}
else -> throw AssemblyError("invert of invalid type")
}
}
private fun inplaceNegate(target: AssignTarget, dt: DataType) {
val arrayIdx = target.arrayindexed
val identifier = target.identifier
val memory = target.memoryAddress
when(dt) {
DataType.BYTE -> {
when {
identifier!=null -> {
val name = asmgen.asmIdentifierName(identifier)
asmgen.out("""
lda #0
sec
sbc $name
sta $name""")
}
memory!=null -> {
TODO()
}
arrayIdx!=null -> {
TODO()
}
}
}
DataType.WORD -> {
when {
identifier!=null -> {
val name = asmgen.asmIdentifierName(identifier)
asmgen.out("""
lda #0
sec
sbc $name
sta $name
lda #0
sbc $name+1
sta $name+1""")
}
memory!=null -> {
TODO()
}
arrayIdx!=null -> {
TODO()
}
}
}
DataType.FLOAT -> {
TODO()
}
else -> throw AssemblyError("negate of invalid type")
}
} }
} }

View File

@ -7,18 +7,55 @@ main {
sub start() { sub start() {
byte A byte A = 99
byte B = +A ubyte U = $18
byte C = -A word B = 9999
uword W = 43210 uword W = $18f0
c64scr.print_b(A)
c64.CHROUT('\n')
A = -A A = -A
c64scr.print_b(A)
c64scr.print_uw(W)
c64.CHROUT('\n') c64.CHROUT('\n')
W = W as ubyte ; TODO cast(W as ubyte) as uword -> W and 255 U = ~U
c64scr.print_uw(W) c64scr.print_ubhex(U, true)
c64.CHROUT('\n') c64.CHROUT('\n')
U = not U
c64scr.print_ubhex(U, true)
c64.CHROUT('\n')
U = not U
c64scr.print_ubhex(U, true)
c64.CHROUT('\n')
c64scr.print_w(B)
c64.CHROUT('\n')
B = -B
c64scr.print_w(B)
c64.CHROUT('\n')
W = ~W
c64scr.print_uwhex(W, true)
c64.CHROUT('\n')
W = not W
c64scr.print_uwhex(W, true)
c64.CHROUT('\n')
W = not W
c64scr.print_uwhex(W, true)
c64.CHROUT('\n')
;
; byte B = +A
; byte C = -A
; uword W = 43210
; A = -A
;
; c64scr.print_uw(W)
; c64.CHROUT('\n')
;
; W = W as ubyte ; TODO cast(W as ubyte) as uword -> W and 255
; c64scr.print_uw(W)
; c64.CHROUT('\n')
} }
} }