mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
various regression fixes
This commit is contained in:
parent
ee906ba82c
commit
5f2bf2b375
@ -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 -
|
||||||
|
@ -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>>()
|
||||||
|
|
||||||
|
@ -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)) {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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 = "????????????????????????????????????????"
|
||||||
@ -42,6 +37,7 @@
|
|||||||
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")
|
||||||
|
@ -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")
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user