Пример #1
0
 def assemble(self, node, mode, env):
     "A generic instruction called by the visitor methods themselves"
     (opcode, expr) = node.data
     bin_op = Ops.opcodes[opcode][mode]
     if bin_op is None:
         Err.log('%s does not have mode "%s"' % (opcode.upper(),
                                                 Ops.modes[mode]))
         return
     self.outputbyte(IR.ConstantExpr(bin_op), env)
     arglen = Ops.lengths[mode]
     if mode == 14:  # Special handling for relative mode
         arg = expr.value(env)
         arg = arg - (env.getPC() + 2)
         if arg < -128 or arg > 127:
             Err.log("Branch target out of bounds")
             arg = 0
         if arg < 0:
             arg += 256
         expr = IR.ConstantExpr(arg)
     if arglen == 1:
         self.outputbyte(expr, env)
     if arglen == 2:
         self.outputword(expr, env)
     env.incPC(1 + arglen)
     self.code += 1 + arglen
Пример #2
0
def expandMacro(ppt, name, arglist):
    global macros
    if name not in macros:
        Err.log("Undefined macro '%s'" % name)
        return IR.NullNode
    argexprs = [
        IR.Node(ppt, "Label", "_*%d" % i, arg)
        for (i, arg) in zip(xrange(1, sys.maxint), arglist)
    ]
    bindexprs = [
        IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i))
        for i in range(1,
                       len(arglist) + 1)
    ]
    body = [
        IR.Node("%s->%s" % (ppt, node.ppt), node.nodetype, *node.data)
        for node in macros[name]
    ]
    invocation = [IR.Node(ppt, "ScopeBegin")] + argexprs + [
        IR.Node(ppt, "ScopeBegin")
    ] + bindexprs + body + [
        IR.Node(ppt, "ScopeEnd"),
        IR.Node(ppt, "ScopeEnd")
    ]
    return IR.SequenceNode(ppt, invocation)
Пример #3
0
 def assemble(self, node, mode, env):
     "A generic instruction called by the visitor methods themselves"
     (opcode, expr, expr2) = node.data
     bin_op = Ops.opcodes[opcode][mode]
     if bin_op is None:
         Err.log('%s does not have mode "%s"' %
                 (opcode.upper(), Ops.modes[mode]))
         return
     inst_bytes = []
     self.outputbyte(IR.ConstantExpr(bin_op), env, inst_bytes)
     arglen = Ops.lengths[mode]
     val1 = None
     val2 = None
     if expr is not None:
         val1 = expr.value(env)
     if expr2 is not None:
         val2 = expr2.value(env)
     if mode == Ops.modes.index("Zero Page, Relative"):
         expr2 = self.relativize(expr2, env, arglen)
         self.outputbyte(expr, env, inst_bytes)
         self.outputbyte(expr2, env, inst_bytes)
     else:
         if mode == Ops.modes.index("Relative"):
             expr = self.relativize(expr, env, arglen)
         elif mode == Ops.modes.index("RelativeLong"):
             expr = self.relativizelong(expr, env, arglen)
         if arglen == 1:
             self.outputbyte(expr, env, inst_bytes)
         elif arglen == 2:
             self.outputword(expr, env, inst_bytes)
     self.listing.listInstruction(
         self.listing_string(env.getPC(), inst_bytes, mode, opcode, val1,
                             val2))
     env.incPC(1 + arglen)
     self.code += 1 + arglen
Пример #4
0
 def assemble(self, node, mode, env):
     "A generic instruction called by the visitor methods themselves"
     (opcode, expr, expr2) = node.data
     bin_op = Ops.opcodes[opcode][mode]
     if bin_op is None:
         Err.log('%s does not have mode "%s"' % (opcode.upper(),
                                                 Ops.modes[mode]))
         return
     inst_bytes = []
     self.outputbyte(IR.ConstantExpr(bin_op), env, inst_bytes)
     arglen = Ops.lengths[mode]
     val1 = None
     val2 = None
     if expr is not None:
         val1 = expr.value(env)
     if expr2 is not None:
         val2 = expr2.value(env)
     if mode == 15:  # ZP Relative mode is wildly nonstandard
         expr2 = self.relativize(expr2, env, arglen)
         self.outputbyte(expr, env, inst_bytes)
         self.outputbyte(expr2, env, inst_bytes)
     else:
         if mode == 14:
             expr = self.relativize(expr, env, arglen)
         if arglen == 1:
             self.outputbyte(expr, env, inst_bytes)
         elif arglen == 2:
             self.outputword(expr, env, inst_bytes)
     self.listing.listInstruction(self.listing_string(env.getPC(),
                                                      inst_bytes,
                                                      mode, opcode,
                                                      val1, val2))
     env.incPC(1 + arglen)
     self.code += 1 + arglen
