mirror of
https://github.com/irmen/prog8.git
synced 2025-11-24 06:17:39 +00:00
add if-expression versions for the conditionals if_cc, if_cs, if_vc etc
This commit is contained in:
@@ -860,7 +860,7 @@ class AsmGen6502Internal (
|
||||
}
|
||||
}
|
||||
|
||||
private fun branchInstruction(condition: BranchCondition, complement: Boolean) =
|
||||
internal fun branchInstruction(condition: BranchCondition, complement: Boolean) =
|
||||
if(complement) {
|
||||
when (condition) {
|
||||
BranchCondition.CS -> "bcc"
|
||||
@@ -1698,6 +1698,10 @@ $repeatLabel""")
|
||||
ifExpressionAsmgen.assignIfExpression(target, value)
|
||||
}
|
||||
|
||||
internal fun assignBranchCondExpression(target: AsmAssignTarget, value: PtBranchCondExpression) {
|
||||
ifExpressionAsmgen.assignBranchCondExpression(target, value)
|
||||
}
|
||||
|
||||
internal fun cmpAwithByteValue(value: PtExpression, useSbc: Boolean) {
|
||||
val compare = if(useSbc) "sec | sbc" else "cmp"
|
||||
fun cmpViaScratch() {
|
||||
|
||||
@@ -44,6 +44,69 @@ internal class IfExpressionAsmGen(private val asmgen: AsmGen6502Internal, privat
|
||||
}
|
||||
}
|
||||
|
||||
internal fun assignBranchCondExpression(target: AsmAssignTarget, expr: PtBranchCondExpression) {
|
||||
require(target.datatype==expr.type ||
|
||||
target.datatype.isUnsignedWord && (expr.type.isString || expr.type.isPointer) ||
|
||||
target.datatype.isPointer && (expr.type.isUnsignedWord || expr.type.isPointer || expr.type.isString))
|
||||
|
||||
if(target.kind==TargetStorageKind.REGISTER && target.datatype.isUnsignedByte && target.register==RegisterOrPair.A) {
|
||||
if(expr.condition==BranchCondition.CC) {
|
||||
if(expr.truevalue.asConstInteger()==0 && expr.falsevalue.asConstInteger()==1) {
|
||||
asmgen.out(" lda #0 | rol a")
|
||||
return
|
||||
}
|
||||
else if(expr.truevalue.asConstInteger()==1 && expr.falsevalue.asConstInteger()==0) {
|
||||
asmgen.out(" lda #0 | rol a | eor #1")
|
||||
return
|
||||
}
|
||||
}
|
||||
else if(expr.condition==BranchCondition.CS) {
|
||||
if(expr.truevalue.asConstInteger()==0 && expr.falsevalue.asConstInteger()==1) {
|
||||
asmgen.out(" lda #0 | rol a | eor #1")
|
||||
return
|
||||
}
|
||||
else if(expr.truevalue.asConstInteger()==1 && expr.falsevalue.asConstInteger()==0) {
|
||||
asmgen.out(" lda #0 | rol a")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val trueLabel = asmgen.makeLabel("branchexpr_true")
|
||||
val endLabel = asmgen.makeLabel("branchexpr_end")
|
||||
val branch = asmgen.branchInstruction(expr.condition, false)
|
||||
|
||||
asmgen.out(" $branch $trueLabel")
|
||||
|
||||
when {
|
||||
expr.type.isByteOrBool -> {
|
||||
asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.A)
|
||||
asmgen.jmp(endLabel)
|
||||
asmgen.out(trueLabel)
|
||||
asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.A)
|
||||
asmgen.out(endLabel)
|
||||
assignmentAsmGen.assignRegisterByte(target, CpuRegister.A, false, false)
|
||||
}
|
||||
expr.type.isWord || expr.type.isString -> {
|
||||
asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.AY)
|
||||
asmgen.jmp(endLabel)
|
||||
asmgen.out(trueLabel)
|
||||
asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.AY)
|
||||
asmgen.out(endLabel)
|
||||
assignmentAsmGen.assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
}
|
||||
expr.type.isFloat -> {
|
||||
asmgen.assignExpressionToRegister(expr.falsevalue, RegisterOrPair.FAC1, true)
|
||||
asmgen.jmp(endLabel)
|
||||
asmgen.out(trueLabel)
|
||||
asmgen.assignExpressionToRegister(expr.truevalue, RegisterOrPair.FAC1, true)
|
||||
asmgen.out(endLabel)
|
||||
asmgen.assignRegister(RegisterOrPair.FAC1, target)
|
||||
}
|
||||
else -> throw AssemblyError("weird dt")
|
||||
}
|
||||
}
|
||||
|
||||
private fun evalIfExpressionConditonAndBranchWhenFalse(condition: PtExpression, falseLabel: String) {
|
||||
when (condition) {
|
||||
is PtBinaryExpression -> {
|
||||
|
||||
@@ -526,6 +526,7 @@ internal class AssignmentAsmGen(
|
||||
}
|
||||
}
|
||||
is PtIfExpression -> asmgen.assignIfExpression(assign.target, value)
|
||||
is PtBranchCondExpression -> asmgen.assignBranchCondExpression(assign.target, value)
|
||||
is PtPointerDeref -> pointergen.assignPointerDerefExpression(assign.target, value)
|
||||
else -> throw AssemblyError("weird assignment value type $value")
|
||||
}
|
||||
|
||||
@@ -83,6 +83,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
is PtArrayIndexer -> translate(expr)
|
||||
is PtBinaryExpression -> translate(expr)
|
||||
is PtIfExpression -> translate(expr)
|
||||
is PtBranchCondExpression -> translate(expr)
|
||||
is PtBuiltinFunctionCall -> codeGen.translateBuiltinFunc(expr)
|
||||
is PtFunctionCall -> translate(expr)
|
||||
is PtContainmentCheck -> translate(expr)
|
||||
@@ -253,6 +254,69 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun translate(branchExpr: PtBranchCondExpression): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val trueTr = translateExpression(branchExpr.truevalue)
|
||||
val falseTr = translateExpression(branchExpr.falsevalue)
|
||||
val trueLabel = codeGen.createLabelName()
|
||||
val endLabel = codeGen.createLabelName()
|
||||
val irDt = irType(branchExpr.type)
|
||||
|
||||
if(branchExpr.condition==BranchCondition.CC && irDt==IRDataType.BYTE) {
|
||||
if(branchExpr.truevalue.asConstInteger()==0 && branchExpr.falsevalue.asConstInteger()==1) {
|
||||
result.add(IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, irDt, reg1=trueTr.resultReg, immediate = 0)
|
||||
it += IRInstruction(Opcode.ROXL, irDt, reg1=trueTr.resultReg)
|
||||
})
|
||||
return ExpressionCodeResult(result, irDt, trueTr.resultReg, -1)
|
||||
}
|
||||
else if(branchExpr.truevalue.asConstInteger()==1 && branchExpr.falsevalue.asConstInteger()==0) {
|
||||
result.add(IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, irDt, reg1=trueTr.resultReg, immediate = 0)
|
||||
it += IRInstruction(Opcode.ROXL, irDt, reg1=trueTr.resultReg)
|
||||
it += IRInstruction(Opcode.XOR, irDt, reg1=trueTr.resultReg, immediate = 1)
|
||||
})
|
||||
return ExpressionCodeResult(result, irDt, trueTr.resultReg, -1)
|
||||
}
|
||||
}
|
||||
else if(branchExpr.condition==BranchCondition.CS) {
|
||||
if(branchExpr.truevalue.asConstInteger()==0 && branchExpr.falsevalue.asConstInteger()==1) {
|
||||
result.add(IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, irDt, reg1=trueTr.resultReg, immediate = 0)
|
||||
it += IRInstruction(Opcode.ROXL, irDt, reg1=trueTr.resultReg)
|
||||
it += IRInstruction(Opcode.XOR, irDt, reg1=trueTr.resultReg, immediate = 1)
|
||||
})
|
||||
return ExpressionCodeResult(result, irDt, trueTr.resultReg, -1)
|
||||
}
|
||||
else if(branchExpr.truevalue.asConstInteger()==1 && branchExpr.falsevalue.asConstInteger()==0) {
|
||||
result.add(IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.LOAD, irDt, reg1=trueTr.resultReg, immediate = 0)
|
||||
it += IRInstruction(Opcode.ROXL, irDt, reg1=trueTr.resultReg)
|
||||
})
|
||||
return ExpressionCodeResult(result, irDt, trueTr.resultReg, -1)
|
||||
}
|
||||
}
|
||||
|
||||
val branchInstr = codeGen.IRBranchInstr(branchExpr.condition, trueLabel)
|
||||
addInstr(result, branchInstr, null)
|
||||
|
||||
if (irDt != IRDataType.FLOAT) {
|
||||
addToResult(result, falseTr, trueTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = endLabel), null)
|
||||
result += IRCodeChunk(trueLabel, null)
|
||||
addToResult(result, trueTr, trueTr.resultReg, -1)
|
||||
result += IRCodeChunk(endLabel, null)
|
||||
return ExpressionCodeResult(result, irDt, trueTr.resultReg, -1)
|
||||
} else {
|
||||
addToResult(result, falseTr, -1, trueTr.resultFpReg)
|
||||
addInstr(result, IRInstruction(Opcode.JUMP, labelSymbol = endLabel), null)
|
||||
result += IRCodeChunk(trueLabel, null)
|
||||
addToResult(result, trueTr, -1, trueTr.resultFpReg)
|
||||
result += IRCodeChunk(endLabel, null)
|
||||
return ExpressionCodeResult(result, irDt, -1, trueTr.resultFpReg)
|
||||
}
|
||||
}
|
||||
|
||||
private fun translate(expr: PtAddressOf): ExpressionCodeResult {
|
||||
val vmDt = irType(expr.type)
|
||||
// note: LOAD <symbol> gets you the address of the symbol, whereas LOADM <symbol> would get you the value stored at that location
|
||||
|
||||
@@ -336,7 +336,7 @@ class IRCodeGen(
|
||||
return result
|
||||
}
|
||||
|
||||
private fun IRBranchInstr(condition: BranchCondition, label: String?=null, address: Int?=null): IRInstruction {
|
||||
internal fun IRBranchInstr(condition: BranchCondition, label: String?=null, address: Int?=null): IRInstruction {
|
||||
if(label!=null)
|
||||
return when(condition) {
|
||||
BranchCondition.CS -> IRInstruction(Opcode.BSTCS, labelSymbol = label)
|
||||
|
||||
@@ -54,6 +54,7 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
|| removeDoubleSecClc(chunk1, indexedInstructions)
|
||||
|| cleanupPushPop(chunk1, indexedInstructions)
|
||||
|| simplifyConstantReturns(chunk1, indexedInstructions)
|
||||
|| removeNeedlessLoads(chunk1, indexedInstructions)
|
||||
} while (changed)
|
||||
}
|
||||
}
|
||||
@@ -353,6 +354,29 @@ class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeNeedlessLoads(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
/*
|
||||
load.b r2,#2
|
||||
loadr.b r1,r2
|
||||
jump p8_label_gen_2
|
||||
*/
|
||||
var changed=false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
if(idx>=2 && ins.opcode in OpcodesThatJump) {
|
||||
val previous = indexedInstructions[idx-1].value
|
||||
val previous2 = indexedInstructions[idx-2].value
|
||||
if(previous.opcode==Opcode.LOADR && previous2.opcode in OpcodesThatLoad) {
|
||||
if(previous.reg2==previous2.reg1) {
|
||||
chunk.instructions[idx-2] = previous2.copy(reg1=previous.reg1)
|
||||
chunk.instructions.removeAt(idx-1)
|
||||
changed=true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeUselessArithmetic(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
// note: this is hard to solve for the non-immediate instructions atm because the values are loaded into registers first
|
||||
var changed = false
|
||||
|
||||
@@ -100,6 +100,7 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
is StringLiteral -> transform(expr)
|
||||
is TypecastExpression -> transform(expr)
|
||||
is IfExpression -> transform(expr)
|
||||
is BranchConditionExpression -> transform(expr)
|
||||
is PtrDereference -> transform(expr)
|
||||
is StaticStructInitializer -> transform(expr)
|
||||
is ArrayIndexedPtrDereference -> throw FatalAstException("this should have been converted to some other ast nodes")
|
||||
@@ -141,6 +142,14 @@ class SimplifiedAstMaker(private val program: Program, private val errors: IErro
|
||||
return ifexpr
|
||||
}
|
||||
|
||||
private fun transform(branchExpr: BranchConditionExpression): PtBranchCondExpression {
|
||||
val type = branchExpr.inferType(program).getOrElse { throw FatalAstException("unknown dt") }
|
||||
val bexpr = PtBranchCondExpression(branchExpr.condition, type, branchExpr.position)
|
||||
bexpr.add(transformExpression(branchExpr.truevalue))
|
||||
bexpr.add(transformExpression(branchExpr.falsevalue))
|
||||
return bexpr
|
||||
}
|
||||
|
||||
private fun transform(srcDefer: Defer): PtDefer {
|
||||
val defer = PtDefer(srcDefer.position)
|
||||
srcDefer.scope.statements.forEach {
|
||||
|
||||
@@ -66,6 +66,13 @@ class AstToSourceTextConverter(val output: (text: String) -> Unit, val program:
|
||||
ifExpr.falsevalue.accept(this)
|
||||
}
|
||||
|
||||
override fun visit(branchExpr: BranchConditionExpression) {
|
||||
output("if_${branchExpr.condition.name.lowercase()} ")
|
||||
branchExpr.truevalue.accept(this)
|
||||
output(" else ")
|
||||
branchExpr.falsevalue.accept(this)
|
||||
}
|
||||
|
||||
override fun visit(continueStmt: Continue) {
|
||||
output("continue")
|
||||
}
|
||||
|
||||
@@ -551,10 +551,10 @@ class Antlr2KotlinVisitor(val source: SourceCode): AbstractParseTreeVisitor<Node
|
||||
return IfExpression(condition, truevalue, falsevalue, ctx.toPosition())
|
||||
}
|
||||
|
||||
override fun visitBranchcondition_expression(ctx: Branchcondition_expressionContext): IfExpression {
|
||||
val branchcondition = branchCondition(ctx.branchcondition())
|
||||
override fun visitBranchcondition_expression(ctx: Branchcondition_expressionContext): BranchConditionExpression {
|
||||
val condition = branchCondition(ctx.branchcondition())
|
||||
val (truevalue, falsevalue) = ctx.expression().map { it.accept(this) as Expression }
|
||||
throw SyntaxError("branchcondition expression not yet supported", ctx.toPosition())
|
||||
return BranchConditionExpression(condition, truevalue, falsevalue, ctx.toPosition())
|
||||
}
|
||||
|
||||
override fun visitBranch_stmt(ctx: Branch_stmtContext): ConditionalBranch {
|
||||
|
||||
@@ -1660,6 +1660,42 @@ class IfExpression(var condition: Expression, var truevalue: Expression, var fal
|
||||
}
|
||||
}
|
||||
|
||||
class BranchConditionExpression(var condition: BranchCondition, var truevalue: Expression, var falsevalue: Expression, override val position: Position) : Expression() {
|
||||
|
||||
override lateinit var parent: Node
|
||||
|
||||
override fun linkParents(parent: Node) {
|
||||
this.parent = parent
|
||||
truevalue.linkParents(this)
|
||||
falsevalue.linkParents(this)
|
||||
}
|
||||
|
||||
override val isSimple: Boolean = truevalue.isSimple && falsevalue.isSimple
|
||||
|
||||
override fun constValue(program: Program) = null
|
||||
override fun toString() = "BranchExpr(cond=$condition, true=$truevalue, false=$falsevalue, pos=$position)"
|
||||
override fun accept(visitor: IAstVisitor) = visitor.visit(this)
|
||||
override fun accept(visitor: AstWalker, parent: Node) = visitor.visit(this, parent)
|
||||
override fun referencesIdentifier(nameInSource: List<String>): Boolean = truevalue.referencesIdentifier(nameInSource) || falsevalue.referencesIdentifier(nameInSource)
|
||||
override fun inferType(program: Program): InferredTypes.InferredType {
|
||||
val t1 = truevalue.inferType(program)
|
||||
val t2 = falsevalue.inferType(program)
|
||||
if(t1==t2) return t1
|
||||
if(t1.isPointer && t2.isUnsignedWord || t1.isUnsignedWord && t2.isPointer) return InferredTypes.knownFor(BaseDataType.UWORD)
|
||||
return InferredTypes.unknown()
|
||||
}
|
||||
|
||||
override fun copy(): Expression = BranchConditionExpression(condition, truevalue.copy(), falsevalue.copy(), position)
|
||||
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
if(replacement !is Expression)
|
||||
throw FatalAstException("invalid replace")
|
||||
else if(node===truevalue) truevalue=replacement
|
||||
else if(node===falsevalue) falsevalue=replacement
|
||||
else throw FatalAstException("invalid replace")
|
||||
}
|
||||
}
|
||||
|
||||
class PtrDereference(
|
||||
val chain: List<String>,
|
||||
val derefLast: Boolean,
|
||||
|
||||
@@ -114,6 +114,7 @@ abstract class AstWalker {
|
||||
open fun before(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(expr: PrefixExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(ifExpr: IfExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(branchExpr: BranchConditionExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(forLoop: ForLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(repeatLoop: RepeatLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun before(unrollLoop: UnrollLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
@@ -165,6 +166,7 @@ abstract class AstWalker {
|
||||
open fun after(expr: BinaryExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(expr: PrefixExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(ifExpr: IfExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(branchExpr: BranchConditionExpression, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(forLoop: ForLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(repeatLoop: RepeatLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
open fun after(unrollLoop: UnrollLoop, parent: Node): Iterable<IAstModification> = noModifications
|
||||
@@ -510,6 +512,13 @@ abstract class AstWalker {
|
||||
track(after(ifExpr, parent), ifExpr, parent)
|
||||
}
|
||||
|
||||
fun visit(branchExpr: BranchConditionExpression, parent: Node) {
|
||||
track(before(branchExpr, parent), branchExpr, parent)
|
||||
branchExpr.truevalue.accept(this, branchExpr)
|
||||
branchExpr.falsevalue.accept(this, branchExpr)
|
||||
track(after(branchExpr, parent), branchExpr, parent)
|
||||
}
|
||||
|
||||
fun visit(inlineAssembly: InlineAssembly, parent: Node) {
|
||||
track(before(inlineAssembly, parent), inlineAssembly, parent)
|
||||
track(after(inlineAssembly, parent), inlineAssembly, parent)
|
||||
|
||||
@@ -100,6 +100,11 @@ interface IAstVisitor {
|
||||
ifExpr.falsevalue.accept(this)
|
||||
}
|
||||
|
||||
fun visit(branchExpr: BranchConditionExpression) {
|
||||
branchExpr.truevalue.accept(this)
|
||||
branchExpr.falsevalue.accept(this)
|
||||
}
|
||||
|
||||
fun visit(label: Label) {
|
||||
}
|
||||
|
||||
|
||||
@@ -742,6 +742,12 @@ An example, to select the number of cards to use depending on what game is playe
|
||||
else
|
||||
numcards = 52
|
||||
|
||||
The expression form is also available for the conditionals ``if_cc``, ``if_cs``, ``if_z`` etc.
|
||||
(These particular variants for checking the value of the Carry status bit actually compile into very efficient branchless assembly code)::
|
||||
|
||||
ubyte carryvalue = if_cs 1 else 0
|
||||
|
||||
|
||||
|
||||
on .. goto / on .. call statement (jump table)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -78,7 +78,6 @@ STRUCTS and TYPED POINTERS
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- add if-expression versions for the conditionals if_cc, if_cs, if_vc etc etc so you can write a = b + if_cs 1 else 0 (make sure it gets compiled to nice instructions lda #0; rol a etc.) See visitBranchcondition_expression()
|
||||
- %breakpoint after an assignment is parsed as part of the expression (x % breakpoint), that should not happen
|
||||
- when a complete block is removed because unused, suppress all info messages about everything in the block being removed
|
||||
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1
|
||||
|
||||
@@ -1,19 +1,42 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
struct Node {
|
||||
ubyte id
|
||||
}
|
||||
|
||||
^^byte @shared bptr = 2000
|
||||
^^word @shared swptr = 2000
|
||||
^^uword @shared uwptr = 2000
|
||||
^^Node @shared node = 2000
|
||||
|
||||
sub start() {
|
||||
alias nid = node.id
|
||||
cx16.r0 = mkword(0, cx16.r9L)
|
||||
swptr^^ = mkword(0, cx16.r9L) as word
|
||||
uwptr^^ = mkword(0, cx16.r9L)
|
||||
sys.set_carry()
|
||||
txt.print_ub(if_cc 0 else 1)
|
||||
txt.nl()
|
||||
sys.clear_carry()
|
||||
txt.print_ub(if_cc 0 else 1)
|
||||
txt.nl()
|
||||
sys.set_carry()
|
||||
txt.print_ub(if_cs 0 else 1)
|
||||
txt.nl()
|
||||
sys.clear_carry()
|
||||
txt.print_ub(if_cs 0 else 1)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
|
||||
;%import textio
|
||||
;%zeropage basicsafe
|
||||
;
|
||||
;main {
|
||||
; struct Node {
|
||||
; ubyte id
|
||||
; str name
|
||||
; uword array
|
||||
; }
|
||||
;
|
||||
; ^^Node @shared @zp node = 2000
|
||||
;
|
||||
; sub start() {
|
||||
; txt.print_uw(node)
|
||||
; txt.spc()
|
||||
; cx16.r0 = &node.array ; TODO don't clobber node pointer itself!!
|
||||
; txt.print_uw(cx16.r0)
|
||||
; txt.spc()
|
||||
; txt.print_uw(node)
|
||||
; txt.nl()
|
||||
; }
|
||||
;}
|
||||
|
||||
@@ -514,6 +514,23 @@ val OpcodesThatDependOnCarry = arrayOf(
|
||||
Opcode.ROXRM
|
||||
)
|
||||
|
||||
val OpcodesThatLoad = arrayOf(
|
||||
Opcode.LOAD,
|
||||
Opcode.LOADM,
|
||||
Opcode.LOADI,
|
||||
Opcode.LOADX,
|
||||
Opcode.LOADIX,
|
||||
Opcode.LOADR,
|
||||
Opcode.LOADHA,
|
||||
Opcode.LOADHX,
|
||||
Opcode.LOADHY,
|
||||
Opcode.LOADHAX,
|
||||
Opcode.LOADHAY,
|
||||
Opcode.LOADHXY,
|
||||
Opcode.LOADFIELD,
|
||||
Opcode.LOADHFACZERO,
|
||||
Opcode.LOADHFACONE
|
||||
)
|
||||
val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThatSetStatusbitsIncludingCarry
|
||||
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
is PtPointerDeref -> false
|
||||
is PtTypeCast -> value.isSimple()
|
||||
is PtIfExpression -> condition.isSimple() && truevalue.isSimple() && falsevalue.isSimple()
|
||||
is PtBranchCondExpression -> truevalue.isSimple() && falsevalue.isSimple()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,6 +260,12 @@ class PtIfExpression(type: DataType, position: Position): PtExpression(type, pos
|
||||
get() = children[2] as PtExpression
|
||||
}
|
||||
|
||||
class PtBranchCondExpression(val condition: BranchCondition, type: DataType, position: Position): PtExpression(type, position) {
|
||||
val truevalue: PtExpression
|
||||
get() = children[0] as PtExpression
|
||||
val falsevalue: PtExpression
|
||||
get() = children[1] as PtExpression
|
||||
}
|
||||
|
||||
class PtContainmentCheck(position: Position): PtExpression(DataType.BOOL, position) {
|
||||
val needle: PtExpression
|
||||
|
||||
@@ -188,6 +188,7 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni
|
||||
}
|
||||
is PtDefer -> "<defer>"
|
||||
is PtIfExpression -> "<ifexpr>"
|
||||
is PtBranchCondExpression -> "<branchexpr> if_${node.condition.name.lowercase()}"
|
||||
is PtJmpTable -> "<jmptable>"
|
||||
is PtStructDecl -> {
|
||||
"struct ${node.name} { " + node.fields.joinToString(" ") { "${it.first} ${it.second}" } + " }"
|
||||
|
||||
Reference in New Issue
Block a user