various regression fixes

This commit is contained in:
Irmen de Jong 2019-01-16 00:28:30 +01:00
parent ee906ba82c
commit 5f2bf2b375
10 changed files with 71 additions and 55 deletions

View File

@ -259,7 +259,7 @@ _numlen
- lda (c64.SCRATCH_ZPWORD1),y - lda (c64.SCRATCH_ZPWORD1),y
cmp #'0' cmp #'0'
bmi + bmi +
cmp #'9' cmp #':' ; one after '9'
bpl + bpl +
iny iny
bne - bne -

View File

@ -14,6 +14,12 @@ class StatementReorderer(private val namespace: INameScope, private val heap: He
// - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives. // - the 'start' subroutine in the 'main' block will be moved to the top immediately following the directives.
// - all other subroutines will be moved to the end of their block. // - all other subroutines will be moved to the end of their block.
// @todo sort the VariableInitializations and normal assignments: as long as the values are constants and they follow eachother without other stmts inbetween. something like this:
// // sort by datatype and value, so multiple initializations with the same value can be optimized (to load the value just once)
// val sortedInits = varinits.sortedWith(compareBy({it.value.resultingDatatype(namespace, heap)}, {it.value.constValue(namespace, heap)?.asNumericValue?.toDouble()}))
private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option") private val directivesToMove = setOf("%output", "%launcher", "%zeropage", "%zpreserved", "%address", "%option")
private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>() private val vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()

View File

@ -183,10 +183,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.START_PROCDEF) prog.instr(Opcode.START_PROCDEF)
prog.line(subroutine.position) prog.line(subroutine.position)
// note: the caller has already written the arguments into the subroutine's parameter variables. // note: the caller has already written the arguments into the subroutine's parameter variables.
val (varinits, others) = subroutine.statements.partition { it is VariableInitializationAssignment } // note2: don't separate normal and VariableInitializationAssignment here, because the order strictly matters
val varInits: List<VariableInitializationAssignment> = varinits as List<VariableInitializationAssignment> translate(subroutine.statements)
translateVarInits(varInits)
translate(others)
val r= super.process(subroutine) val r= super.process(subroutine)
prog.instr(Opcode.END_PROCDEF) prog.instr(Opcode.END_PROCDEF)
return r return r
@ -200,13 +198,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
} }
} }
private fun translateVarInits(varinits: List<VariableInitializationAssignment>) {
// sort by datatype and value, so multiple initializations with the same value can be optimized (to load the value just once)
val sortedInits = varinits.sortedWith(compareBy({it.value.resultingDatatype(namespace, heap)}, {it.value.constValue(namespace, heap)?.asNumericValue?.toDouble()}))
for (vi in sortedInits)
translate(vi)
}
private fun translate(statements: List<IStatement>) { private fun translate(statements: List<IStatement>) {
for (stmt: IStatement in statements) { for (stmt: IStatement in statements) {
generatedLabelSequenceNumber++ generatedLabelSequenceNumber++
@ -935,13 +926,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) { private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
// evaluate the arguments and assign them into the subroutine's argument variables. // evaluate the arguments and assign them into the subroutine's argument variables.
var restoreX = Register.X in subroutine.asmClobbers var restoreX = Register.X in subroutine.asmClobbers
if(restoreX)
prog.instr(Opcode.RSAVEX)
if(subroutine.isAsmSubroutine) { if(subroutine.isAsmSubroutine) {
if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size) if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size)
throw CompilerException("no support for mix of register and non-register subroutine arguments") throw CompilerException("no support for mix of register and non-register subroutine arguments")
if(restoreX)
prog.instr(Opcode.RSAVEX)
// only register arguments (or status-flag bits) // only register arguments (or status-flag bits)
var carryParam: Boolean? = null var carryParam: Boolean? = null
for(arg in arguments.zip(subroutine.asmParameterRegisters)) { for(arg in arguments.zip(subroutine.asmParameterRegisters)) {

View File

@ -43,7 +43,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
optimizeVariableCopying() optimizeVariableCopying()
optimizeMultipleSequentialLineInstrs() optimizeMultipleSequentialLineInstrs()
optimizeCallReturnIntoJump() optimizeCallReturnIntoJump()
optimizeRestoreXYSaveXYIntoRestoreXY() optimizeRestoreXSaveXIntoRepopX()
// todo: add more optimizations to stackvm code // todo: add more optimizations to stackvm code
optimizeRemoveNops() // must be done as the last step optimizeRemoveNops() // must be done as the last step
@ -57,16 +57,14 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
blk.instructions.removeIf { it.opcode== Opcode.NOP && it !is LabelInstr } blk.instructions.removeIf { it.opcode== Opcode.NOP && it !is LabelInstr }
} }
private fun optimizeRestoreXYSaveXYIntoRestoreXY() { private fun optimizeRestoreXSaveXIntoRepopX() {
// replace rrestorex/y+rsavex/y combo by only rrestorex/y // replace rrestorex+rsavex combo by only repopX
for(blk in blocks) { for(blk in blocks) {
val instructionsToReplace = mutableMapOf<Int, Instruction>() val instructionsToReplace = mutableMapOf<Int, Instruction>()
blk.instructions.asSequence().withIndex().filter {it.value.opcode!=Opcode.LINE}.windowed(2).toList().forEach { blk.instructions.asSequence().withIndex().filter {it.value.opcode!=Opcode.LINE}.windowed(2).toList().forEach {
if(it[0].value.opcode==Opcode.RRESTOREX && it[1].value.opcode==Opcode.RSAVEX) { if(it[0].value.opcode==Opcode.RRESTOREX && it[1].value.opcode==Opcode.RSAVEX) {
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) instructionsToReplace[it[0].index] = Instruction(Opcode.REPOPX)
}
else if(it[0].value.opcode==Opcode.RRESTOREY && it[1].value.opcode==Opcode.RSAVEY) {
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP) instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
} }
} }

View File

@ -259,10 +259,9 @@ enum class Opcode {
CLI, // clear irq-disable status flag CLI, // clear irq-disable status flag
RSAVE, // save all internal registers and status flags RSAVE, // save all internal registers and status flags
RSAVEX, // save just X (the evaluation stack pointer) RSAVEX, // save just X (the evaluation stack pointer)
RSAVEY, // save just Y (used in for loops for instance)
RRESTORE, // restore all internal registers and status flags RRESTORE, // restore all internal registers and status flags
RRESTOREX, // restore just X (the evaluation stack pointer) RRESTOREX, // restore just X (the evaluation stack pointer)
RRESTOREY, // restore just Y (used in for loops for instance) REPOPX, // restore just X (the evaluation stack pointer) but store it again too (essentially not erasing the value that's saved on the stack)
NOP, // do nothing NOP, // do nothing
BREAKPOINT, // breakpoint BREAKPOINT, // breakpoint

View File

@ -479,10 +479,9 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
// restore all registers and cpu status flag // restore all registers and cpu status flag
" pla | tay | pla | tax | pla | plp" " pla | tay | pla | tax | pla | plp"
} }
Opcode.RSAVEX -> " txa | pha" Opcode.RSAVEX -> " sta ${C64Zeropage.SCRATCH_REG} | txa | pha | lda ${C64Zeropage.SCRATCH_REG}"
Opcode.RRESTOREX -> " pla | tax" Opcode.RRESTOREX -> " sta ${C64Zeropage.SCRATCH_REG} | pla | tax | lda ${C64Zeropage.SCRATCH_REG}"
Opcode.RSAVEY -> " tya | pha" Opcode.REPOPX -> " sta ${C64Zeropage.SCRATCH_REG} | pla | tax | pha | lda ${C64Zeropage.SCRATCH_REG}"
Opcode.RRESTOREY -> " pla | tay"
Opcode.DISCARD_BYTE -> " inx" Opcode.DISCARD_BYTE -> " inx"
Opcode.DISCARD_WORD -> " inx" Opcode.DISCARD_WORD -> " inx"
Opcode.DISCARD_FLOAT -> " inx | inx | inx" Opcode.DISCARD_FLOAT -> " inx | inx | inx"

View File

@ -1486,9 +1486,8 @@ class StackVm(private var traceOutputFile: String?) {
P_irqd = evalstack.pop().asBooleanValue P_irqd = evalstack.pop().asBooleanValue
} }
Opcode.RSAVEX -> evalstack.push(variables["X"]) Opcode.RSAVEX -> evalstack.push(variables["X"])
Opcode.RSAVEY -> evalstack.push(variables["Y"])
Opcode.RRESTOREX -> variables["X"] = evalstack.pop() Opcode.RRESTOREX -> variables["X"] = evalstack.pop()
Opcode.RRESTOREY -> variables["Y"] = evalstack.pop() Opcode.REPOPX -> variables["X"] = evalstack.peek()
Opcode.INLINE_ASSEMBLY -> throw VmExecutionException("stackVm doesn't support executing inline assembly code") Opcode.INLINE_ASSEMBLY -> throw VmExecutionException("stackVm doesn't support executing inline assembly code")
Opcode.PUSH_ADDR_HEAPVAR -> { Opcode.PUSH_ADDR_HEAPVAR -> {
val heapId = variables[ins.callLabel]!!.heapId val heapId = variables[ins.callLabel]!!.heapId

View File

@ -8,11 +8,6 @@
; It's less readable I think, but produces a smaller program. ; It's less readable I think, but produces a smaller program.
; @todo doesn't work correctly any longer and locks up at the end. Something seems broken in the if statements comparing the numbers.
~ main { ~ main {
sub start() { sub start() {
str name = "????????????????????????????????????????" str name = "????????????????????????????????????????"
@ -39,9 +34,10 @@
c64flt.FADDH() ; add 0.5.. c64flt.FADDH() ; add 0.5..
c64flt.FADDH() ; and again, so +1 total c64flt.FADDH() ; and again, so +1 total
A, Y = c64flt.GETADRAY() A, Y = c64flt.GETADRAY()
secretnumber = A ; secret number = rnd()*100+1 secretnumber = A ; secret number = rnd()*100+1
ask_guess: ask_guess:
c64.STROUT("\nYou have ") c64.STROUT("\nYou have ")
c64scr.print_ub(attempts_left) c64scr.print_ub(attempts_left)
c64.STROUT(" guess") c64.STROUT(" guess")

View File

@ -33,7 +33,7 @@
return ending(true) return ending(true)
} else { } else {
c64scr.print("\n\nThat is too ") c64scr.print("\n\nThat is too ")
if guess<secretnumber ; @todo not correct anymore, entering '19' says too low while the number is 18 if guess<secretnumber
c64scr.print("low!\n") c64scr.print("low!\n")
else else
c64scr.print("high!\n") c64scr.print("high!\n")

View File

@ -5,36 +5,59 @@
sub start() { sub start() {
; c64scr.print_ub(c64utils.str2ubyte("1"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("12"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("123"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("1234"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("12xyz"))
; c64.CHROUT('\n')
; c64.CHROUT('\n')
;
; c64scr.print_ub(c64utils.str2ubyte("19"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("199"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("29"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("99xyz"))
; c64.CHROUT('\n')
; c64scr.print_ub(c64utils.str2ubyte("199xyz"))
; c64.CHROUT('\n')
; c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2ubyte("1")) c64scr.print_b(c64utils.str2byte("1"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2ubyte("12")) c64scr.print_b(c64utils.str2byte("12"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2ubyte("123")) c64scr.print_b(c64utils.str2byte("123"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2ubyte("1234")) c64scr.print_b(c64utils.str2byte("1234"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2ubyte("12xyz")) c64scr.print_b(c64utils.str2ubyte("12xyz"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2byte("1")) c64scr.print_b(c64utils.str2byte("19"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2byte("12")) c64scr.print_b(c64utils.str2byte("29"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2byte("123")) c64scr.print_b(c64utils.str2byte("199"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2byte("1234")) c64scr.print_b(c64utils.str2byte("299"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_ub(c64utils.str2ubyte("12xyz")) c64scr.print_b(c64utils.str2ubyte("99zzxyz"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_b(c64utils.str2byte("-1")) c64scr.print_b(c64utils.str2byte("-9"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_b(c64utils.str2byte("-12")) c64scr.print_b(c64utils.str2byte("-99"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_b(c64utils.str2byte("-123")) c64scr.print_b(c64utils.str2byte("-199"))
c64.CHROUT('\n') c64.CHROUT('\n')
c64scr.print_b(c64utils.str2byte("-1111")) c64scr.print_b(c64utils.str2byte("-1111"))
c64.CHROUT('\n') c64.CHROUT('\n')
@ -42,5 +65,10 @@
c64.CHROUT('\n') c64.CHROUT('\n')
} }
sub foo(ubyte param1, ubyte param2) {
ubyte local1
}
} }