Пример #5
0
def pragmaCbmfloat(ppt, line, result):
    "Parses a string into a CBM BASIC format floating point number"
    data = []
    while True:
        try:
            v_str = line.expect("STRING").value
            v = float(v_str)
            if v == 0.0:
                data.extend([0, 0, 0, 0, 0])
            else:
                if v < 0.0:
                    sign = 128
                    v = -v
                else:
                    sign = 0
                expt = math.floor(math.log(v, 2))
                if expt >= -128 and expt <= 126:
                    mantissa = v / (2**expt)
                    m1 = (mantissa - 1.0) * 128 + sign
                    m2 = m1 * 256
                    m3 = m2 * 256
                    m4 = m3 * 256
                    data.extend(
                        [int(x) % 256 for x in [expt + 129, m1, m2, m3, m4]])
                else:
                    Err.log("Floating point constant out of range")
        except ValueError:
            Err.log("Expected: floating point")
        next = line.expect(',', 'EOL').type
        if next == 'EOL':
            break
    bytes = [IR.ConstantExpr(x) for x in data]
    result.append(IR.Node(ppt, "Byte", *bytes))
Пример #6
0
def pragmaCbmfloat(ppt, line, result):
    "Parses a string into a CBM BASIC format floating point number"
    data = []
    while True:
        try:
            v_str = line.expect("STRING").value
            v = float(v_str)
            if v == 0.0:
                data.extend([0,0,0,0,0])
            else:
                if v < 0.0:
                    sign = 128
                    v = -v
                else:
                    sign = 0
                expt = math.floor(math.log(v, 2))
                if expt >= -128 and expt <= 126:
                    mantissa = v / (2**expt)
                    m1 = (mantissa - 1.0) * 128 + sign
                    m2 = m1 * 256
                    m3 = m2 * 256
                    m4 = m3 * 256
                    data.extend([int(x) % 256 for x in [expt+129,m1,m2,m3,m4]])
                else:
                    Err.log("Floating point constant out of range")
        except ValueError:
            Err.log("Expected: floating point")
        next = line.expect(',', 'EOL').type
        if next == 'EOL':
            break
    bytes = [IR.ConstantExpr(x) for x in data]
    result.append(IR.Node(ppt, "Byte", *bytes))
    def expect(self, *tokens):
        """Reads a token from the ParseLine line and returns it if it's of a type
	in the sequence tokens.  Otherwise, it logs an error."""
        token = self.pop()
        if token.type not in tokens:
            Err.log('Expected: "' + '", "'.join(tokens) + '"')
        return token
Пример #8
0
	def expect(self, *tokens):
		"""Reads a token from the ParseLine line and returns it if it's of a type
	in the sequence tokens.  Otherwise, it logs an error."""
		token = self.pop()
		if token.type not in tokens: 
			Err.log('Expected: "'+'", "'.join(tokens)+'"')
		return token
Пример #9
0
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
Пример #10
0
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
Пример #11
0
 def visitMacroEnd(self, node, env):
     if self.inDef:
         Macro.endMacro()
         node.nodetype = "None"
         node.data = []
         self.inDef = False
     elif not self.nestedError:
         Err.log("Unmatched .macend")
 def __getitem__(self, item):
     if item[0] == '_':
         for dict in [self.dicts[i] for i in self.stack]:
             if item in dict: return dict[item]
     else:
         if item in self.dicts[0]: return self.dicts[0][item]
     Err.log("Unknown label '%s'" % item)
     return 0
Пример #13
0
	def __getitem__(self, item):
		if item[0] == '_':
			for dict in [self.dicts[i] for i in self.stack]:
				if item in dict: return dict[item]
		else:
			if item in self.dicts[0]: return self.dicts[0][item]
		Err.log("Unknown label '%s'" % item)
		return 0
Пример #14
0
 def visitMacroEnd(self, node, env):
     if self.inDef:
         Macro.endMacro()
         node.nodetype = "None"
         node.data = []
         self.inDef = 0
     elif not self.nestedError:
         Err.log("Unmatched .macend")
