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 pragmaIncbin(ppt, line, result): "Includes a binary file" filename = line.expect("STRING").value offset = IR.ConstantExpr(0) size = None if str(line.lookahead(0)) == ",": line.pop() offset = FE.parse_expr(line) if str(line.lookahead(0)) == ",": line.pop() size = FE.parse_expr(line) line.expect("EOL") if type(filename) == str: try: f = file(os.path.join(FE.context_directory, filename), "rb") if offset.hardcoded and (size is None or size.hardcoded): # We know how big it will be, we can just use the values. # First check to make sure they're sane if offset.value() < 0: Err.log("Offset may not be negative") f.close() return f.seek(0, 2) # Seek to end of file if offset.value() > f.tell(): Err.log("Offset runs past end of file") f.close() return if size is not None: if size.value() < 0: Err.log("Length may not be negative") f.close() return if offset.value() + size.value() > f.tell(): Err.log(".incbin length too long") f.close() return if size is None: size = IR.ConstantExpr(-1) f.seek(offset.value()) bytes = f.read(size.value()) bytes = [IR.ConstantExpr(ord(x)) for x in bytes] result.append(IR.Node(ppt, "Byte", *bytes)) else: # offset or length could change based on label placement. # This seems like an unbelievably bad idea, but since we # don't have constant prop it will happen for any symbolic # alias. Don't use symbolic aliases when extracting tiny # pieces out of humongous files, I guess. bytes = f.read() bytes = [IR.ConstantExpr(ord(x)) for x in bytes] if size is None: size = IR.SequenceExpr([IR.ConstantExpr(len(bytes)), "-", offset]) result.append(IR.Node(ppt, "ByteRange", offset, size, *bytes)) f.close() except IOError: Err.log("Could not read " + filename) return
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 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)