Esempio n. 1
0
    def exit_proc(self, lineno):
        """ Exits current procedure. Local labels are transferred to global
        scope unless they have been marked as local ones.

        Raises an error if no current local context (stack underflow)
        """
        __DEBUG__('Exiting current scope from lineno %i' % lineno)

        if len(self.local_labels) <= 1:
            error(lineno, 'ENDP in global scope (with no PROC)')
            return

        for label in self.local_labels[-1].values():
            if label.local:
                if not label.defined:
                    error(lineno, "Undefined LOCAL label '%s'" % label.name)
                    return
                continue

            name = label.name
            _lineno = label.lineno
            value = label.value

            if name not in self.global_labels.keys():
                self.global_labels[name] = label
            else:
                self.global_labels[name].define(value, _lineno)

        self.local_labels.pop()  # Removes current context
        self.scopes.pop()
Esempio n. 2
0
def p_asm_ld8(p):
    """ asm : LD reg8 COMMA reg8_hl
            | LD reg8_hl COMMA reg8
            | LD reg8 COMMA reg8
            | LD SP COMMA HL
            | LD SP COMMA reg16i
            | LD A COMMA reg8
            | LD reg8 COMMA A
            | LD reg8_hl COMMA A
            | LD A COMMA reg8_hl
            | LD A COMMA A
            | LD A COMMA I
            | LD I COMMA A
            | LD A COMMA R
            | LD R COMMA A
            | LD A COMMA reg8i
            | LD reg8i COMMA A
            | LD reg8 COMMA reg8i
            | LD reg8i COMMA regBCDE
            | LD reg8i COMMA reg8i
    """
    if p[2] in ('H', 'L') and p[4] in ('IXH', 'IXL', 'IYH', 'IYL'):
        p[0] = None
        error(p.lineno(0), "Unexpected token '%s'" % p[4])
    else:
        p[0] = Asm(p.lineno(1), 'LD %s,%s' % (p[2], p[4]))
Esempio n. 3
0
def p_ind8_I(p):
    """    reg8_I : LP IX expr RP
               | LP IY expr RP
               | LP IX PLUS pexpr RP
               | LP IX MINUS pexpr RP
               | LP IY PLUS pexpr RP
               | LP IY MINUS pexpr RP
    """
    if len(p) == 6:
        expr = p[4]
        sign = p[3]
    else:
        expr = p[3]
        gen_ = expr.inorder()
        first_expr = next(gen_, '')
        if first_expr and first_expr.parent:
            if len(first_expr.parent.children) == 2:
                first_token = first_expr.symbol.item
            else:
                first_token = first_expr.parent.symbol.item
        else:
            first_token = '<nothing>'
        if first_token not in ('-', '+'):
            error(
                p.lineno(2),
                "Unexpected token '{}'. Expected '+' or '-'".format(
                    first_token))
        sign = '+'

    if sign == '-':
        expr = Expr.makenode(Container(sign, p.lineno(2)), expr)

    p[0] = ('(%s+N)' % p[2], expr)
Esempio n. 4
0
    def set_org(self, value, lineno):
        """ Sets a new ORG value
        """
        if value < 0 or value > MAX_MEM:
            error(lineno, "Memory ORG out of range [0 .. 65535]. Current value: %i" % value)

        self.index = self.ORG = value
Esempio n. 5
0
    def __init__(self, lineno, asm, arg=None):
        self.lineno = lineno

        if asm not in ('DEFB', 'DEFS', 'DEFW'):
            try:
                super(Asm, self).__init__(asm, arg)
            except Error as v:
                error(lineno, v.msg)
                return

            self.pending = len([
                x for x in self.arg
                if isinstance(x, Expr) and x.try_eval() is None
            ]) > 0

            if not self.pending:
                self.arg = self.argval()
        else:
            self.asm = asm
            self.pending = True

            if isinstance(arg, str):
                self.arg = tuple(
                    [Expr(Container(ord(x), lineno)) for x in arg])
            else:
                self.arg = arg

            self.arg_num = len(self.arg)
Esempio n. 6
0
def p_error(p):
    if p is not None:
        if p.type != 'NEWLINE':
            error(p.lineno, "Syntax error. Unexpected token '%s' [%s]" % (p.value, p.type))
        else:
            error(p.lineno, "Syntax error. Unexpected end of line [NEWLINE]")
    else:
        OPTIONS.stderr.value.write("General syntax error at assembler (unexpected End of File?)")
        gl.has_errors += 1
Esempio n. 7
0
    def __set_byte(self, byte, lineno):
        """ Sets a byte at the current location,
        and increments org in one. Raises an error if org > MAX_MEMORY
        """
        if byte < 0 or byte > 255:
            error(lineno, 'Invalid byte value %i' % byte)

        self.memory_bytes[self.org] = byte
        self.index += 1  # Increment current memory pointer
Esempio n. 8
0
    def define(self, value, lineno, namespace=None):
        """ Defines label value. It can be anything. Even an AST
        """
        if self.defined:
            error(lineno, "label '%s' already defined at line %i" % (self.name, self.lineno))

        self.value = value
        self.lineno = lineno
        self.namespace = NAMESPACE if namespace is None else namespace
Esempio n. 9
0
def p_im(p):
    """ asm : IM expr
    """
    val = p[2].eval()
    if val not in (0, 1, 2):
        error(p.lineno(1), 'Invalid IM number %i' % val)
        p[0] = None
        return

    p[0] = Asm(p.lineno(1), 'IM %i' % val)
Esempio n. 10
0
def p_align(p):
    """ asm : ALIGN expr
            | ALIGN pexpr
    """
    align = p[2].eval()
    if align < 2:
        error(p.lineno(1), "ALIGN value must be greater than 1")
        return

    MEMORY.set_org(MEMORY.org + (align - MEMORY.org % align) % align, p.lineno(1))
