mirror of
https://github.com/irmen/prog8.git
synced 2025-04-12 03:37:11 +00:00
goto can now accept any expression as address (instead of just a constant), and ofcourse a label name still.
This commit is contained in:
parent
cc59069876
commit
9e8cc8b54d
@ -608,8 +608,9 @@ class AsmGen6502Internal (
|
||||
}
|
||||
is PtAugmentedAssign -> assignmentAsmGen.translate(stmt)
|
||||
is PtJump -> {
|
||||
val (asmLabel, indirect) = getJumpTarget(stmt)
|
||||
jmp(asmLabel, indirect)
|
||||
val target = getJumpTarget(stmt)
|
||||
require(!target.needsExpressionEvaluation)
|
||||
jmp(target.asmLabel, target.indirect)
|
||||
}
|
||||
is PtLabel -> translate(stmt)
|
||||
is PtConditionalBranch -> translate(stmt)
|
||||
@ -1003,16 +1004,17 @@ $repeatLabel""")
|
||||
if(jump!=null) {
|
||||
// branch with only a jump (goto)
|
||||
val instruction = branchInstruction(stmt.condition, false)
|
||||
val (asmLabel, indirect) = getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
val target = getJumpTarget(jump)
|
||||
require(!target.needsExpressionEvaluation)
|
||||
if(target.indirect) {
|
||||
val complementedInstruction = branchInstruction(stmt.condition, true)
|
||||
out("""
|
||||
$complementedInstruction +
|
||||
jmp ($asmLabel)
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
}
|
||||
else {
|
||||
out(" $instruction $asmLabel")
|
||||
out(" $instruction ${target.asmLabel}")
|
||||
}
|
||||
translate(stmt.falseScope)
|
||||
} else {
|
||||
@ -1038,19 +1040,30 @@ $repeatLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getJumpTarget(jump: PtJump): Pair<String, Boolean> {
|
||||
class JumpTarget(val asmLabel: String, val indirect: Boolean, val needsExpressionEvaluation: Boolean)
|
||||
|
||||
internal fun getJumpTarget(jump: PtJump, evaluateAddressExpression: Boolean = true): JumpTarget {
|
||||
val ident = jump.target as? PtIdentifier
|
||||
if(ident!=null) {
|
||||
// can be a label, or a pointer variable
|
||||
val symbol = symbolTable.lookup(ident.name)
|
||||
return if(symbol?.type in arrayOf(StNodeType.STATICVAR, StNodeType.MEMVAR, StNodeType.CONSTANT))
|
||||
Pair(asmSymbolName(ident), true) // indirect jump if the jump symbol is a variable
|
||||
JumpTarget(asmSymbolName(ident), true, false) // indirect jump if the jump symbol is a variable
|
||||
else
|
||||
Pair(asmSymbolName(ident), false)
|
||||
JumpTarget(asmSymbolName(ident), false, false)
|
||||
}
|
||||
val addr = jump.target.asConstInteger()
|
||||
if(addr!=null) return Pair(addr.toHex(), false)
|
||||
else TODO("GOTO TARGET ${jump.target}")
|
||||
if(addr!=null)
|
||||
return JumpTarget(addr.toHex(), false, false)
|
||||
else {
|
||||
if(evaluateAddressExpression) {
|
||||
// we can do the address evaluation right now and just use a temporary pointer variable
|
||||
assignExpressionToVariable(jump.target, "P8ZP_SCRATCH_W1", DataType.forDt(BaseDataType.UWORD))
|
||||
return JumpTarget("P8ZP_SCRATCH_W1", true, false)
|
||||
} else {
|
||||
return JumpTarget("PROG8_JUMP_TARGET_IS_UNEVALUATED_ADDRESS_EXPRESSION", true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun translate(ret: PtReturn) {
|
||||
|
@ -83,25 +83,27 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
asmgen.out(" bit ${variable.name}")
|
||||
if(testForBitSet) {
|
||||
if(jumpAfterIf!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect)
|
||||
val target = asmgen.getJumpTarget(jumpAfterIf)
|
||||
require(!target.needsExpressionEvaluation)
|
||||
if(target.indirect)
|
||||
throw AssemblyError("cannot BIT to indirect label ${ifElse.position}")
|
||||
if(ifElse.hasElse())
|
||||
throw AssemblyError("didn't expect else part here ${ifElse.position}")
|
||||
else
|
||||
asmgen.out(" bmi $asmLabel")
|
||||
asmgen.out(" bmi ${target.asmLabel}")
|
||||
}
|
||||
else
|
||||
translateIfElseBodies("bpl", ifElse)
|
||||
} else {
|
||||
if(jumpAfterIf!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect)
|
||||
val target = asmgen.getJumpTarget(jumpAfterIf)
|
||||
require(!target.needsExpressionEvaluation)
|
||||
if(target.indirect)
|
||||
throw AssemblyError("cannot BIT to indirect label ${ifElse.position}")
|
||||
if(ifElse.hasElse())
|
||||
throw AssemblyError("didn't expect else part here ${ifElse.position}")
|
||||
else
|
||||
asmgen.out(" bpl $asmLabel")
|
||||
asmgen.out(" bpl ${target.asmLabel}")
|
||||
}
|
||||
else
|
||||
translateIfElseBodies("bmi", ifElse)
|
||||
@ -113,25 +115,27 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
asmgen.out(" bit ${variable.name}")
|
||||
if(testForBitSet) {
|
||||
if(jumpAfterIf!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect)
|
||||
val target = asmgen.getJumpTarget(jumpAfterIf)
|
||||
require(!target.needsExpressionEvaluation)
|
||||
if(target.indirect)
|
||||
throw AssemblyError("cannot BIT to indirect label ${ifElse.position}")
|
||||
if(ifElse.hasElse())
|
||||
throw AssemblyError("didn't expect else part here ${ifElse.position}")
|
||||
else
|
||||
asmgen.out(" bvs $asmLabel")
|
||||
asmgen.out(" bvs ${target.asmLabel}")
|
||||
}
|
||||
else
|
||||
translateIfElseBodies("bvc", ifElse)
|
||||
} else {
|
||||
if(jumpAfterIf!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect)
|
||||
val target = asmgen.getJumpTarget(jumpAfterIf)
|
||||
require(!target.needsExpressionEvaluation)
|
||||
if(target.indirect)
|
||||
throw AssemblyError("cannot BIT to indirect label ${ifElse.position}")
|
||||
if(ifElse.hasElse())
|
||||
throw AssemblyError("didn't expect else part here ${ifElse.position}")
|
||||
else
|
||||
asmgen.out(" bvc $asmLabel")
|
||||
asmgen.out(" bvc ${target.asmLabel}")
|
||||
}
|
||||
else
|
||||
translateIfElseBodies("bvs", ifElse)
|
||||
@ -171,14 +175,17 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
|
||||
private fun translateJumpElseBodies(branchInstr: String, falseBranch: String, jump: PtJump, elseBlock: PtNodeGroup) {
|
||||
// comparison value is already in A
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out(" $falseBranch +")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
$falseBranch +
|
||||
jmp ($asmLabel)
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
asmgen.out(" $branchInstr $asmLabel")
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out(" $branchInstr ${target.asmLabel}")
|
||||
}
|
||||
asmgen.translate(elseBlock)
|
||||
}
|
||||
@ -283,17 +290,19 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
">" -> {
|
||||
if(signed) {
|
||||
return if (jumpAfterIf != null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jumpAfterIf, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out(" bmi + | beq +")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jumpAfterIf, true)
|
||||
asmgen.out("""
|
||||
bmi +
|
||||
beq +
|
||||
jmp ($asmLabel)
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
beq +
|
||||
bpl $asmLabel
|
||||
bpl ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -348,17 +357,19 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
if(signed) {
|
||||
// inverted '>'
|
||||
return if (jumpAfterIf != null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jumpAfterIf, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out(" bmi + | bne ++")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jumpAfterIf, true)
|
||||
asmgen.out("""
|
||||
bmi +
|
||||
bne ++
|
||||
+ jmp ($asmLabel)
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
bmi $asmLabel
|
||||
beq $asmLabel""")
|
||||
bmi ${target.asmLabel}
|
||||
beq ${target.asmLabel}""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
}
|
||||
@ -427,17 +438,19 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
asmgen.assignExpressionToRegister(condition.left, RegisterOrPair.A, false)
|
||||
asmgen.cmpAwithByteValue(condition.right, false)
|
||||
if(jumpAfterIf!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jumpAfterIf)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jumpAfterIf, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out(" bcc + | beq +")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jumpAfterIf, true)
|
||||
asmgen.out("""
|
||||
bcc +
|
||||
beq +
|
||||
jmp ($asmLabel)
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
beq +
|
||||
bcs $asmLabel
|
||||
bcs ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -520,25 +533,29 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
if(signed) {
|
||||
// word < X
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bvc +
|
||||
eor #128
|
||||
+ bpl +
|
||||
jmp ($asmLabel)
|
||||
+ bpl +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bvc +
|
||||
eor #128
|
||||
+ bmi $asmLabel""")
|
||||
+ bmi ${target.asmLabel}""")
|
||||
}
|
||||
} else {
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
@ -572,23 +589,27 @@ internal class IfElseAsmGen(private val program: PtProgram,
|
||||
} else {
|
||||
// uword < X
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cpy $valueMsb
|
||||
bcc _jump
|
||||
+ bne +
|
||||
cmp $valueLsb
|
||||
bcs +
|
||||
_jump jmp ($asmLabel)
|
||||
bcs +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
_jump jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cpy $valueMsb
|
||||
bcc $asmLabel
|
||||
bcc ${target.asmLabel}
|
||||
bne +
|
||||
cmp $valueLsb
|
||||
bcc $asmLabel
|
||||
bcc ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
} else {
|
||||
@ -644,25 +665,29 @@ _jump jmp ($asmLabel)
|
||||
if(signed) {
|
||||
// word >= X
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bvs +
|
||||
eor #128
|
||||
+ bpl +
|
||||
jmp ($asmLabel)
|
||||
+ bpl +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bvs +
|
||||
eor #128
|
||||
+ bmi $asmLabel""")
|
||||
+ bmi ${target.asmLabel}""")
|
||||
}
|
||||
} else {
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
@ -696,21 +721,25 @@ _jump jmp ($asmLabel)
|
||||
} else {
|
||||
// uword >= X
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bcc +
|
||||
jmp ($asmLabel)
|
||||
bcc +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
tya
|
||||
sbc $valueMsb
|
||||
bcs $asmLabel""")
|
||||
bcs ${target.asmLabel}""")
|
||||
}
|
||||
} else {
|
||||
val afterIfLabel = asmgen.makeLabel("afterif")
|
||||
@ -795,23 +824,27 @@ _jump jmp ($asmLabel)
|
||||
|
||||
fun compareLsbMsb(valueLsb: String, valueMsb: String) {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
lda $valueMsb
|
||||
bmi +
|
||||
bne ++
|
||||
lda $valueLsb
|
||||
bne ++
|
||||
+ jmp ($asmLabel)
|
||||
bne ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
lda $valueMsb
|
||||
bmi $asmLabel
|
||||
bmi ${target.asmLabel}
|
||||
bne +
|
||||
lda $valueLsb
|
||||
beq $asmLabel
|
||||
beq ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -870,23 +903,27 @@ _jump jmp ($asmLabel)
|
||||
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cpy #0
|
||||
bmi +
|
||||
bne ++
|
||||
cmp #0
|
||||
bne ++
|
||||
+ jmp ($asmLabel)
|
||||
bne ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cpy #0
|
||||
bmi $asmLabel
|
||||
bmi ${target.asmLabel}
|
||||
bne +
|
||||
cmp #0
|
||||
beq $asmLabel
|
||||
beq ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -931,23 +968,27 @@ _jump jmp ($asmLabel)
|
||||
|
||||
fun compareLsbMsb(valueLsb: String, valueMsb: String) {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
lda $valueMsb
|
||||
bmi ++
|
||||
bne +
|
||||
lda $valueLsb
|
||||
beq ++
|
||||
+ jmp ($asmLabel)
|
||||
beq ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
lda $valueMsb
|
||||
bmi +
|
||||
bne $asmLabel
|
||||
bne ${target.asmLabel}
|
||||
lda $valueLsb
|
||||
bne $asmLabel
|
||||
bne ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -1007,23 +1048,27 @@ _jump jmp ($asmLabel)
|
||||
|
||||
asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true)
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cpy #0
|
||||
bmi ++
|
||||
bne +
|
||||
cmp #0
|
||||
beq ++
|
||||
+ jmp ($asmLabel)
|
||||
cpy #0
|
||||
bmi ++
|
||||
bne +
|
||||
cmp #0
|
||||
beq ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cpy #0
|
||||
bmi +
|
||||
bne $asmLabel
|
||||
cmp #0
|
||||
bne $asmLabel
|
||||
cpy #0
|
||||
bmi +
|
||||
bne ${target.asmLabel}
|
||||
cmp #0
|
||||
bne ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -1147,21 +1192,25 @@ _jump jmp ($asmLabel)
|
||||
|
||||
fun translateAYNotEquals(valueLsb: String, valueMsb: String) {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
bne +
|
||||
cpy $valueMsb
|
||||
beq ++
|
||||
+ jmp ($asmLabel)
|
||||
beq ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
bne $asmLabel
|
||||
bne ${target.asmLabel}
|
||||
cpy $valueMsb
|
||||
bne $asmLabel""")
|
||||
bne ${target.asmLabel}""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
@ -1195,21 +1244,25 @@ _jump jmp ($asmLabel)
|
||||
|
||||
fun translateAYEquals(valueLsb: String, valueMsb: String) {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
bne +
|
||||
cpy $valueMsb
|
||||
bne +
|
||||
jmp ($asmLabel)
|
||||
bne +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
cmp $valueLsb
|
||||
bne +
|
||||
cpy $valueMsb
|
||||
beq $asmLabel
|
||||
beq ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -1243,25 +1296,29 @@ _jump jmp ($asmLabel)
|
||||
fun translateEqualsVarVar(left: PtIdentifier, right: PtIdentifier) {
|
||||
if(notEquals) {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp ${right.name}
|
||||
bne +
|
||||
lda ${left.name}+1
|
||||
cmp ${right.name}+1
|
||||
beq ++
|
||||
+ jmp ($asmLabel)
|
||||
beq ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp ${right.name}
|
||||
bne $asmLabel
|
||||
bne ${target.asmLabel}
|
||||
lda ${left.name}+1
|
||||
cmp ${right.name}+1
|
||||
bne $asmLabel""")
|
||||
bne ${target.asmLabel}""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
@ -1298,25 +1355,29 @@ _jump jmp ($asmLabel)
|
||||
} else {
|
||||
// XXX translateAYEquals(right.name, right.name + "+1")
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp ${right.name}
|
||||
bne +
|
||||
lda ${left.name}+1
|
||||
cmp ${right.name}+1
|
||||
bne +
|
||||
jmp ($asmLabel)
|
||||
bne +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp ${right.name}
|
||||
bne +
|
||||
lda ${left.name}+1
|
||||
cmp ${right.name}+1
|
||||
beq $asmLabel
|
||||
beq ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
@ -1356,25 +1417,29 @@ _jump jmp ($asmLabel)
|
||||
val value = right.number.toInt()
|
||||
if(notEquals) {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp #<$value
|
||||
bne +
|
||||
lda ${left.name}+1
|
||||
cmp #>$value
|
||||
beq ++
|
||||
+ jmp ($asmLabel)
|
||||
beq ++""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
+ jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp #<$value
|
||||
bne $asmLabel
|
||||
bne ${target.asmLabel}
|
||||
lda ${left.name}+1
|
||||
cmp #>$value
|
||||
bne $asmLabel""")
|
||||
bne ${target.asmLabel}""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
} else {
|
||||
@ -1410,25 +1475,29 @@ _jump jmp ($asmLabel)
|
||||
}
|
||||
} else {
|
||||
if(jump!=null) {
|
||||
val (asmLabel, indirect) = asmgen.getJumpTarget(jump)
|
||||
if(indirect) {
|
||||
var target = asmgen.getJumpTarget(jump, false)
|
||||
if(target.indirect) {
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp #<$value
|
||||
bne +
|
||||
lda ${left.name}+1
|
||||
cmp #>$value
|
||||
bne +
|
||||
jmp ($asmLabel)
|
||||
bne +""")
|
||||
if(target.needsExpressionEvaluation)
|
||||
target = asmgen.getJumpTarget(jump, true)
|
||||
asmgen.out("""
|
||||
jmp (${target.asmLabel})
|
||||
+""")
|
||||
} else {
|
||||
require(!target.needsExpressionEvaluation)
|
||||
asmgen.out("""
|
||||
lda ${left.name}
|
||||
cmp #<$value
|
||||
bne +
|
||||
lda ${left.name}+1
|
||||
cmp #>$value
|
||||
beq $asmLabel
|
||||
beq ${target.asmLabel}
|
||||
+""")
|
||||
}
|
||||
asmgen.translate(stmt.elseScope)
|
||||
|
@ -304,7 +304,7 @@ class IRCodeGen(
|
||||
}
|
||||
addInstr(result, branchIns, null)
|
||||
} else {
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
if(branch.falseScope.children.isNotEmpty())
|
||||
result += translateNode(branch.falseScope)
|
||||
@ -1031,7 +1031,7 @@ class IRCodeGen(
|
||||
if(identifier!=null) {
|
||||
it += IRInstruction(Opcode.JUMPI, labelSymbol = identifier.name)
|
||||
} else {
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
} else {
|
||||
// normal jump, directly to target with branch opcode
|
||||
@ -1057,7 +1057,7 @@ class IRCodeGen(
|
||||
else if(goto.target is PtIdentifier)
|
||||
IRInstruction(gotoOpcode, IRDataType.BYTE, reg1 = compResultReg, immediate = 0, labelSymbol = (goto.target as PtIdentifier).name)
|
||||
else
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1076,7 +1076,7 @@ class IRCodeGen(
|
||||
if(identifier!=null)
|
||||
IRInstruction(branchOpcode, labelSymbol = identifier.name)
|
||||
else
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1086,7 +1086,7 @@ class IRCodeGen(
|
||||
val afterIfLabel = createLabelName()
|
||||
val identifier = goto.target as? PtIdentifier
|
||||
if(identifier==null) {
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
val gotoSymbol = identifier.name
|
||||
|
||||
@ -1257,7 +1257,7 @@ class IRCodeGen(
|
||||
else if(goto.target is PtIdentifier)
|
||||
addInstr(result, IRInstruction(opcode, irDt, reg1 = firstReg, immediate = number, labelSymbol = (goto.target as PtIdentifier).name), null)
|
||||
else
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1316,7 +1316,7 @@ class IRCodeGen(
|
||||
else if(goto.target is PtIdentifier)
|
||||
addInstr(result, IRInstruction(opcode, irDt, reg1 = firstReg, reg2 = secondReg, labelSymbol = (goto.target as PtIdentifier).name), null)
|
||||
else
|
||||
TODO("GOTO TARGET ${goto.target}")
|
||||
TODO("JUMP to expression address ${goto.target}")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1660,7 +1660,7 @@ class IRCodeGen(
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = identifier.name)
|
||||
}
|
||||
} else {
|
||||
TODO("GOTO TARGET ${jump.target}")
|
||||
TODO("JUMP to expression address ${jump.target}")
|
||||
}
|
||||
}
|
||||
result += chunk
|
||||
|
@ -760,12 +760,13 @@ using qualified "dotted names"::
|
||||
|
||||
uword address = $4000
|
||||
goto address ; jump via address variable
|
||||
goto address + idx ; jump to an adress that is the result of an expression
|
||||
|
||||
Notice that this is a valid way to end a subroutine (you can either ``return`` from it, or jump
|
||||
to another piece of code that eventually returns).
|
||||
|
||||
If you jump to an address variable (uword), it is doing an 'indirect' jump: the jump will be done
|
||||
to the address that's currently in the variable.
|
||||
If you jump to an address variable or expression (uword), it is doing an 'indirect' jump: the jump will be done
|
||||
to the address that's currently in the variable, or the result of the expression.
|
||||
|
||||
|
||||
Assignments
|
||||
|
@ -1,8 +1,9 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
goto can now accept any expression (instead of just a constant address or an identifier).
|
||||
document this. + FIX code gen for the case where the target is a non-constant expression! See TODOs with "GOTO TARGET"
|
||||
- make word arrays split by default (remove @split tag) and use new @nosplit tag to make an array use the old storage format? Also invert -splitarrays command line option.
|
||||
- add &< and &> operators to get the address of the lsb-array and msb-array, respectively. Regular & will just return the start of the split array in memory whatever byte comes first.
|
||||
- update Syntax files + Document all of this (also that word arrays can then have length 256 by default as well, and that @linear will reduce it to half.)
|
||||
|
||||
...
|
||||
|
||||
@ -10,7 +11,6 @@ document this. + FIX code gen for the case where the target is a non-constant e
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- make word arrays split by default (remove @split tag) and use new @notsplit or @linear tag to make an array use the old storage format? Also remove -splitarrays command line option. Document this (also that word arrays can then have length 256 by default as well, and that @linear will reduce it to half.)
|
||||
- a syntax to access specific bits in a variable, to avoid manually shifts&ands, something like variable[4:8] ? (or something else this may be too similar to regular array indexing)
|
||||
- something to reduce the need to use fully qualified names all the time. 'with' ? Or 'using <prefix>'?
|
||||
- Libraries: improve ability to create library files in prog8; for instance there's still stuff injected into the start of the start() routine AND there is separate setup logic going on before calling it.
|
||||
@ -46,6 +46,7 @@ IR/VM
|
||||
- fix call() return value handling
|
||||
- fix float register parameters (FAC1,FAC2) for extsubs, search for TODO("floating point register parameters not supported")
|
||||
- proper code gen for the CALLI instruction and that it (optionally) returns a word value that needs to be assigned to a reg
|
||||
- make it possible to jump and branch to a computed address (expression), see TODO("JUMP to expression address
|
||||
- idea: (but LLVM IR simply keeps the variables, so not a good idea then?...): replace all scalar variables by an allocated register. Keep a table of the variable to register mapping (including the datatype)
|
||||
global initialization values are simply a list of LOAD instructions.
|
||||
Variables replaced include all subroutine parameters! So the only variables that remain as variables are arrays and strings.
|
||||
|
@ -2,8 +2,17 @@ main {
|
||||
sub start() {
|
||||
goto $3000
|
||||
goto labeltje
|
||||
|
||||
goto cx16.r0
|
||||
|
||||
goto cx16.r0+cx16.r1
|
||||
|
||||
if cx16.r0==0
|
||||
goto cx16.r0+cx16.r1
|
||||
|
||||
if cx16.r0>2000
|
||||
goto cx16.r0+cx16.r1
|
||||
|
||||
labeltje:
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user