mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +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()} }
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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 {
|
||||
return if(identifier.memberOfStruct(program.namespace)!=null) {
|
||||
val name = identifier.targetVarDecl(program.namespace)!!.name
|
||||
@ -1442,5 +1448,4 @@ $label nop""")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||
private val variableAsmName: String? = null,
|
||||
val array: ArrayIndexedExpression? = null,
|
||||
val memory: DirectMemoryRead? = null,
|
||||
val register: CpuRegister? = null,
|
||||
val register: RegisterOrPair? = null,
|
||||
val number: NumericLiteralValue? = 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 IdentifierReference -> {
|
||||
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 -> {
|
||||
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 -> {
|
||||
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 -> {
|
||||
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.AY -> asmgen.out(" sta ${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 -> {
|
||||
@ -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.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")
|
||||
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 {
|
||||
when(regs) {
|
||||
RegisterOrPair.AX -> asmgen.out(" pha | txa | pha")
|
||||
RegisterOrPair.AY -> asmgen.out(" pha | tya | pha")
|
||||
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("""
|
||||
pla
|
||||
sta ${target.asmVarname},y
|
||||
dey
|
||||
pla
|
||||
sta ${target.asmVarname},y""")
|
||||
if (regs !in Cx16VirtualRegisters) {
|
||||
when (regs) {
|
||||
RegisterOrPair.AX -> asmgen.out(" pha | txa | pha")
|
||||
RegisterOrPair.AY -> asmgen.out(" pha | tya | pha")
|
||||
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("""
|
||||
pla
|
||||
sta ${target.asmVarname},y
|
||||
dey
|
||||
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 -> {
|
||||
when(regs) {
|
||||
@ -1475,7 +1506,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
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 -> { }
|
||||
@ -1487,7 +1518,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
||||
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.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
|
||||
""")
|
||||
}
|
||||
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 -> {
|
||||
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")
|
||||
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")
|
||||
|
@ -2,6 +2,7 @@
|
||||
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)
|
||||
- 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))
|
||||
|
@ -5,27 +5,16 @@
|
||||
|
||||
main {
|
||||
|
||||
|
||||
sub start() {
|
||||
uword screencolorRGB
|
||||
uword drawcolorRGB
|
||||
ubyte ll
|
||||
ubyte hh
|
||||
ubyte lower2_x_bits=1
|
||||
ubyte cbits4
|
||||
ubyte operand
|
||||
|
||||
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 |= colorbits[lower2_x_bits] ; TODO why lda..ora instead of ora 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?
|
||||
|
||||
; 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