Esempio n. 11
0
    def resolve(self, lineno):
        """ Evaluates label value. Exits with error (unresolved) if value is none
        """
        if not self.defined:
            error(lineno, "Undeclared label '%s'" % self.name)

        if isinstance(self.value, Expr):
            return self.value.eval()

        return self.value
Esempio n. 12
0
def p_DEFS(p):  # Define bytes
    """ asm : DEFS number_list
    """
    if len(p[2]) > 2:
        error(p.lineno(1), "too many arguments for DEFS")

    if len(p[2]) < 2:
        num = Expr.makenode(Container(0, p.lineno(1)))  # Defaults to 0
        p[2] = p[2] + (num, )

    p[0] = Asm(p.lineno(1), 'DEFS', p[2])
Esempio n. 13
0
def p_rst(p):
    """ asm : RST expr
    """
    val = p[2].eval()

    if val not in (0, 8, 16, 24, 32, 40, 48, 56):
        error(p.lineno(1), 'Invalid RST number %i' % val)
        p[0] = None
        return

    p[0] = Asm(p.lineno(1), 'RST %XH' % val)
Esempio n. 14
0
def p_BIT_ix(p):
    """ asm : bitop expr COMMA reg8_I
            | bitop pexpr COMMA reg8_I
    """
    bit = p[2].eval()
    if bit < 0 or bit > 7:
        error(p.lineno(3), 'Invalid bit position %i. Must be in [0..7]' % bit)
        p[0] = None
        return

    p[0] = Asm(p.lineno(3), '%s %i,%s' % (p[1], bit, p[4][0]), p[4][1])
Esempio n. 15
0
def assemble(input_):
    """ Assembles input string, and leave the result in the
    MEMORY global object
    """
    global MEMORY

    if MEMORY is None:
        MEMORY = Memory()

    parser.parse(input_, lexer=LEXER, debug=OPTIONS.Debug.value > 2)
    if len(MEMORY.scopes):
        error(MEMORY.scopes[-1], 'Missing ENDP to close this scope')

    return gl.has_errors
Esempio n. 16
0
    def try_eval(self):
        """ Recursively evals the node. Returns None
        if it is still unresolved.
        """
        item = self.symbol.item

        if isinstance(item, int):
            return item

        if isinstance(item, Label):
            if item.defined:
                if isinstance(item.value, Expr):
                    return item.value.try_eval()
                else:
                    return item.value
            else:
                if Expr.ignore:
                    return None

                # Try to resolve into the global namespace
                error(self.symbol.lineno, "Undefined label '%s'" % item.name)
                return None

        try:
            if isinstance(item, tuple):
                return tuple([x.try_eval() for x in item])

            if isinstance(item, list):
                return [x.try_eval() for x in item]

            if item == '-' and len(self.children) == 1:
                return -self.left.try_eval()

            if item == '+' and len(self.children) == 1:
                return self.left.try_eval()

            try:
                return self.funct[item](self.left.try_eval(),
                                        self.right.try_eval())
            except ZeroDivisionError:
                error(self.symbol.lineno, 'Division by 0')
            except KeyError:
                pass

        except TypeError:
            pass

        return None
Esempio n. 17
0
def p_incbin(p):
    """ asm : INCBIN STRING
    """
    try:
        fname = zxbpp.search_filename(p[2], p.lineno(2), local_first=True)
        if not fname:
            p[0] = None
            return
        with api.utils.open_file(fname, 'rb') as f:
            filecontent = f.read()
    except IOError:
        error(p.lineno(2), "cannot read file '%s'" % p[2])
        p[0] = None
        return

    p[0] = Asm(p.lineno(1), 'DEFB', filecontent)
Esempio n. 18
0
    def dump(self):
        """ Returns a tuple containing code ORG (origin address), and a list of bytes (OUTPUT)
        """
        org = min(self.memory_bytes.keys())  # Org is the lowest one
        OUTPUT = []
        align = []

        for label in self.global_labels.values():
            if not label.defined:
                error(label.lineno, "Undefined GLOBAL label '%s'" % label.name)

        for i in range(org, max(self.memory_bytes.keys()) + 1):
            if gl.has_errors:
                return org, OUTPUT

            try:
                try:
                    a = [x for x in self.orgs[i]
                         if isinstance(x, Asm)]  # search for asm instructions

                    if not a:
                        align.append(
                            0)  # Fill with ZEROes not used memory regions
                        continue

                    OUTPUT += align
                    align = []
                    a = a[0]
                    if a.pending:
                        a.arg = a.argval()
                        a.pending = False
                        tmp = a.bytes()

                        for r in range(len(tmp)):
                            self.memory_bytes[i + r] = tmp[r]
                except KeyError:
                    pass

                OUTPUT.append(self.memory_bytes[i])

            except KeyError:
                OUTPUT.append(0)  # Fill with ZEROes not used memory regions

        return org, OUTPUT
Esempio n. 19
0
    def argval(self):
        """ Solve args values or raise errors if not
        defined yet
        """
        if gl.has_errors:
            return [None]

        if self.asm in ('DEFB', 'DEFS', 'DEFW'):
            return tuple(
                [x.eval() if isinstance(x, Expr) else x for x in self.arg])

        self.arg = tuple(
            [x if not isinstance(x, Expr) else x.eval() for x in self.arg])
        if self.asm.split(' ')[0] in ('JR', 'DJNZ'):  # A relative jump?
            if self.arg[0] < -128 or self.arg[0] > 127:
                error(self.lineno, 'Relative jump out of range')
                return [None]

        return super(Asm, self).argval()