Пример #15
0
 def visitMacroBegin(self, node, env):
     if self.inDef:
         Err.log("Nested macro definition")
         self.nestedError = 1
     else:
         Macro.newMacro(node.data[0])
         node.nodetype = "None"
         node.data = []
         self.inDef = 1
Пример #16
0
 def visitMacroBegin(self, node, env):
     if self.inDef:
         Err.log("Nested macro definition")
         self.nestedError = True
     else:
         Macro.newMacro(node.data[0])
         node.nodetype = "None"
         node.data = []
         self.inDef = True
Пример #17
0
 def reset(self):
     "Clears out program counter, segment, and scoping information"
     self.pc = 0
     self.segmentdict = {}
     self.segment = "*text-default*"
     self.scopecount = 0
     if len(self.stack) > 1:
         Err.log("Unmatched .scope")
     self.stack = [0]
Пример #18
0
 def add_token(token):
     "Converts a substring into a single lexeme"
     if token == "":
         return
     if token == "0":
         result.append(Lexeme("NUM", 0))
         return
     firstchar = token[0]
     rest = token[1:]
     if firstchar == '"':
         result.append(Lexeme("STRING", rest))
         return
     elif firstchar in bases:
         try:
             result.append(Lexeme("NUM", long(rest, bases[firstchar][1])))
             return
         except ValueError:
             Err.log('Invalid ' + bases[firstchar][0] + ' constant: ' +
                     rest)
             result.append(Lexeme("NUM", 0))
             return
     elif firstchar.isdigit():
         try:
             result.append(Lexeme("NUM", long(token)))
         except ValueError:
             Err.log('Identifiers may not begin with a number')
             result.append(Lexeme("LABEL", "ERROR"))
         return
     elif firstchar == "'":
         if len(rest) == 1:
             result.append(Lexeme("NUM", ord(rest)))
         else:
             Err.log("Invalid character constant '" + rest + "'")
             result.append(Lexeme("NUM", 0))
         return
     elif firstchar in punctuation:
         if rest != "":
             Err.log("Internal lexer error!  '" + token + "' can't happen!")
         result.append(Lexeme(firstchar))
         return
     else:   # Label, opcode, or index register
         id = token.lower()
         if is_opcode(id):
             result.append(Lexeme("OPCODE", id))
         elif id == "x":
             result.append(Lexeme("X"))
         elif id == "y":
             result.append(Lexeme("Y"))
         elif id == "z":
             result.append(Lexeme("Z"))
         elif id == "sp":
             result.append(Lexeme("SP"))
         else:
             result.append(Lexeme("LABEL", id))
         return
     # should never reach here
     Err.log("Internal lexer error: add_token fall-through")
Пример #19
0
 def add_token(token):
     "Converts a substring into a single lexeme"
     if token == "":
         return
     if token == "0":
         result.append(Lexeme("NUM", 0))
         return
     firstchar = token[0]
     rest = token[1:]
     if firstchar == '"':
         result.append(Lexeme("STRING", rest))
         return
     elif firstchar in bases:
         try:
             result.append(Lexeme("NUM", int(rest, bases[firstchar][1])))
             return
         except ValueError:
             Err.log('Invalid ' + bases[firstchar][0] + ' constant: ' +
                     rest)
             result.append(Lexeme("NUM", 0))
             return
     elif firstchar.isdigit():
         try:
             result.append(Lexeme("NUM", int(token)))
         except ValueError:
             Err.log('Identifiers may not begin with a number')
             result.append(Lexeme("LABEL", "ERROR"))
         return
     elif firstchar == "'":
         if len(rest) == 1:
             result.append(Lexeme("NUM", ord(rest)))
         else:
             Err.log("Invalid character constant '" + rest + "'")
             result.append(Lexeme("NUM", 0))
         return
     elif firstchar in punctuation:
         if rest != "":
             Err.log("Internal lexer error!  '" + token + "' can't happen!")
         result.append(Lexeme(firstchar))
         return
     else:  # Label, opcode, or index register
         id = token.lower()
         if is_opcode(id):
             result.append(Lexeme("OPCODE", id))
         elif id == "x":
             result.append(Lexeme("X"))
         elif id == "y":
             result.append(Lexeme("Y"))
         elif id == "z":
             result.append(Lexeme("Z"))
         elif id == "sp":
             result.append(Lexeme("SP"))
         else:
             result.append(Lexeme("LABEL", id))
         return
     # should never reach here
     Err.log("Internal lexer error: add_token fall-through")
