assignment source now also treats cx16.r[0-15] as registers

no longer create useless assignment code for r0=r0
This commit is contained in:
Irmen de Jong 2021-02-06 13:01:45 +01:00
parent 49ea31c0a4
commit cc96ab7a9b
6 changed files with 108 additions and 43 deletions

View File

@ -91,6 +91,13 @@ enum class RegisterOrPair {
val names by lazy { values().map { it.toString()} } val names by lazy { values().map { it.toString()} }
} }
fun asCpuRegister(): CpuRegister = when(this) {
A -> CpuRegister.A
X -> CpuRegister.X
Y -> CpuRegister.Y
else -> throw IllegalArgumentException("no cpu hardware register for $this")
}
} // only used in parameter and return value specs in asm subroutines } // only used in parameter and return value specs in asm subroutines
enum class Statusflag { enum class Statusflag {

View File

@ -506,6 +506,12 @@ internal class AsmGen(private val program: Program,
} }
} }
internal fun asmSymbolName(regs: RegisterOrPair): String =
if(regs in Cx16VirtualRegisters)
"cx16." + regs.toString().toLowerCase()
else
throw AssemblyError("no symbol name for register $regs")
internal fun asmVariableName(identifier: IdentifierReference): String { internal fun asmVariableName(identifier: IdentifierReference): String {
return if(identifier.memberOfStruct(program.namespace)!=null) { return if(identifier.memberOfStruct(program.namespace)!=null) {
val name = identifier.targetVarDecl(program.namespace)!!.name val name = identifier.targetVarDecl(program.namespace)!!.name
@ -1442,5 +1448,4 @@ $label nop""")
} }
return false return false
} }
} }

View File

@ -104,7 +104,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
private val variableAsmName: String? = null, private val variableAsmName: String? = null,
val array: ArrayIndexedExpression? = null, val array: ArrayIndexedExpression? = null,
val memory: DirectMemoryRead? = null, val memory: DirectMemoryRead? = null,
val register: CpuRegister? = null, val register: RegisterOrPair? = null,
val number: NumericLiteralValue? = null, val number: NumericLiteralValue? = null,
val expression: Expression? = null val expression: Expression? = null
) )
@ -138,7 +138,15 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation") is ArrayLiteralValue -> throw AssemblyError("array literal value should not occur anymore for asm generation")
is IdentifierReference -> { is IdentifierReference -> {
val dt = value.inferType(program).typeOrElse(DataType.STRUCT) val dt = value.inferType(program).typeOrElse(DataType.STRUCT)
AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, dt, variableAsmName = asmgen.asmVariableName(value)) val varName=asmgen.asmVariableName(value)
// special case: "cx16.r[0-15]" are 16-bits virtual registers of the commander X16 system
if(dt==DataType.UWORD && varName.toLowerCase().startsWith("cx16.r")) {
val regStr = varName.toLowerCase().substring(5)
val reg = RegisterOrPair.valueOf(regStr.toUpperCase())
AsmAssignSource(SourceStorageKind.REGISTER, program, asmgen, dt, register = reg)
} else {
AsmAssignSource(SourceStorageKind.VARIABLE, program, asmgen, dt, variableAsmName = varName)
}
} }
is DirectMemoryRead -> { is DirectMemoryRead -> {
AsmAssignSource(SourceStorageKind.MEMORY, program, asmgen, DataType.UBYTE, memory = value) AsmAssignSource(SourceStorageKind.MEMORY, program, asmgen, DataType.UBYTE, memory = value)

View File

@ -263,7 +263,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
} }
SourceStorageKind.REGISTER -> { SourceStorageKind.REGISTER -> {
assignRegisterByte(assign.target, assign.source.register!!) when(assign.source.datatype) {
DataType.UBYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister())
DataType.UWORD -> assignRegisterpairWord(assign.target, assign.source.register!!)
else -> throw AssemblyError("invalid register dt")
}
} }
SourceStorageKind.STACK -> { SourceStorageKind.STACK -> {
assignStackValue(assign.target) assignStackValue(assign.target)
@ -1434,7 +1438,15 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname} | stx ${target.asmVarname}+1") RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname} | stx ${target.asmVarname}+1")
RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname} | sty ${target.asmVarname}+1") RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname} | sty ${target.asmVarname}+1")
RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname} | sty ${target.asmVarname}+1") RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname} | sty ${target.asmVarname}+1")
else -> throw AssemblyError("expected reg pair") in Cx16VirtualRegisters -> {
val srcReg = asmgen.asmSymbolName(regs)
asmgen.out("""
lda $srcReg
sta ${target.asmVarname}
lda $srcReg+1
sta ${target.asmVarname}+1""")
}
else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
} }
TargetStorageKind.ARRAY -> { TargetStorageKind.ARRAY -> {
@ -1444,24 +1456,43 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname}+$idx | stx ${target.asmVarname}+$idx+1") RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname}+$idx | stx ${target.asmVarname}+$idx+1")
RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1")
RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1") RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname}+$idx | sty ${target.asmVarname}+$idx+1")
else -> throw AssemblyError("expected reg pair") in Cx16VirtualRegisters -> {
val srcReg = asmgen.asmSymbolName(regs)
asmgen.out("""
lda $srcReg
sta ${target.asmVarname}+$idx
lda $srcReg+1
sta ${target.asmVarname}+$idx+1""")
}
else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
} }
else { else {
when(regs) { if (regs !in Cx16VirtualRegisters) {
RegisterOrPair.AX -> asmgen.out(" pha | txa | pha") when (regs) {
RegisterOrPair.AY -> asmgen.out(" pha | tya | pha") RegisterOrPair.AX -> asmgen.out(" pha | txa | pha")
RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha") RegisterOrPair.AY -> asmgen.out(" pha | tya | pha")
else -> throw AssemblyError("expected reg pair") RegisterOrPair.XY -> asmgen.out(" txa | pha | tya | pha")
} else -> throw AssemblyError("expected reg pair")
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true) }
asmgen.out(""" asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true)
pla asmgen.out("""
sta ${target.asmVarname},y pla
dey sta ${target.asmVarname},y
pla dey
sta ${target.asmVarname},y""") pla
sta ${target.asmVarname},y""")
} else {
val srcReg = asmgen.asmSymbolName(regs)
asmgen.loadScaledArrayIndexIntoRegister(target.array!!, DataType.UWORD, CpuRegister.Y, true)
asmgen.out("""
lda $srcReg+1
sta ${target.asmVarname},y
dey
lda $srcReg
sta ${target.asmVarname},y""")
} }
}
} }
TargetStorageKind.REGISTER -> { TargetStorageKind.REGISTER -> {
when(regs) { when(regs) {
@ -1475,7 +1506,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
stx cx16.${target.register.toString().toLowerCase()}+1 stx cx16.${target.register.toString().toLowerCase()}+1
""") """)
} }
else -> throw AssemblyError("expected reg pair") else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
RegisterOrPair.AY -> when(target.register!!) { RegisterOrPair.AY -> when(target.register!!) {
RegisterOrPair.AY -> { } RegisterOrPair.AY -> { }
@ -1487,7 +1518,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
sty cx16.${target.register.toString().toLowerCase()}+1 sty cx16.${target.register.toString().toLowerCase()}+1
""") """)
} }
else -> throw AssemblyError("expected reg pair") else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
RegisterOrPair.XY -> when(target.register!!) { RegisterOrPair.XY -> when(target.register!!) {
RegisterOrPair.AY -> { asmgen.out(" txa") } RegisterOrPair.AY -> { asmgen.out(" txa") }
@ -1499,16 +1530,40 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
sty cx16.${target.register.toString().toLowerCase()}+1 sty cx16.${target.register.toString().toLowerCase()}+1
""") """)
} }
else -> throw AssemblyError("expected reg pair") else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
else -> throw AssemblyError("expected reg pair") in Cx16VirtualRegisters -> {
val srcReg = asmgen.asmSymbolName(regs)
if(regs!=target.register) {
when(target.register) {
RegisterOrPair.AX -> asmgen.out(" lda $srcReg | ldx $srcReg+1")
RegisterOrPair.AY -> asmgen.out(" lda $srcReg | ldy $srcReg+1")
RegisterOrPair.XY -> asmgen.out(" ldx $srcReg | ldy $srcReg+1")
in Cx16VirtualRegisters -> {
val targetReg = asmgen.asmSymbolName(target.register!!)
asmgen.out(" lda $srcReg | sta $targetReg | lda $srcReg+1 | sta $targetReg+1")
}
else -> throw AssemblyError("invalid reg")
}
}
}
else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
} }
TargetStorageKind.STACK -> { TargetStorageKind.STACK -> {
when(regs) { when(regs) {
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | sty P8ESTACK_HI,x | dex") RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | sty P8ESTACK_HI,x | dex")
RegisterOrPair.AX, RegisterOrPair.XY -> throw AssemblyError("can't use X here") RegisterOrPair.AX, RegisterOrPair.XY -> throw AssemblyError("can't use X here")
else -> throw AssemblyError("expected reg pair") in Cx16VirtualRegisters -> {
val srcReg = asmgen.asmSymbolName(regs)
asmgen.out("""
lda $srcReg
sta P8ESTACK_LO,x
lda $srcReg+1
sta P8ESTACK_HI,x
dex""")
}
else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
} }
} }
TargetStorageKind.MEMORY -> throw AssemblyError("can't store word into memory byte") TargetStorageKind.MEMORY -> throw AssemblyError("can't store word into memory byte")

View File

@ -2,6 +2,7 @@
TODO TODO
==== ====
- refactor the project module structure: make the static ast stuff a separate module, the optimizers another one, etc.
- optimize for loop iterations better to allow proper inx, cpx #value, bne loop instructions (like repeat loop) - optimize for loop iterations better to allow proper inx, cpx #value, bne loop instructions (like repeat loop)
- implement the linked_list millfork benchmark - implement the linked_list millfork benchmark
- optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2)) - optimize swap of two memread values with index, using the same pointer expression/variable, like swap(@(ptr+1), @(ptr+2))

View File

@ -5,27 +5,16 @@
main { main {
sub start() { sub start() {
uword screencolorRGB ubyte lower2_x_bits=1
uword drawcolorRGB ubyte cbits4
ubyte ll ubyte operand
ubyte hh
cx16.vpoke(1, mkword(hh, ll), lsb(screencolorRGB)) cbits4 &= operand
cbits4 |= operand
cx16.vpoke(lsb(cx16.r1), cx16.r0, cbits4) ; TODO r0 is alreay in r0, avoid bogus assignment here ;cbits4 &= gfx2.plot.mask4c[lower2_x_bits] ; TODO why lda..and instead of and mask,y?
cbits4 &= gfx2.plot.mask4c[lower2_x_bits] ; TODO why lda..and instead of and mask,y? ;cbits4 |= colorbits[lower2_x_bits] ; TODO why lda..ora instead of ora mask,y?
cbits4 |= colorbits[lower2_x_bits] ; TODO why lda..ora instead of ora mask,y?
; ubyte value
; ubyte bb1
;
; value = cx16.vpeek(lsb(cx16.r0), mkword(value, bb1))
; value = cx16.vpeek(lsb(cx16.r0), mkword(value, bb1))
;
; ubyte lx = lsb(cx16.r0)
; value = cx16.vpeek(lx, mkword(value, bb1))
; value = cx16.vpeek(lx, mkword(value, bb1))
} }
} }