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
cmp #'0'
bmi +
cmp #'9'
cmp #':' ; one after '9'
bpl +
iny
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.
// - 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 vardeclsToAdd = mutableMapOf<INameScope, MutableList<VarDecl>>()

View File

@ -183,10 +183,8 @@ private class StatementTranslator(private val prog: IntermediateProgram,
prog.instr(Opcode.START_PROCDEF)
prog.line(subroutine.position)
// note: the caller has already written the arguments into the subroutine's parameter variables.
val (varinits, others) = subroutine.statements.partition { it is VariableInitializationAssignment }
val varInits: List<VariableInitializationAssignment> = varinits as List<VariableInitializationAssignment>
translateVarInits(varInits)
translate(others)
// note2: don't separate normal and VariableInitializationAssignment here, because the order strictly matters
translate(subroutine.statements)
val r= super.process(subroutine)
prog.instr(Opcode.END_PROCDEF)
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>) {
for (stmt: IStatement in statements) {
generatedLabelSequenceNumber++
@ -935,13 +926,13 @@ private class StatementTranslator(private val prog: IntermediateProgram,
private fun translateSubroutineCall(subroutine: Subroutine, arguments: List<IExpression>, callPosition: Position) {
// evaluate the arguments and assign them into the subroutine's argument variables.
var restoreX = Register.X in subroutine.asmClobbers
if(restoreX)
prog.instr(Opcode.RSAVEX)
if(subroutine.isAsmSubroutine) {
if(subroutine.parameters.size!=subroutine.asmParameterRegisters.size)
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)
var carryParam: Boolean? = null
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()
optimizeMultipleSequentialLineInstrs()
optimizeCallReturnIntoJump()
optimizeRestoreXYSaveXYIntoRestoreXY()
optimizeRestoreXSaveXIntoRepopX()
// todo: add more optimizations to stackvm code
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 }
}
private fun optimizeRestoreXYSaveXYIntoRestoreXY() {
// replace rrestorex/y+rsavex/y combo by only rrestorex/y
private fun optimizeRestoreXSaveXIntoRepopX() {
// replace rrestorex+rsavex combo by only repopX
for(blk in blocks) {
val instructionsToReplace = mutableMapOf<Int, Instruction>()
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) {
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
else if(it[0].value.opcode==Opcode.RRESTOREY && it[1].value.opcode==Opcode.RSAVEY) {
instructionsToReplace[it[0].index] = Instruction(Opcode.REPOPX)
instructionsToReplace[it[1].index] = Instruction(Opcode.NOP)
}
}

View File

@ -259,10 +259,9 @@ enum class Opcode {
CLI, // clear irq-disable status flag
RSAVE, // save all internal registers and status flags
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
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
BREAKPOINT, // breakpoint

View File

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

View File

@ -1486,9 +1486,8 @@ class StackVm(private var traceOutputFile: String?) {
P_irqd = evalstack.pop().asBooleanValue
}
Opcode.RSAVEX -> evalstack.push(variables["X"])
Opcode.RSAVEY -> evalstack.push(variables["Y"])
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.PUSH_ADDR_HEAPVAR -> {
val heapId = variables[ins.callLabel]!!.heapId

View File

@ -8,11 +8,6 @@
; 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 {
sub start() {
str name = "????????????????????????????????????????"
@ -39,9 +34,10 @@
c64flt.FADDH() ; add 0.5..
c64flt.FADDH() ; and again, so +1 total
A, Y = c64flt.GETADRAY()
secretnumber = A ; secret number = rnd()*100+1
secretnumber = A ; secret number = rnd()*100+1
ask_guess:
c64.STROUT("\nYou have ")
c64scr.print_ub(attempts_left)
c64.STROUT(" guess")

View File

@ -33,7 +33,7 @@
return ending(true)
} else {
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")
else
c64scr.print("high!\n")

View File

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