Пример #20
0
def endMacro():
    global currentname
    global currentbody
    global macros
    if currentname is None:
        Err.log("Internal error!  Ended a non-existent macro!")
    else:
        macros[currentname] = currentbody
        currentname = None
        currentbody = None
Пример #21
0
 def relativize(self, expr, env, arglen):
     "Convert an expression into one for use in relative addressing"
     arg = expr.value(env)
     arg = arg - (env.getPC() + arglen + 1)
     if arg < -128 or arg > 127:
         Err.log("Branch target out of bounds")
         arg = 0
     if arg < 0:
         arg += 256
     return IR.ConstantExpr(arg)
Пример #22
0
 def outputbyte(self, expr, env):
     'Outputs a byte, with range checking'
     if self.writeOK:
         val = expr.value(env)
         if val < 0x00 or val > 0xff:
             Err.log("Byte constant " + str(expr) + " out of range")
             val = 0
         self.output.append(int(val))
     else:
         Err.log("Attempt to write to data segment")
Пример #23
0
	def visitAdvance(self, node, env): 
		pc = env.getPC()
		target = node.data[0].value(env)
		if (pc > target):
			Err.log("Attempted to .advance backwards: $%x to $%x" % (pc, target))
		else:
			zero = IR.ConstantExpr(0)
			for i in xrange(target-pc): self.outputbyte(zero, env)
			self.filler += target-pc
		env.setPC(target)
Пример #24
0
	def visitLabel(self, node, env):
		(label, val) = node.data
		fulllabel = "%d:%s" % (env.stack[0], label)
		if fulllabel in self.labelmap and self.labelmap[fulllabel] is not node: 
			Err.log("Duplicate label definition '%s'" % label)
		if fulllabel not in self.labelmap:
			self.labelmap[fulllabel] = node
		if val.valid(env, self.PCvalid) and label not in env:
			env[label]=0
			self.changed=1
Пример #25
0
def expandMacro(ppt, name, arglist):
	global macros
	if name not in macros:
		Err.log("Undefined macro '%s'" % name)
		return IR.NullNode
	argexprs = [IR.Node(ppt, "Label", "_*%d" % i, arg) for (i, arg) in zip(xrange(1, sys.maxint), arglist)]
	bindexprs = [IR.Node(ppt, "Label", "_%d" % i, IR.LabelExpr("_*%d" % i)) for i in range(1, len(arglist)+1)]
	body = [IR.Node("%s->%s" % (ppt, node.ppt), node.nodetype, *node.data) for node in macros[name]]
	invocation = [IR.Node(ppt, "ScopeBegin")] + argexprs + [IR.Node(ppt, "ScopeBegin")] + bindexprs + body + [IR.Node(ppt, "ScopeEnd"), IR.Node(ppt, "ScopeEnd")]
	return IR.SequenceNode(ppt, invocation)
Пример #26
0
 def visitLabel(self, node, env):
     (label, val) = node.data
     fulllabel = "%d:%s" % (env.stack[0], label)
     if fulllabel in self.labelmap and self.labelmap[fulllabel] is not node:
         Err.log("Duplicate label definition '%s'" % label)
     if fulllabel not in self.labelmap:
         self.labelmap[fulllabel] = node
     if val.valid(env, self.PCvalid) and label not in env:
         env[label] = 0
         self.changed = 1
Пример #27
0
 def relativize(self, expr, env, arglen):
     "Convert an expression into one for use in relative addressing"
     arg = expr.value(env)
     arg = arg - (env.getPC() + arglen + 1)
     if arg < -128 or arg > 127:
         Err.log("Branch target out of bounds")
         arg = 0
     if arg < 0:
         arg += 256
     return IR.ConstantExpr(arg)
Пример #28
0
 def outputbyte(self, expr, env):
     'Outputs a byte, with range checking'
     if self.writeOK:
         val = expr.value(env)
         if val < 0x00 or val > 0xff:
             Err.log("Byte constant " + str(expr) + " out of range")
             val = 0
         self.output.append(int(val))
     else:
         Err.log("Attempt to write to data segment")
Пример #29
0
def endMacro():
    global currentname
    global currentbody
    global macros
    if currentname is None:
        Err.log("Internal error!  Ended a non-existent macro!")
    else:
        macros[currentname] = currentbody
        currentname = None
        currentbody = None
