def pragmaSpace(ppt, line, result): "Reserves space in a data segment for a variable" lbl = line.expect("LABEL").value size = line.expect("NUM").value line.expect("EOL") result.append(IR.Node(ppt, "Label", lbl, IR.PCExpr())) result.append(IR.Node(ppt, "SetPC", IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(size)])))
def visitZPRelative(self, node, env): (opcode, tested, expr) = node.data arg = expr.value(env) arg = arg - (env.getPC() + 3) if arg < -128 or arg > 127: # Otherwise, we replace it with a 'macro' of sorts by hand: # $branch LOC -> $reversed_branch ^+6; JMP LOC # We don't use temp labels here because labels need to have # been fixed in place by this point, and JMP is always 3 # bytes long. expansion = [IR.Node(node.ppt, "ZPRelative", ExtendBranches.reversed[opcode], tested, IR.SequenceExpr([IR.PCExpr(), "+", IR.ConstantExpr(6)])), IR.Node(node.ppt, "Absolute", 'jmp', expr, None)] node.nodetype = 'SEQUENCE' node.data = expansion if Cmd.warn_on_branch_extend: print>>sys.stderr, str(node.ppt) + ": WARNING: " + \ opcode + " out of range, " \ "replacing with " + \ ExtendBranches.reversed[opcode] + \ "/jmp combo" self.changed = True node.accept(self, env) else: PCTracker.visitZPRelative(self, node, env)
def visitRelative(self, node, env): (opcode, expr) = node.data[:2] arg = expr.value(env) arg = arg - (env.getPC() + 2) if arg < -128 or arg > 127: if Cmd.enable_4502_exts: node.nodetype = "RelativeLong" if Cmd.warn_on_branch_extend: print(str(node.ppt) + ": WARNING: " \ "branch out of range, replacing with 16-bit relative branch", file=sys.stderr) else: if opcode == 'bra': # If BRA - BRanch Always - is out of range, it's a JMP. node.data = ('jmp', expr, None) node.nodetype = "Absolute" if Cmd.warn_on_branch_extend: print(str(node.ppt) + ": WARNING: " \ "bra out of range, replacing with jmp", file=sys.stderr) else: # Otherwise, we replace it with a 'macro' of sorts by hand: # $branch LOC -> $reversed_branch ^+5; JMP LOC # We don't use temp labels here because labels need to have # been fixed in place by this point, and JMP is always 3 # bytes long. expansion = [ IR.Node( node.ppt, "Relative", ExtendBranches.reversed[opcode], IR.SequenceExpr( [IR.PCExpr(), "+", IR.ConstantExpr(5)]), None), IR.Node(node.ppt, "Absolute", 'jmp', expr, None) ] node.nodetype = 'SEQUENCE' node.data = expansion if Cmd.warn_on_branch_extend: print(str(node.ppt) + ": WARNING: " + \ opcode + " out of range, " \ "replacing with " + \ ExtendBranches.reversed[opcode] + \ "/jmp combo", file=sys.stderr) self.changed = True node.accept(self, env) else: PCTracker.visitRelative(self, node, env)
def atom(): "Parses lowest-priority expression components." global templabelcount next = line.lookahead(0).type if next == "NUM": return IR.ConstantExpr(line.expect("NUM").value) elif next in ["LABEL", "X", "Y", "Z", "SP", "OPCODE"]: return IR.LabelExpr(line.expect("LABEL").value) elif next == "^": line.expect("^") return IR.PCExpr() elif next == "[": line.expect("[") result = parse_expr(line) line.expect("]") return result elif next == "+": offset = 0 while next == "+": offset += 1 line.expect("+") next = line.lookahead(0).type return IR.LabelExpr("*" + str(templabelcount + offset)) elif next == "-": offset = 1 while next == "-": offset -= 1 line.expect("-") next = line.lookahead(0).type return IR.LabelExpr("*" + str(templabelcount + offset)) elif next == ">": line.expect(">") return IR.HighByteExpr(atom()) elif next == "<": line.expect("<") return IR.LowByteExpr(atom()) else: Err.log('Expected: expression')
def aux(): "Accumulates all IR nodes defined by this line." if line.lookahead(0).type == "EOL": pass elif line.lookahead(1).type == ":": newlabel = line.expect("LABEL").value line.expect(":") result.append(IR.Node(ppt, "Label", newlabel, IR.PCExpr())) aux() elif line.lookahead(0).type == "*": global templabelcount templabelcount = templabelcount + 1 result.append( IR.Node(ppt, "Label", "*" + str(templabelcount), IR.PCExpr())) line.expect("*") aux() elif line.lookahead(0).type == "." or line.lookahead(0).type == "`": which = line.expect(".", "`").type if (which == "."): pragma = line.expect("LABEL").value else: pragma = "invoke" pragmaFunction = "pragma" + pragma.title() for mod in pragma_modules: if hasattr(mod, pragmaFunction): getattr(mod, pragmaFunction)(ppt, line, result) break else: Err.log("Unknown pragma " + pragma) else: # Instruction opcode = line.expect("OPCODE").value arg2 = None if line.lookahead(0).type == "#": mode = "Immediate" line.expect("#") arg = parse_expr(line) line.expect("EOL") elif line.lookahead(0).type == "(": line.expect("(") arg = parse_expr(line) if line.lookahead(0).type == ",": line.expect(",") if line.lookahead(0).type == "X": mode = "PointerX" line.expect("X") line.expect(")") line.expect("EOL") else: mode = "PointerSPY" line.expect("SP") line.expect(")") line.expect(",") line.expect("Y") line.expect("EOL") else: line.expect(")") tok = line.expect(",", "EOL").type if tok == "EOL": mode = "Pointer" else: if line.lookahead(0).type == "Y": mode = "PointerY" line.expect("Y") line.expect("EOL") else: mode = "PointerZ" line.expect("Z") line.expect("EOL") elif line.lookahead(0).type == "EOL": mode = "Implied" arg = None else: arg = parse_expr(line) tok = line.expect("EOL", ",").type if tok == ",": # Parser has to special-case the BBXn instructions, # Which uniquely take two addresses if opcode[:3] in ["bbs", "bbr"]: arg2 = parse_expr(line) mode = "Memory2" else: tok = line.expect("X", "Y", "Z").type if tok == "X": mode = "MemoryX" elif tok == "Y": mode = "MemoryY" else: mode = "MemoryZ" line.expect("EOL") else: mode = "Memory" result.append(IR.Node(ppt, mode, opcode, arg, arg2))
def aux(): "Accumulates all IR nodes defined by this line." if line.lookahead(0).type == "EOL": pass elif line.lookahead(1).type == ":": newlabel = line.expect("LABEL").value line.expect(":") result.append(IR.Node(ppt, "Label", newlabel, IR.PCExpr())) aux() elif line.lookahead(0).type == "*": global templabelcount templabelcount = templabelcount + 1 result.append( IR.Node(ppt, "Label", "*" + str(templabelcount), IR.PCExpr())) line.expect("*") aux() elif line.lookahead(0).type == "." or line.lookahead(0).type == "`": which = line.expect(".", "`").type if (which == "."): pragma = line.expect("LABEL").value else: pragma = "invoke" pragmaFunction = "pragma" + pragma.title() for mod in pragma_modules: if hasattr(mod, pragmaFunction): getattr(mod, pragmaFunction)(ppt, line, result) break else: Err.log("Unknown pragma " + pragma) else: # Instruction opcode = line.expect("OPCODE").value if line.lookahead(0).type == "#": mode = "Immediate" line.expect("#") arg = parse_expr(line) line.expect("EOL") elif line.lookahead(0).type == "(": line.expect("(") arg = parse_expr(line) if line.lookahead(0).type == ",": mode = "IndirectX" line.expect(",") line.expect("X") line.expect(")") line.expect("EOL") else: line.expect(")") tok = line.expect(",", "EOL").type if tok == "EOL": mode = "Indirect" else: mode = "IndirectY" line.expect("Y") line.expect("EOL") elif line.lookahead(0).type == "EOL": mode = "Implied" arg = None else: arg = parse_expr(line) tok = line.expect("EOL", ",").type if tok == ",": tok = line.expect("X", "Y").type if tok == "X": mode = "MemoryX" else: mode = "MemoryY" line.expect("EOL") else: mode = "Memory" result.append(IR.Node(ppt, mode, opcode, arg))