mirror of
https://github.com/irmen/prog8.git
synced 2025-02-22 01:29:07 +00:00
fixed and optimized branches and gotos in if statements
This commit is contained in:
parent
209b50ddf7
commit
dd02d97db4
@ -5,13 +5,11 @@ import prog8.ast.RegisterOrPair.*
|
||||
import prog8.compiler.intermediate.IntermediateProgram
|
||||
import prog8.compiler.intermediate.Opcode
|
||||
import prog8.compiler.intermediate.Value
|
||||
import prog8.compiler.intermediate.branchOpcodes
|
||||
import prog8.optimizing.same
|
||||
import prog8.parser.tryGetEmbeddedResource
|
||||
import prog8.stackvm.Syscall
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
@ -514,10 +512,24 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
* _stmt_999_end:
|
||||
* nop
|
||||
*
|
||||
* @todo generate more efficient bytecode for the form with just jumps: if(..) goto .. [else goto ..]
|
||||
* For if statements with goto's, more efficient code is generated.
|
||||
*/
|
||||
prog.line(stmt.position)
|
||||
translate(stmt.condition)
|
||||
|
||||
val trueGoto = stmt.truepart.statements.singleOrNull() as? Jump
|
||||
if(trueGoto!=null) {
|
||||
// optimization for if (condition) goto ....
|
||||
val conditionJumpOpcode = when(stmt.condition.resultingDatatype(namespace, heap)) {
|
||||
DataType.UBYTE, DataType.BYTE -> Opcode.JNZ
|
||||
DataType.UWORD, DataType.WORD -> Opcode.JNZW
|
||||
else -> throw CompilerException("invalid condition datatype (expected byte or word) $stmt")
|
||||
}
|
||||
translate(trueGoto, conditionJumpOpcode)
|
||||
translate(stmt.elsepart)
|
||||
return
|
||||
}
|
||||
|
||||
val conditionJumpOpcode = when(stmt.condition.resultingDatatype(namespace, heap)) {
|
||||
DataType.UBYTE, DataType.BYTE -> Opcode.JZ
|
||||
DataType.UWORD, DataType.WORD -> Opcode.JZW
|
||||
@ -1388,7 +1400,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
when {
|
||||
stmt.generatedLabel!=null -> jumpLabel = stmt.generatedLabel
|
||||
stmt.address!=null -> {
|
||||
if(branchOpcode!=null)
|
||||
if(branchOpcode in branchOpcodes)
|
||||
throw CompilerException("cannot branch to address, should use absolute jump instead")
|
||||
jumpAddress = Value(DataType.UWORD, stmt.address)
|
||||
}
|
||||
|
@ -285,3 +285,8 @@ val opcodesWithVarArgument = setOf(
|
||||
Opcode.DEC_INDEXED_VAR_UB, Opcode.DEC_INDEXED_VAR_B, Opcode.DEC_INDEXED_VAR_UW,
|
||||
Opcode.DEC_INDEXED_VAR_W, Opcode.DEC_INDEXED_VAR_FLOAT
|
||||
)
|
||||
|
||||
val branchOpcodes = setOf(
|
||||
Opcode.BCS, Opcode.BCC, Opcode.BZ, Opcode.BNZ,
|
||||
Opcode.BNEG, Opcode.BPOS, Opcode.BVS, Opcode.BVC
|
||||
)
|
||||
|
@ -700,44 +700,72 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
Opcode.INV_WORD -> " jsr prog8_lib.inv_word"
|
||||
Opcode.NOT_BYTE -> " jsr prog8_lib.not_byte"
|
||||
Opcode.NOT_WORD -> " jsr prog8_lib.not_word"
|
||||
Opcode.BCS -> " bcs ${ins.callLabel}"
|
||||
Opcode.BCC -> " bcc ${ins.callLabel}"
|
||||
Opcode.BNEG -> " bmi ${ins.callLabel}"
|
||||
Opcode.BPOS -> " bpl ${ins.callLabel}"
|
||||
Opcode.BVC -> " bvc ${ins.callLabel}"
|
||||
Opcode.BVS -> " bvs ${ins.callLabel}"
|
||||
Opcode.BZ -> " beq ${ins.callLabel}"
|
||||
Opcode.BNZ -> " bne ${ins.callLabel}"
|
||||
Opcode.BCS -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bcs $label"
|
||||
}
|
||||
Opcode.BCC -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bcc $label"
|
||||
}
|
||||
Opcode.BNEG -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bmi $label"
|
||||
}
|
||||
Opcode.BPOS -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bpl $label"
|
||||
}
|
||||
Opcode.BVC -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bvc $label"
|
||||
}
|
||||
Opcode.BVS -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bvs $label"
|
||||
}
|
||||
Opcode.BZ -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" beq $label"
|
||||
}
|
||||
Opcode.BNZ -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
" bne $label"
|
||||
}
|
||||
Opcode.JZ -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
"""
|
||||
inx
|
||||
lda ${(ESTACK_LO).toHex()},x
|
||||
beq ${ins.callLabel}
|
||||
beq $label
|
||||
"""
|
||||
}
|
||||
Opcode.JZW -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
"""
|
||||
inx
|
||||
lda ${(ESTACK_LO).toHex()},x
|
||||
beq ${ins.callLabel}
|
||||
beq $label
|
||||
lda ${(ESTACK_HI).toHex()},x
|
||||
beq ${ins.callLabel}
|
||||
beq $label
|
||||
"""
|
||||
}
|
||||
Opcode.JNZ -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
"""
|
||||
inx
|
||||
lda ${(ESTACK_LO).toHex()},x
|
||||
bne ${ins.callLabel}
|
||||
bne $label
|
||||
"""
|
||||
}
|
||||
Opcode.JNZW -> {
|
||||
val label = ins.callLabel ?: hexVal(ins)
|
||||
"""
|
||||
inx
|
||||
lda ${(ESTACK_LO).toHex()},x
|
||||
bne ${ins.callLabel}
|
||||
bne $label
|
||||
lda ${(ESTACK_HI).toHex()},x
|
||||
bne ${ins.callLabel}
|
||||
bne $label
|
||||
"""
|
||||
}
|
||||
Opcode.CAST_B_TO_UB -> "" // is a no-op, just carry on with the byte as-is
|
||||
|
@ -368,7 +368,6 @@ class SimplifyExpressions(private val namespace: INameScope, private val heap: H
|
||||
}
|
||||
|
||||
|
||||
// todo: get rid of this?
|
||||
private data class ReorderedAssociativeBinaryExpr(val expr: BinaryExpression, val leftVal: LiteralValue?, val rightVal: LiteralValue?)
|
||||
|
||||
private fun reorderAssociative(expr: BinaryExpression, leftVal: LiteralValue?): ReorderedAssociativeBinaryExpr {
|
||||
|
@ -18,43 +18,4 @@ Memory Block Operations
|
||||
these should call (or emit inline) optimized pieces of assembly code, so they run as fast as possible
|
||||
|
||||
At least we have memcopy() already and some screen related routines in asm
|
||||
|
||||
|
||||
Bitmap Definition (for Sprites and Characters)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
to define CHARACTERS (8x8 monochrome or 4x8 multicolor = 8 bytes)
|
||||
--> PLACE in memory on correct address (???k aligned)
|
||||
|
||||
and SPRITES (24x21 monochrome or 12x21 multicolor = 63 bytes)
|
||||
--> PLACE in memory on correct address (base+sprite pointer, 64-byte aligned)
|
||||
--> actually not needed because a block at the correct address, and an array using 3x21 binary values, more or less does exactly this already::
|
||||
|
||||
~ spritedata $0a00 {
|
||||
; this memory block contains the sprite data
|
||||
; it must start on an address aligned to 64 bytes.
|
||||
%option force_output ; make sure the data in this block appears in the resulting program
|
||||
|
||||
ubyte[63] balloonsprite = [ %00000000,%01111111,%00000000,
|
||||
%00000001,%11111111,%11000000,
|
||||
%00000011,%11111111,%11100000,
|
||||
%00000011,%11100011,%11100000,
|
||||
%00000111,%11011100,%11110000,
|
||||
%00000111,%11011101,%11110000,
|
||||
%00000111,%11011100,%11110000,
|
||||
%00000011,%11100011,%11100000,
|
||||
%00000011,%11111111,%11100000,
|
||||
%00000011,%11111111,%11100000,
|
||||
%00000010,%11111111,%10100000,
|
||||
%00000001,%01111111,%01000000,
|
||||
%00000001,%00111110,%01000000,
|
||||
%00000000,%10011100,%10000000,
|
||||
%00000000,%10011100,%10000000,
|
||||
%00000000,%01001001,%00000000,
|
||||
%00000000,%01001001,%00000000,
|
||||
%00000000,%00111110,%00000000,
|
||||
%00000000,%00111110,%00000000,
|
||||
%00000000,%00111110,%00000000,
|
||||
%00000000,%00011100,%00000000 ]
|
||||
}
|
||||
|
||||
@todo add memset() to easily set a part of memory to a specific byte value
|
||||
|
@ -1,11 +1,33 @@
|
||||
%output raw
|
||||
%launcher none
|
||||
%import c64lib
|
||||
|
||||
|
||||
~ main {
|
||||
|
||||
sub start() {
|
||||
|
||||
; memset($0400, $0400+40, 81)
|
||||
|
||||
A=99
|
||||
if(A<99) goto first else goto second
|
||||
|
||||
first:
|
||||
c64scr.print("a<99 !\n")
|
||||
goto next
|
||||
second:
|
||||
c64scr.print("wrong: a>=99 ?!\n")
|
||||
|
||||
next:
|
||||
A=99
|
||||
if(A<99) goto first2 else {
|
||||
c64scr.print("wrong: a>=99 ?!\n")
|
||||
}
|
||||
return
|
||||
|
||||
first2:
|
||||
c64scr.print("a<99 !\n")
|
||||
|
||||
return
|
||||
|
||||
ubyte ub1
|
||||
ubyte ub2
|
||||
byte b1
|
||||
|
Loading…
x
Reference in New Issue
Block a user