Пример #30
0
 def outputword_be(self, expr, env):
     'Outputs a big-endian word, with range checking'
     if self.writeOK:
         val = expr.value(env)
         if val < 0x0000 or val > 0xFFFF:
             Err.log("Word constant " + str(expr) + " out of range")
             val = 0
         self.output.append(int((val >> 8) & 0xFF))
         self.output.append(int(val & 0xFF))
     else:
         Err.log("Attempt to write to data segment")
Пример #31
0
 def outputword_be(self, expr, env):
     'Outputs a big-endian word, with range checking'
     if self.writeOK:
         val = expr.value(env)
         if val < 0x0000 or val > 0xFFFF:
             Err.log("Word constant " + str(expr) + " out of range")
             val = 0
         self.output.append(int((val >> 8) & 0xFF))
         self.output.append(int(val & 0xFF))
     else:
         Err.log("Attempt to write to data segment")
Пример #32
0
def newMacro(name):
    "Start creating a new macro with the specified name."
    global currentname
    global currentbody
    global macros
    if currentname is not None:
        Err.log("Internal error!  Nested macro attempt!")
    else:
        if name in macros:
            Err.log("Duplicate macro definition '%s'" % name)
        currentname = name
        currentbody = []
Пример #33
0
	def go(self, node, env):
		"""Runs this FixPoint's passes, in order, until the fixpoint
		is true.  Always runs the passes at least once."""
		for i in xrange(100):
			if Err.count != 0: break
			for p in self.passes:
				p.go(node, env)
			if Err.count != 0: break
			if self.fixpoint(): break 
			if Cmd.verbose > 1: print "Fixpoint failed, looping back"
		else:
			Err.log("Can't make %s converge!  Maybe there's a recursive dependency somewhere?" % self.name)
Пример #34
0
 def visitAdvance(self, node, env):
     pc = env.getPC()
     target = node.data[0].value(env)
     if (pc > target):
         Err.log("Attempted to .advance backwards: $%x to $%x" %
                 (pc, target))
     else:
         zero = IR.ConstantExpr(0)
         for i in range(target - pc):
             self.outputbyte(zero, env)
         self.filler += target - pc
     env.setPC(target)
Пример #35
0
def newMacro(name):
    "Start creating a new macro with the specified name."
    global currentname
    global currentbody
    global macros
    if currentname is not None:
        Err.log("Internal error!  Nested macro attempt!")
    else:
        if name in macros:
            Err.log("Duplicate macro definition '%s'" % name)
        currentname = name
        currentbody = []
Пример #36
0
 def visitAdvance(self, node, env):
     pc = env.getPC()
     target = node.data[0].value(env)
     if (pc > target):
         Err.log("Attempted to .advance backwards: $%x to $%x" %
                 (pc, target))
     else:
         created = []
         for i in xrange(target - pc):
             self.outputbyte(node.data[1], env, created)
         self.filler += target - pc
         self.registerData(created, env.getPC())
     env.setPC(target)
Пример #37
0
 def visitAdvance(self, node, env):
     pc = env.getPC()
     target = node.data[0].value(env)
     if (pc > target):
         Err.log("Attempted to .advance backwards: $%x to $%x" %
                 (pc, target))
     else:
         created = []
         for i in xrange(target - pc):
             self.outputbyte(node.data[1], env, created)
         self.filler += target - pc
         self.registerData(created, env.getPC())
     env.setPC(target)
Пример #38
0
 def outputword(self, expr, env, tee=None):
     'Outputs a little-endian word, with range checking'
     if self.writeOK:
         val = expr.value(env)
         if val < 0x0000 or val > 0xFFFF:
             Err.log("Word constant " + str(expr) + " out of range")
             val = 0
         self.output.append(int(val & 0xFF))
         self.output.append(int((val >> 8) & 0xFF))
         if tee is not None:
             tee.extend(self.output[-2:])
     else:
         Err.log("Attempt to write to data segment")
Пример #39
0
def pragmaCharmapbin(ppt, line, result):
	"Load a new character map from a file"
	global currentcharmap
	filename = line.expect("STRING").value
	line.expect("EOL")
	if type(filename)==str:
		f = file(filename, "rb")
		bytes = f.read()
		f.close()
		if len(bytes)==256:
			currentcharmap = bytes
		else:
			Err.log("Character map "+filename+" not 256 bytes long")
