mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
more efficient branch asm, and fixed jump/call asm
This commit is contained in:
parent
775cdd451c
commit
a43f81cad4
@ -17,6 +17,14 @@
|
||||
word[len(zcoor)] rotatedz=-1
|
||||
|
||||
sub start() {
|
||||
|
||||
|
||||
label1:
|
||||
label2:
|
||||
Y--
|
||||
if_mi goto label1
|
||||
if_mi goto label1 else goto label2
|
||||
|
||||
uword anglex
|
||||
uword angley
|
||||
uword anglez
|
||||
|
@ -61,15 +61,18 @@ sub irq() {
|
||||
|
||||
angle++
|
||||
c64.MSIGX=0
|
||||
for ubyte i in 0 to 14 step 2 {
|
||||
word x = (sin8(angle*2-i*8) as word)+190 ; @todo will/should be using shifts for faster multiplication
|
||||
byte y = cos8(angle*3-i*8) // 2 ; @todo will/should be using shifts for faster multiplication
|
||||
@(SP0X+i) = lsb(x)
|
||||
@(SP0Y+i) = y+150 as ubyte
|
||||
ubyte i=14
|
||||
|
||||
lsr(c64.MSIGX)
|
||||
if msb(x) c64.MSIGX |= %10000000
|
||||
}
|
||||
nextsprite: ; @todo should be a for loop from 14 to 0 step -2 but this causes a value out of range error at the moment
|
||||
word x = (sin8(angle*2-i*8) as word)+190 ; @todo will/should be using shifts for faster multiplication
|
||||
byte y = cos8(angle*3-i*8) // 2 ; @todo will/should be using shifts for faster multiplication
|
||||
@(SP0X+i) = lsb(x)
|
||||
@(SP0Y+i) = y+150 as ubyte
|
||||
|
||||
lsl(c64.MSIGX)
|
||||
if msb(x) c64.MSIGX++
|
||||
i-=2
|
||||
if_pl goto nextsprite
|
||||
|
||||
c64.EXTCOL++
|
||||
}
|
||||
|
@ -270,9 +270,9 @@ interface IAstProcessor {
|
||||
return scope
|
||||
}
|
||||
|
||||
fun process(typecastExpression: TypecastExpression): IExpression {
|
||||
typecastExpression.expression = typecastExpression.expression.process(this)
|
||||
return typecastExpression
|
||||
fun process(typecast: TypecastExpression): IExpression {
|
||||
typecast.expression = typecast.expression.process(this)
|
||||
return typecast
|
||||
}
|
||||
|
||||
fun process(memread: DirectMemoryRead): IExpression {
|
||||
@ -1934,7 +1934,7 @@ private fun prog8Parser.ReturnstmtContext.toAst() : Return {
|
||||
|
||||
private fun prog8Parser.UnconditionaljumpContext.toAst(): Jump {
|
||||
val address = integerliteral()?.toAst()?.number?.toInt()
|
||||
val identifier = scoped_identifier().toAst()
|
||||
val identifier = scoped_identifier()?.toAst()
|
||||
return Jump(address, identifier, null, toPosition())
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
is VariableInitializationAssignment -> translate(stmt) // for initializing vars in a scope
|
||||
is Assignment -> translate(stmt) // normal and augmented assignments
|
||||
is PostIncrDecr -> translate(stmt)
|
||||
is Jump -> translate(stmt)
|
||||
is Jump -> translate(stmt, null)
|
||||
is FunctionCallStatement -> translate(stmt)
|
||||
is IfStatement -> translate(stmt)
|
||||
is BranchStatement -> translate(stmt)
|
||||
@ -399,35 +399,67 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
* _stmt_999_end:
|
||||
* nop
|
||||
*
|
||||
* @todo generate more efficient bytecode for the form with just jumps: if_xx goto .. [else goto ..] ?
|
||||
* -> this should translate into just a single branch opcode per goto
|
||||
* if the branch statement just contains jumps, more efficient code is generated.
|
||||
* (just the appropriate branching instruction is outputted!)
|
||||
*/
|
||||
if(branch.elsepart.isEmpty() && branch.truepart.isEmpty())
|
||||
return
|
||||
|
||||
fun branchOpcode(branch: BranchStatement, complement: Boolean) =
|
||||
if(complement) {
|
||||
when (branch.condition) {
|
||||
BranchCondition.CS -> Opcode.BCC
|
||||
BranchCondition.CC -> Opcode.BCS
|
||||
BranchCondition.EQ, BranchCondition.Z -> Opcode.BNZ
|
||||
BranchCondition.NE, BranchCondition.NZ -> Opcode.BZ
|
||||
BranchCondition.VS -> Opcode.BVC
|
||||
BranchCondition.VC -> Opcode.BVS
|
||||
BranchCondition.MI, BranchCondition.NEG -> Opcode.BPOS
|
||||
BranchCondition.PL, BranchCondition.POS -> Opcode.BNEG
|
||||
}
|
||||
} else {
|
||||
when (branch.condition) {
|
||||
BranchCondition.CS -> Opcode.BCS
|
||||
BranchCondition.CC -> Opcode.BCC
|
||||
BranchCondition.EQ, BranchCondition.Z -> Opcode.BZ
|
||||
BranchCondition.NE, BranchCondition.NZ -> Opcode.BNZ
|
||||
BranchCondition.VS -> Opcode.BVS
|
||||
BranchCondition.VC -> Opcode.BVC
|
||||
BranchCondition.MI, BranchCondition.NEG -> Opcode.BNEG
|
||||
BranchCondition.PL, BranchCondition.POS -> Opcode.BPOS
|
||||
}
|
||||
}
|
||||
|
||||
prog.line(branch.position)
|
||||
val labelElse = makeLabel("else")
|
||||
val labelEnd = makeLabel("end")
|
||||
val opcode = when(branch.condition) {
|
||||
BranchCondition.CS -> Opcode.BCC
|
||||
BranchCondition.CC -> Opcode.BCS
|
||||
BranchCondition.EQ, BranchCondition.Z -> Opcode.BNZ
|
||||
BranchCondition.NE, BranchCondition.NZ -> Opcode.BZ
|
||||
BranchCondition.VS -> Opcode.BVC
|
||||
BranchCondition.VC -> Opcode.BVS
|
||||
BranchCondition.MI, BranchCondition.NEG -> Opcode.BPOS
|
||||
BranchCondition.PL, BranchCondition.POS -> Opcode.BNEG
|
||||
}
|
||||
if(branch.elsepart.isEmpty()) {
|
||||
prog.instr(opcode, callLabel = labelEnd)
|
||||
translate(branch.truepart)
|
||||
prog.label(labelEnd)
|
||||
val truejump = branch.truepart.statements.first()
|
||||
val elsejump = branch.elsepart.statements.firstOrNull()
|
||||
if(truejump is Jump && truejump.address==null && (elsejump ==null || (elsejump is Jump && elsejump.address==null))) {
|
||||
// optimized code for just conditional jumping
|
||||
val opcodeTrue = branchOpcode(branch, false)
|
||||
translate(truejump, opcodeTrue)
|
||||
if(elsejump is Jump) {
|
||||
val opcodeFalse = branchOpcode(branch, true)
|
||||
translate(elsejump, opcodeFalse)
|
||||
}
|
||||
} else {
|
||||
prog.instr(opcode, callLabel = labelElse)
|
||||
translate(branch.truepart)
|
||||
prog.instr(Opcode.JUMP, callLabel = labelEnd)
|
||||
prog.label(labelElse)
|
||||
translate(branch.elsepart)
|
||||
prog.label(labelEnd)
|
||||
// regular if..else branching
|
||||
val labelElse = makeLabel("else")
|
||||
val labelEnd = makeLabel("end")
|
||||
val opcode = branchOpcode(branch, true)
|
||||
if (branch.elsepart.isEmpty()) {
|
||||
prog.instr(opcode, callLabel = labelEnd)
|
||||
translate(branch.truepart)
|
||||
prog.label(labelEnd)
|
||||
} else {
|
||||
prog.instr(opcode, callLabel = labelElse)
|
||||
translate(branch.truepart)
|
||||
prog.instr(Opcode.JUMP, callLabel = labelEnd)
|
||||
prog.label(labelElse)
|
||||
translate(branch.elsepart)
|
||||
prog.label(labelEnd)
|
||||
}
|
||||
prog.instr(Opcode.NOP)
|
||||
}
|
||||
prog.instr(Opcode.NOP)
|
||||
}
|
||||
|
||||
private fun makeLabel(postfix: String): String {
|
||||
@ -1235,13 +1267,17 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
prog.instr(Opcode.SYSCALL, Value(DataType.UBYTE, callNr))
|
||||
}
|
||||
|
||||
private fun translate(stmt: Jump) {
|
||||
private fun translate(stmt: Jump, branchOpcode: Opcode?) {
|
||||
var jumpAddress: Value? = null
|
||||
var jumpLabel: String? = null
|
||||
|
||||
when {
|
||||
stmt.generatedLabel!=null -> jumpLabel = stmt.generatedLabel
|
||||
stmt.address!=null -> jumpAddress = Value(DataType.UWORD, stmt.address)
|
||||
stmt.address!=null -> {
|
||||
if(branchOpcode!=null)
|
||||
throw CompilerException("cannot branch to address, should use absolute jump instead")
|
||||
jumpAddress = Value(DataType.UWORD, stmt.address)
|
||||
}
|
||||
else -> {
|
||||
val target = stmt.identifier!!.targetStatement(namespace)!!
|
||||
jumpLabel = when(target) {
|
||||
@ -1252,7 +1288,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
|
||||
}
|
||||
}
|
||||
prog.line(stmt.position)
|
||||
prog.instr(Opcode.JUMP, jumpAddress, jumpLabel)
|
||||
prog.instr(branchOpcode ?: Opcode.JUMP, jumpAddress, jumpLabel)
|
||||
}
|
||||
|
||||
private fun translate(stmt: PostIncrDecr) {
|
||||
|
@ -414,8 +414,18 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
|
||||
Opcode.CLC -> " clc"
|
||||
Opcode.SEI -> " sei"
|
||||
Opcode.CLI -> " cli"
|
||||
Opcode.JUMP -> " jmp ${ins.callLabel}"
|
||||
Opcode.CALL -> " jsr ${ins.callLabel}"
|
||||
Opcode.JUMP -> {
|
||||
if(ins.callLabel!=null)
|
||||
" jmp ${ins.callLabel}"
|
||||
else
|
||||
" jmp ${hexVal(ins)}"
|
||||
}
|
||||
Opcode.CALL -> {
|
||||
if(ins.callLabel!=null)
|
||||
" jsr ${ins.callLabel}"
|
||||
else
|
||||
" jsr ${hexVal(ins)}"
|
||||
}
|
||||
Opcode.RETURN -> " rts"
|
||||
Opcode.RSAVE -> {
|
||||
// save cpu status flag and all registers A, X, Y.
|
||||
|
Loading…
x
Reference in New Issue
Block a user