mirror of
https://github.com/irmen/prog8.git
synced 2024-10-07 00:55:33 +00:00
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:
parent
49ea31c0a4
commit
cc96ab7a9b
@ -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 {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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")
|
||||||
|
@ -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))
|
||||||
|
@ -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))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user