Пример #40
0
 def outputword(self, expr, env, tee=None):
     'Outputs a little-endian word, with range checking'
     if self.writeOK:
         val = expr.value(env)
         if val < 0x0000 or val > 0xFFFF:
             Err.log("Word constant " + str(expr) + " out of range")
             val = 0
         self.output.append(int(val & 0xFF))
         self.output.append(int((val >> 8) & 0xFF))
         if tee is not None:
             tee.extend(self.output[-2:])
     else:
         Err.log("Attempt to write to data segment")
Пример #41
0
    def go(self, node, env):
        """Runs this FixPoint's passes, in order, until the fixpoint
		is true.  Always runs the passes at least once."""
        for i in range(100):
            if Err.count != 0: break
            for p in self.passes:
                p.go(node, env)
            if Err.count != 0: break
            if self.fixpoint(): break
            if Cmd.verbose > 1: print("Fixpoint failed, looping back")
        else:
            Err.log(
                "Can't make %s converge!  Maybe there's a recursive dependency somewhere?"
                % self.name)
Пример #42
0
def pragmaCharmap(ppt, line, result):
	"Modify the character map."
	global currentcharmap, basecharmap
	bytes = readData(line)
	if len(bytes) == 0:
		currentcharmap = basecharmap
	else:
		try:
			base = bytes[0].data
			newsubstr = "".join([chr(x.data) for x in bytes[1:]])
			currentcharmap = currentcharmap[:base] + newsubstr + currentcharmap[base+len(newsubstr):]
			if len(currentcharmap) != 256 or base < 0 or base > 255:
				Err.log("Charmap replacement out of range")
				currentcharmap = currentcharmap[:256]
		except ValueError:
			Err.log("Illegal character in .charmap directive")
Пример #43
0
 def expect(self, *tokens):
     """Reads a token from the ParseLine line and returns it if it's of a
 type in the sequence tokens.  Otherwise, it logs an error."""
     token = self.pop()
     if token.type in tokens:
         return token
     if "LABEL" in tokens:
         if token.type in ["X", "Y"]:
             token.value = token.type.lower()
             token.type = "LABEL"
             return token
         elif token.type == "OPCODE":
             token.type = "LABEL"
             return token
     Err.log('Expected: "' + '", "'.join(tokens) + '"')
     return token
Пример #44
0
def parse_file(ppt, filename):
	"Loads a .P65 source file, and returns an IR list."
	Err.currentpoint = ppt
	if Cmd.verbose > 0: print "Loading "+filename
	try:
		f = file(filename)
		linelist = f.readlines()
		f.close()
		pptlist = ["%s:%d" % (filename, i+1) for i in range(len(linelist))]
		lexlist = map(lex, pptlist, linelist)
		IRlist = map(parse_line, pptlist, lexlist)
		IRlist = [node for node in IRlist if node is not IR.NullNode]
		return IR.SequenceNode(ppt, IRlist)
	except IOError:
		Err.log ("Could not read "+filename)
		return IR.NullNode
Пример #45
0
 def visitLabel(self, node, env):
     (label, val) = node.data
     fulllabel = "%d:%s" % (env.stack[0], label)
     if fulllabel in self.labelmap and self.labelmap[fulllabel] is not node:
         Err.log("Duplicate label definition '%s'" % label)
     if fulllabel not in self.labelmap:
         self.labelmap[fulllabel] = node
     if val.valid(env, self.PCvalid) and label not in env:
         env[label] = 0
         self.changed = True
     if label in ['a', 'x', 'y'] and self.runcount == 1:
         print>>sys.stderr, str(node.ppt) + ": WARNING: " \
             "using register name as label"
     if label in Ops.opcodes and self.runcount == 1:
         print>>sys.stderr, str(node.ppt) + ": WARNING: " \
             "using opcode name as label"
Пример #46
0
 def visitLabel(self, node, env):
     (label, val) = node.data
     fulllabel = "%d:%s" % (env.stack[0], label)
     if fulllabel in self.labelmap and self.labelmap[fulllabel] is not node:
         Err.log("Duplicate label definition '%s'" % label)
     if fulllabel not in self.labelmap:
         self.labelmap[fulllabel] = node
     if val.valid(env, self.PCvalid) and label not in env:
         env[label] = 0
         self.changed = True
     if label in ['a', 'x', 'y'] and self.runcount == 1:
         print>>sys.stderr, str(node.ppt) + ": WARNING: " \
             "using register name as label"
     if label in Ops.opcodes and self.runcount == 1:
         print>>sys.stderr, str(node.ppt) + ": WARNING: " \
             "using opcode name as label"
