mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
multiplications
This commit is contained in:
parent
2a08c22b0f
commit
6fe0959fdc
@ -64,6 +64,7 @@
|
||||
memory ubyte SP7X = $d00e
|
||||
memory ubyte SP7Y = $d00f
|
||||
memory ubyte[16] SPXY = $d000 ; the 8 sprite X and Y registers as an array.
|
||||
memory uword[8] SPXYW = $d000 ; the 8 sprite X and Y registers as a combined xy word array.
|
||||
|
||||
memory ubyte MSIGX = $d010
|
||||
memory ubyte SCROLY = $d011
|
||||
|
@ -66,9 +66,9 @@ class AstIdentifiersChecker(val heap: HeapValues) : IAstProcessor {
|
||||
// lsb(...) is just an alias for type cast to ubyte, so replace with "... as ubyte"
|
||||
val typecast = TypecastExpression(functionCall.arglist.single(), DataType.UBYTE, functionCall.position)
|
||||
typecast.linkParents(functionCall.parent)
|
||||
return typecast
|
||||
return super.process(typecast)
|
||||
}
|
||||
return functionCall
|
||||
return super.process(functionCall)
|
||||
}
|
||||
|
||||
override fun process(decl: VarDecl): IStatement {
|
||||
|
@ -832,7 +832,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
else -> throw CompilerException("wrong datatype for $funcname()")
|
||||
}
|
||||
}
|
||||
"msb" -> prog.instr(Opcode.MSB) // note: LSB is not a function, it's just an alias for the cast "... as ubyte"
|
||||
"msb" -> prog.instr(Opcode.MSB) // note: "lsb" is not a function at all, it's just an alias for the cast "... as ubyte"
|
||||
"mkword" -> prog.instr(Opcode.MKWORD)
|
||||
"lsl" -> {
|
||||
val arg = args.single()
|
||||
|
@ -72,7 +72,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
for(b in program.blocks)
|
||||
block2asm(b)
|
||||
|
||||
optimizeAssembly(assemblyLines)
|
||||
var optimizationsDone=1
|
||||
while(optimizationsDone>0) {
|
||||
optimizationsDone = optimizeAssembly(assemblyLines)
|
||||
}
|
||||
|
||||
File("${program.name}.asm").printWriter().use {
|
||||
for (line in assemblyLines) { it.println(line) }
|
||||
@ -81,9 +84,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
return AssemblyProgram(program.name)
|
||||
}
|
||||
|
||||
private fun optimizeAssembly(lines: MutableList<String>) {
|
||||
private fun optimizeAssembly(lines: MutableList<String>): Int {
|
||||
// sometimes, iny+dey / inx+dex / dey+iny / dex+inx sequences are generated, these can be eliminated.
|
||||
val removeLines = mutableListOf<Int>()
|
||||
var numberOfOptimizations = 0
|
||||
for(pair in lines.withIndex().windowed(2)) {
|
||||
val first = pair[0].value
|
||||
val second = pair[1].value
|
||||
@ -97,14 +101,53 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
{
|
||||
removeLines.add(pair[0].index)
|
||||
removeLines.add(pair[1].index)
|
||||
numberOfOptimizations++
|
||||
}
|
||||
}
|
||||
|
||||
for(i in removeLines.reversed())
|
||||
lines.removeAt(i)
|
||||
removeLines.clear()
|
||||
|
||||
// sta X + lda X, sty X + ldy X, stx X + ldx X -> the second instruction can be eliminated
|
||||
for(pair in lines.withIndex().windowed(2)) {
|
||||
val first = pair[0].value.trim()
|
||||
val second = pair[1].value.trim()
|
||||
if(first.startsWith(';') || second.startsWith(';'))
|
||||
continue // skip over asm comments
|
||||
|
||||
if((first.startsWith("sta ") && second.startsWith("lda ")) ||
|
||||
(first.startsWith("stx ") && second.startsWith("ldx ")) ||
|
||||
(first.startsWith("sty ") && second.startsWith("ldy ")) ||
|
||||
(first.startsWith("lda ") && second.startsWith("lda ")) ||
|
||||
(first.startsWith("ldy ") && second.startsWith("ldy ")) ||
|
||||
(first.startsWith("ldx ") && second.startsWith("ldx ")) ||
|
||||
(first.startsWith("sta ") && second.startsWith("lda ")) ||
|
||||
(first.startsWith("sty ") && second.startsWith("ldy ")) ||
|
||||
(first.startsWith("stx ") && second.startsWith("ldx "))
|
||||
) {
|
||||
val firstLoc = first.substring(4)
|
||||
val secondLoc = second.substring(4)
|
||||
if(firstLoc==secondLoc) {
|
||||
removeLines.add(pair[1].index)
|
||||
numberOfOptimizations++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for(i in removeLines.reversed())
|
||||
lines.removeAt(i)
|
||||
removeLines.clear()
|
||||
|
||||
return numberOfOptimizations
|
||||
}
|
||||
|
||||
private fun out(str: String) {
|
||||
// TODO: line splitting should be done here instead of at outputFragment
|
||||
assemblyLines.add(str)
|
||||
}
|
||||
|
||||
private fun out(str: String) = assemblyLines.add(str)
|
||||
|
||||
private fun symname(scoped: String, block: IntermediateProgram.ProgramBlock): String {
|
||||
if(' ' in scoped)
|
||||
@ -375,6 +418,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
else {
|
||||
val withNewlines = singleAsm.replace('|', '\n')
|
||||
for (line in withNewlines.split('\n')) {
|
||||
// TODO move line splitting to out() function
|
||||
if (line.isNotEmpty()) {
|
||||
var trimmed = if (line.startsWith(' ')) "\t" + line.trim() else line.trim()
|
||||
trimmed = trimmed.replace(Regex("^\\+\\s+"), "+\t") // sanitize local label indentation
|
||||
@ -783,7 +827,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
Opcode.CAST_UB_TO_UW, Opcode.CAST_UB_TO_W -> " lda #0 | sta ${(ESTACK_HI+1).toHex()},x" // clear the msb
|
||||
Opcode.CAST_B_TO_UW, Opcode.CAST_B_TO_W -> " lda ${(ESTACK_LO+1).toHex()},x | ${signExtendA("${(ESTACK_HI+1).toHex()},x")}" // sign extend the lsb
|
||||
Opcode.MSB -> " lda ${(ESTACK_HI+1).toHex()},x | sta ${(ESTACK_LO+1).toHex()},x"
|
||||
// TODO: Opcode.MKWORD -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${(ESTACK_HI+1).toHex()},x "
|
||||
Opcode.MKWORD -> " inx | lda ${ESTACK_LO.toHex()},x | sta ${(ESTACK_HI+1).toHex()},x "
|
||||
|
||||
Opcode.ADD_UB, Opcode.ADD_B -> { // TODO inline better?
|
||||
"""
|
||||
|
@ -44,25 +44,24 @@
|
||||
|
||||
~ irq {
|
||||
|
||||
sub irq() {
|
||||
ubyte angle ; no initialization value so it keeps the previous one.
|
||||
|
||||
sub irq() {
|
||||
ubyte angle ; no initialization value so it keeps the previous one.
|
||||
c64.EXTCOL--
|
||||
|
||||
c64.EXTCOL--
|
||||
angle++
|
||||
c64.MSIGX=0
|
||||
|
||||
angle++
|
||||
c64.MSIGX=0
|
||||
for ubyte i in 7 to 0 step -1 {
|
||||
uword x = sin8u(angle*2-i*8) as uword + 50
|
||||
ubyte y = cos8u(angle*3-i*8) / 2 + 70
|
||||
c64.SPXYW[i] = mkword(lsb(x), y)
|
||||
lsl(c64.MSIGX)
|
||||
if msb(x) c64.MSIGX++
|
||||
c64.EXTCOL++
|
||||
}
|
||||
c64.EXTCOL-=7 ; @todo for memory vars, this should not become more than 2 * dec but normal sbc instead
|
||||
|
||||
for ubyte i in 14 to 0 step -2 {
|
||||
uword x = sin8u(angle*2-i*8) as uword + 50
|
||||
ubyte y = cos8u(angle*3-i*8) / 2 + 70
|
||||
c64.SPXY[i] = lsb(x)
|
||||
c64.SPXY[i+1] = y
|
||||
lsl(c64.MSIGX)
|
||||
if msb(x) c64.MSIGX++
|
||||
}
|
||||
|
||||
c64.EXTCOL++
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user