def parse_file(ppt, filename):
    "Loads a .P65 source file, and returns an IR list."
    Err.currentpoint = ppt
    if Cmd.verbose > 0: print("Loading " + filename)
    try:
        f = open(filename, 'r', encoding='utf-8')
        linelist = f.readlines()
        f.close()
        pptlist = ["%s:%d" % (filename, i + 1) for i in range(len(linelist))]
        lexlist = map(lex, pptlist, linelist)
        IRlist = map(parse_line, pptlist, lexlist)
        IRlist = [node for node in IRlist if node is not IR.NullNode]
        return IR.SequenceNode(ppt, IRlist)
    except IOError:
        Err.log("Could not read " + filename)
        return IR.NullNode
Пример #48
0
 def expect(self, *tokens):
     """Reads a token from the ParseLine line and returns it if it's of a
 type in the sequence tokens.  Otherwise, it logs an error."""
     token = self.pop()
     if token.type in tokens:
         return token
     if 'LABEL' in tokens:
         if token.type in ['X', 'Y', 'Z', 'SP']:
             token.value = token.type.lower()
             token.type = 'LABEL'
             return token
         elif token.type == 'OPCODE':
             token.type = 'LABEL'
             return token
     Err.log('Expected: "' + '", "'.join(tokens) + '"')
     return token
Пример #49
0
 def expect(self, *tokens):
     """Reads a token from the ParseLine line and returns it if it's of a
 type in the sequence tokens.  Otherwise, it logs an error."""
     token = self.pop()
     if token.type in tokens:
         return token
     if 'LABEL' in tokens:
         if token.type in ['X', 'Y', 'Z', 'SP']:
             token.value = token.type.lower()
             token.type = 'LABEL'
             return token
         elif token.type == 'OPCODE':
             token.type = 'LABEL'
             return token
     Err.log('Expected: "' + '", "'.join(tokens) + '"')
     return token
Пример #50
0
def pragmaCharmap(ppt, line, result):
    "Modify the character map."
    global currentcharmap, basecharmap
    if str(line.lookahead(0)) == "EOL":
        currentcharmap = basecharmap
    else:
        bytes = readData(line)
        try:
            base = bytes[0].data
            newsubstr = "".join([chr(x.data) for x in bytes[1:]])
            currentcharmap = currentcharmap[:base] + newsubstr + \
                             currentcharmap[base + len(newsubstr):]
            if len(currentcharmap) != 256 or base < 0 or base > 255:
                Err.log("Charmap replacement out of range")
                currentcharmap = currentcharmap[:256]
        except ValueError:
            Err.log("Illegal character in .charmap directive")
Пример #51
0
def pragmaCharmapbin(ppt, line, result):
    "Load a new character map from a file"
    global currentcharmap
    filename = line.expect("STRING").value
    line.expect("EOL")
    if type(filename) == str:
        try:
            f = file(os.path.join(FE.context_directory, filename), "rb")
            bytes = f.read()
            f.close()
        except IOError:
            Err.log("Could not read " + filename)
            return
        if len(bytes) == 256:
            currentcharmap = bytes
        else:
            Err.log("Character map " + filename + " not 256 bytes long")
Пример #52
0
def pragmaCharmapbin(ppt, line, result):
    "Load a new character map from a file"
    global currentcharmap
    filename = line.expect("STRING").value
    line.expect("EOL")
    if type(filename) == str:
        try:
            f = open(os.path.join(FE.context_directory, filename), "rb")
            bytes = f.read()
            f.close()
        except IOError:
            Err.log("Could not read " + filename)
            return
        if len(bytes) == 256:
            currentcharmap = bytes
        else:
            Err.log("Character map " + filename + " not 256 bytes long")
Пример #53
0
def parse_file(ppt, filename, load_once=False):
    "Loads an Ophis source file, and returns an IR list."
    global context_directory, loadedfiles
    Err.currentpoint = ppt
    old_context = context_directory
    if filename != '-':
        if context_directory is not None:
            filename = os.path.abspath(
                os.path.join(context_directory, filename))
        if load_once and filename in loadedfiles:
            if Cmd.print_loaded_files:
                print("Skipping " + filename, file=sys.stderr)
            return IR.NullNode
        loadedfiles[filename] = True
    if Cmd.print_loaded_files:
        if filename != '-':
            print("Loading " + filename, file=sys.stderr)
        else:
            print("Loading from standard input", file=sys.stderr)
    try:
        if filename != '-':
            if context_directory is not None:
                filename = os.path.join(context_directory, filename)
            f = open(filename, "rt")
            linelist = f.readlines()
            f.close()
            context_directory = os.path.abspath(os.path.dirname(filename))
        else:
            context_directory = os.getcwd()
            linelist = sys.stdin.readlines()
        pptlist = ["%s:%d" % (filename, i + 1) for i in range(len(linelist))]
        lexlist = list(map(lex, pptlist, linelist))
        IRlist = list(map(parse_line, pptlist, lexlist))
        IRlist = [node for node in IRlist if node is not IR.NullNode]
        context_directory = old_context
        return IR.SequenceNode(ppt, IRlist)
    except IOError:
        Err.log("Could not read " + filename)
        context_directory = old_context
        return IR.NullNode
Пример #54
0
def parse_file(ppt, filename, load_once=False):
    "Loads an Ophis source file, and returns an IR list."
    global context_directory, loadedfiles
    Err.currentpoint = ppt
    old_context = context_directory
    if filename != '-':
        if context_directory is not None:
            filename = os.path.abspath(os.path.join(context_directory,
                                                    filename))
        if load_once and filename in loadedfiles:
            if Cmd.print_loaded_files:
                print>>sys.stderr, "Skipping " + filename
            return IR.NullNode
        loadedfiles[filename] = True
    if Cmd.print_loaded_files:
        if filename != '-':
            print>>sys.stderr, "Loading " + filename
        else:
            print>>sys.stderr, "Loading from standard input"
    try:
        if filename != '-':
            if context_directory is not None:
                filename = os.path.join(context_directory, filename)
            f = file(filename)
            linelist = f.readlines()
            f.close()
            context_directory = os.path.abspath(os.path.dirname(filename))
        else:
            context_directory = os.getcwd()
            linelist = sys.stdin.readlines()
        pptlist = ["%s:%d" % (filename, i + 1) for i in range(len(linelist))]
        lexlist = map(lex, pptlist, linelist)
        IRlist = map(parse_line, pptlist, lexlist)
        IRlist = [node for node in IRlist if node is not IR.NullNode]
        context_directory = old_context
        return IR.SequenceNode(ppt, IRlist)
    except IOError:
        Err.log("Could not read " + filename)
        context_directory = old_context
        return IR.NullNode
Пример #55
0
 def assemble(self, node, mode, env):
     "A generic instruction called by the visitor methods themselves"
     (opcode, expr) = node.data
     bin_op = Ops.opcodes[opcode][mode]
     if bin_op is None:
         Err.log('%s does not have mode "%s"' %
                 (opcode.upper(), Ops.modes[mode]))
         return
     self.outputbyte(IR.ConstantExpr(bin_op), env)
     arglen = Ops.lengths[mode]
     if mode == 11:  # Special handling for relative mode
         arg = expr.value(env)
         arg = arg - (env.getPC() + 2)
         if arg < -128 or arg > 127:
             Err.log("Branch target out of bounds")
             arg = 0
         if arg < 0: arg += 256
         expr = IR.ConstantExpr(arg)
     if arglen == 1: self.outputbyte(expr, env)
     if arglen == 2: self.outputword(expr, env)
     env.incPC(1 + arglen)
     self.code += 1 + arglen
Пример #56
0
 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')
Пример #57
0
 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')
Пример #58
0
 def visitByteRange(self, node, env):
     offset = node.data[0].value(env) + 2
     length = node.data[1].value(env)
     if offset < 2:
         Err.log("Negative offset in .incbin")
     elif offset > len(node.data):
         Err.log("Offset extends past end of file")
     elif length < 0:
         Err.log("Negative length")
     elif offset + length > len(node.data):
         Err.log("File too small for .incbin subrange")
     else:
         created = []
         for expr in node.data[offset:(offset + length)]:
             self.outputbyte(expr, env, created)
         self.registerData(created, env.getPC())
         env.incPC(length)
         self.data += length
Пример #59
0
 def visitCheckPC(self, node, env):
     pc = env.getPC()
     target = node.data[0].value(env)
     if (pc > target):
         Err.log(".checkpc assertion failed: $%x > $%x" % (pc, target))