micro_asm.py revision 4503
14483Sgblack@eecs.umich.edu# Copyright (c) 2003-2005 The Regents of The University of Michigan
24483Sgblack@eecs.umich.edu# All rights reserved.
34483Sgblack@eecs.umich.edu#
44483Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
54483Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are
64483Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright
74483Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
84483Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
94483Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
104483Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution;
114483Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its
124483Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from
134483Sgblack@eecs.umich.edu# this software without specific prior written permission.
144483Sgblack@eecs.umich.edu#
154483Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
164483Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
174483Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
184483Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
194483Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
204483Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
214483Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
224483Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
234483Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
244483Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
254483Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
264483Sgblack@eecs.umich.edu#
274483Sgblack@eecs.umich.edu# Authors: Gabe Black
284483Sgblack@eecs.umich.edu
294483Sgblack@eecs.umich.eduimport os
304483Sgblack@eecs.umich.eduimport sys
314483Sgblack@eecs.umich.eduimport re
324483Sgblack@eecs.umich.eduimport string
334483Sgblack@eecs.umich.eduimport traceback
344483Sgblack@eecs.umich.edu# get type names
354483Sgblack@eecs.umich.edufrom types import *
364483Sgblack@eecs.umich.edu
374483Sgblack@eecs.umich.edu# Prepend the directory where the PLY lex & yacc modules are found
384483Sgblack@eecs.umich.edu# to the search path.
394483Sgblack@eecs.umich.edusys.path[0:0] = [os.environ['M5_PLY']]
404483Sgblack@eecs.umich.edu
414483Sgblack@eecs.umich.edufrom ply import lex
424483Sgblack@eecs.umich.edufrom ply import yacc
434483Sgblack@eecs.umich.edu
444483Sgblack@eecs.umich.edu##########################################################################
454483Sgblack@eecs.umich.edu#
464483Sgblack@eecs.umich.edu# Base classes for use outside of the assembler
474483Sgblack@eecs.umich.edu#
484483Sgblack@eecs.umich.edu##########################################################################
494483Sgblack@eecs.umich.edu
504483Sgblack@eecs.umich.educlass Micro_Container(object):
514483Sgblack@eecs.umich.edu    def __init__(self, name):
524483Sgblack@eecs.umich.edu        self.microops = []
534483Sgblack@eecs.umich.edu        self.name = name
544483Sgblack@eecs.umich.edu        self.directives = {}
554483Sgblack@eecs.umich.edu        self.micro_classes = {}
564483Sgblack@eecs.umich.edu        self.labels = {}
574483Sgblack@eecs.umich.edu
584483Sgblack@eecs.umich.edu    def add_microop(self, microop):
594483Sgblack@eecs.umich.edu        self.microops.append(microop)
604483Sgblack@eecs.umich.edu
614483Sgblack@eecs.umich.edu    def __str__(self):
624483Sgblack@eecs.umich.edu        string = "%s:\n" % self.name
634483Sgblack@eecs.umich.edu        for microop in self.microops:
644483Sgblack@eecs.umich.edu            string += "  %s\n" % microop
654483Sgblack@eecs.umich.edu        return string
664483Sgblack@eecs.umich.edu
674483Sgblack@eecs.umich.educlass Macroop(Micro_Container):
684483Sgblack@eecs.umich.edu    pass
694483Sgblack@eecs.umich.edu
704483Sgblack@eecs.umich.educlass Rom(Micro_Container):
714483Sgblack@eecs.umich.edu    def __init__(self, name):
724483Sgblack@eecs.umich.edu        super(Rom, self).__init__(name)
734483Sgblack@eecs.umich.edu        self.externs = {}
744483Sgblack@eecs.umich.edu
754483Sgblack@eecs.umich.edu##########################################################################
764483Sgblack@eecs.umich.edu#
774483Sgblack@eecs.umich.edu# Support classes
784483Sgblack@eecs.umich.edu#
794483Sgblack@eecs.umich.edu##########################################################################
804483Sgblack@eecs.umich.edu
814483Sgblack@eecs.umich.educlass Label(object):
824483Sgblack@eecs.umich.edu    def __init__(self):
834483Sgblack@eecs.umich.edu        self.extern = False
844483Sgblack@eecs.umich.edu        self.name = ""
854483Sgblack@eecs.umich.edu
864483Sgblack@eecs.umich.educlass Block(object):
874483Sgblack@eecs.umich.edu    def __init__(self):
884483Sgblack@eecs.umich.edu        self.statements = []
894483Sgblack@eecs.umich.edu
904483Sgblack@eecs.umich.educlass Statement(object):
914483Sgblack@eecs.umich.edu    def __init__(self):
924483Sgblack@eecs.umich.edu        self.is_microop = False
934483Sgblack@eecs.umich.edu        self.is_directive = False
944503Sgblack@eecs.umich.edu        self.params = ""
954483Sgblack@eecs.umich.edu
964483Sgblack@eecs.umich.educlass Microop(Statement):
974483Sgblack@eecs.umich.edu    def __init__(self):
984483Sgblack@eecs.umich.edu        super(Microop, self).__init__()
994483Sgblack@eecs.umich.edu        self.mnemonic = ""
1004483Sgblack@eecs.umich.edu        self.labels = []
1014483Sgblack@eecs.umich.edu        self.is_microop = True
1024483Sgblack@eecs.umich.edu
1034483Sgblack@eecs.umich.educlass Directive(Statement):
1044483Sgblack@eecs.umich.edu    def __init__(self):
1054483Sgblack@eecs.umich.edu        super(Directive, self).__init__()
1064483Sgblack@eecs.umich.edu        self.name = ""
1074483Sgblack@eecs.umich.edu        self.is_directive = True
1084483Sgblack@eecs.umich.edu
1094483Sgblack@eecs.umich.edu##########################################################################
1104483Sgblack@eecs.umich.edu#
1114483Sgblack@eecs.umich.edu# Functions that handle common tasks
1124483Sgblack@eecs.umich.edu#
1134483Sgblack@eecs.umich.edu##########################################################################
1144483Sgblack@eecs.umich.edu
1154483Sgblack@eecs.umich.edudef print_error(message):
1164483Sgblack@eecs.umich.edu    print
1174483Sgblack@eecs.umich.edu    print "*** %s" % message
1184483Sgblack@eecs.umich.edu    print
1194483Sgblack@eecs.umich.edu
1204483Sgblack@eecs.umich.edudef handle_statement(parser, container, statement):
1214483Sgblack@eecs.umich.edu    if statement.is_microop:
1224483Sgblack@eecs.umich.edu        try:
1234483Sgblack@eecs.umich.edu            microop = eval('parser.microops[statement.mnemonic](%s)' %
1244483Sgblack@eecs.umich.edu                    statement.params)
1254483Sgblack@eecs.umich.edu        except:
1264483Sgblack@eecs.umich.edu            print_error("Error creating microop object.")
1274483Sgblack@eecs.umich.edu            raise
1284483Sgblack@eecs.umich.edu        try:
1294483Sgblack@eecs.umich.edu            for label in statement.labels:
1304483Sgblack@eecs.umich.edu                container.labels[label.name] = microop
1314483Sgblack@eecs.umich.edu                if label.extern:
1324483Sgblack@eecs.umich.edu                    container.externs[label.name] = microop
1334483Sgblack@eecs.umich.edu            container.add_microop(microop)
1344483Sgblack@eecs.umich.edu        except:
1354483Sgblack@eecs.umich.edu            print_error("Error adding microop.")
1364483Sgblack@eecs.umich.edu            raise
1374483Sgblack@eecs.umich.edu    elif statement.is_directive:
1384483Sgblack@eecs.umich.edu        try:
1394503Sgblack@eecs.umich.edu            eval('container.directives[statement.name](%s)' % statement.params)
1404483Sgblack@eecs.umich.edu        except:
1414483Sgblack@eecs.umich.edu            print_error("Error executing directive.")
1424483Sgblack@eecs.umich.edu            print container.directives
1434483Sgblack@eecs.umich.edu            raise
1444483Sgblack@eecs.umich.edu    else:
1454483Sgblack@eecs.umich.edu        raise Exception, "Didn't recognize the type of statement", statement
1464483Sgblack@eecs.umich.edu
1474483Sgblack@eecs.umich.edu##########################################################################
1484483Sgblack@eecs.umich.edu#
1494483Sgblack@eecs.umich.edu# Lexer specification
1504483Sgblack@eecs.umich.edu#
1514483Sgblack@eecs.umich.edu##########################################################################
1524483Sgblack@eecs.umich.edu
1534483Sgblack@eecs.umich.edu# Error handler.  Just call exit.  Output formatted to work under
1544483Sgblack@eecs.umich.edu# Emacs compile-mode.  Optional 'print_traceback' arg, if set to True,
1554483Sgblack@eecs.umich.edu# prints a Python stack backtrace too (can be handy when trying to
1564483Sgblack@eecs.umich.edu# debug the parser itself).
1574483Sgblack@eecs.umich.edudef error(lineno, string, print_traceback = False):
1584483Sgblack@eecs.umich.edu    # Print a Python stack backtrace if requested.
1594483Sgblack@eecs.umich.edu    if (print_traceback):
1604483Sgblack@eecs.umich.edu        traceback.print_exc()
1614483Sgblack@eecs.umich.edu    if lineno != 0:
1624483Sgblack@eecs.umich.edu        line_str = "%d:" % lineno
1634483Sgblack@eecs.umich.edu    else:
1644483Sgblack@eecs.umich.edu        line_str = ""
1654483Sgblack@eecs.umich.edu    sys.exit("%s %s" % (line_str, string))
1664483Sgblack@eecs.umich.edu
1674483Sgblack@eecs.umich.edureserved = ('DEF', 'MACROOP', 'ROM', 'EXTERN')
1684483Sgblack@eecs.umich.edu
1694483Sgblack@eecs.umich.edutokens = reserved + (
1704483Sgblack@eecs.umich.edu        # identifier
1714483Sgblack@eecs.umich.edu        'ID',
1724483Sgblack@eecs.umich.edu        # arguments for microops and directives
1734483Sgblack@eecs.umich.edu        'PARAMS',
1744483Sgblack@eecs.umich.edu
1754483Sgblack@eecs.umich.edu        'LPAREN', 'RPAREN',
1764483Sgblack@eecs.umich.edu        'LBRACE', 'RBRACE',
1774483Sgblack@eecs.umich.edu        'COLON', 'SEMI', 'DOT',
1784483Sgblack@eecs.umich.edu        'NEWLINE'
1794483Sgblack@eecs.umich.edu        )
1804483Sgblack@eecs.umich.edu
1814483Sgblack@eecs.umich.edu# New lines are ignored at the top level, but they end statements in the
1824483Sgblack@eecs.umich.edu# assembler
1834483Sgblack@eecs.umich.edustates = (
1844483Sgblack@eecs.umich.edu    ('asm', 'exclusive'),
1854483Sgblack@eecs.umich.edu    ('params', 'exclusive'),
1864483Sgblack@eecs.umich.edu)
1874483Sgblack@eecs.umich.edu
1884483Sgblack@eecs.umich.edureserved_map = { }
1894483Sgblack@eecs.umich.edufor r in reserved:
1904483Sgblack@eecs.umich.edu    reserved_map[r.lower()] = r
1914483Sgblack@eecs.umich.edu
1924502Sgblack@eecs.umich.edudef t_ANY_COMMENT(t):
1934502Sgblack@eecs.umich.edu    r'\#[^\n]*(?=\n)'
1944502Sgblack@eecs.umich.edu    #print "t_ANY_COMMENT %s" % t.value
1954502Sgblack@eecs.umich.edu
1964502Sgblack@eecs.umich.edudef t_ANY_MULTILINECOMMENT(t):
1974502Sgblack@eecs.umich.edu    r'/\*([^/]|((?<!\*)/))*\*/'
1984502Sgblack@eecs.umich.edu    #print "t_ANY_MULTILINECOMMENT %s" % t.value
1994502Sgblack@eecs.umich.edu
2004483Sgblack@eecs.umich.edudef t_params_COLON(t):
2014483Sgblack@eecs.umich.edu    r':'
2024483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2034502Sgblack@eecs.umich.edu    #print "t_params_COLON %s" % t.value
2044483Sgblack@eecs.umich.edu    return t
2054483Sgblack@eecs.umich.edu
2064483Sgblack@eecs.umich.edudef t_asm_ID(t):
2074483Sgblack@eecs.umich.edu    r'[A-Za-z_]\w*'
2084483Sgblack@eecs.umich.edu    t.type = reserved_map.get(t.value, 'ID')
2094483Sgblack@eecs.umich.edu    t.lexer.begin('params')
2104502Sgblack@eecs.umich.edu    #print "t_asm_ID %s" % t.value
2114483Sgblack@eecs.umich.edu    return t
2124483Sgblack@eecs.umich.edu
2134483Sgblack@eecs.umich.edudef t_ANY_ID(t):
2144483Sgblack@eecs.umich.edu    r'[A-Za-z_]\w*'
2154483Sgblack@eecs.umich.edu    t.type = reserved_map.get(t.value, 'ID')
2164502Sgblack@eecs.umich.edu    #print "t_ANY_ID %s" % t.value
2174483Sgblack@eecs.umich.edu    return t
2184483Sgblack@eecs.umich.edu
2194483Sgblack@eecs.umich.edudef t_params_PARAMS(t):
2204483Sgblack@eecs.umich.edu    r'([^\n;]|((?<=\\)[\n;]))+'
2214483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2224483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2234502Sgblack@eecs.umich.edu    #print "t_params_PARAMS %s" % t.value
2244483Sgblack@eecs.umich.edu    return t
2254483Sgblack@eecs.umich.edu
2264483Sgblack@eecs.umich.edudef t_INITIAL_LBRACE(t):
2274483Sgblack@eecs.umich.edu    r'\{'
2284483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2294502Sgblack@eecs.umich.edu    #print "t_INITIAL_LBRACE %s" % t.value
2304483Sgblack@eecs.umich.edu    return t
2314483Sgblack@eecs.umich.edu
2324483Sgblack@eecs.umich.edudef t_asm_RBRACE(t):
2334483Sgblack@eecs.umich.edu    r'\}'
2344483Sgblack@eecs.umich.edu    t.lexer.begin('INITIAL')
2354502Sgblack@eecs.umich.edu    #print "t_asm_RBRACE %s" % t.value
2364483Sgblack@eecs.umich.edu    return t
2374483Sgblack@eecs.umich.edu
2384483Sgblack@eecs.umich.edudef t_INITIAL_NEWLINE(t):
2394483Sgblack@eecs.umich.edu    r'\n+'
2404483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2414502Sgblack@eecs.umich.edu    #print "t_INITIAL_NEWLINE %s" % t.value
2424483Sgblack@eecs.umich.edu
2434483Sgblack@eecs.umich.edudef t_asm_NEWLINE(t):
2444483Sgblack@eecs.umich.edu    r'\n+'
2454483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2464502Sgblack@eecs.umich.edu    #print "t_asm_NEWLINE %s" % t.value
2474483Sgblack@eecs.umich.edu    return t
2484483Sgblack@eecs.umich.edu
2494483Sgblack@eecs.umich.edudef t_params_NEWLINE(t):
2504483Sgblack@eecs.umich.edu    r'\n+'
2514483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2524483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2534502Sgblack@eecs.umich.edu    #print "t_params_NEWLINE %s" % t.value
2544483Sgblack@eecs.umich.edu    return t
2554483Sgblack@eecs.umich.edu
2564483Sgblack@eecs.umich.edudef t_params_SEMI(t):
2574483Sgblack@eecs.umich.edu    r';'
2584483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2594502Sgblack@eecs.umich.edu    #print "t_params_SEMI %s" % t.value
2604483Sgblack@eecs.umich.edu    return t
2614483Sgblack@eecs.umich.edu
2624483Sgblack@eecs.umich.edu# Basic regular expressions to pick out simple tokens
2634483Sgblack@eecs.umich.edut_ANY_LPAREN = r'\('
2644483Sgblack@eecs.umich.edut_ANY_RPAREN = r'\)'
2654483Sgblack@eecs.umich.edut_ANY_SEMI   = r';'
2664483Sgblack@eecs.umich.edut_ANY_DOT    = r'\.'
2674483Sgblack@eecs.umich.edu
2684483Sgblack@eecs.umich.edut_ANY_ignore = ' \t\x0c'
2694483Sgblack@eecs.umich.edu
2704483Sgblack@eecs.umich.edudef t_ANY_error(t):
2714483Sgblack@eecs.umich.edu    error(t.lineno, "illegal character '%s'" % t.value[0])
2724483Sgblack@eecs.umich.edu    t.skip(1)
2734483Sgblack@eecs.umich.edu
2744483Sgblack@eecs.umich.edu##########################################################################
2754483Sgblack@eecs.umich.edu#
2764483Sgblack@eecs.umich.edu# Parser specification
2774483Sgblack@eecs.umich.edu#
2784483Sgblack@eecs.umich.edu##########################################################################
2794483Sgblack@eecs.umich.edu
2804483Sgblack@eecs.umich.edu# Start symbol for a file which may have more than one macroop or rom
2814483Sgblack@eecs.umich.edu# specification.
2824483Sgblack@eecs.umich.edudef p_file(t):
2834483Sgblack@eecs.umich.edu    'file : opt_rom_or_macros'
2844483Sgblack@eecs.umich.edu
2854483Sgblack@eecs.umich.edudef p_opt_rom_or_macros_0(t):
2864483Sgblack@eecs.umich.edu    'opt_rom_or_macros : '
2874483Sgblack@eecs.umich.edu
2884483Sgblack@eecs.umich.edudef p_opt_rom_or_macros_1(t):
2894483Sgblack@eecs.umich.edu    'opt_rom_or_macros : rom_or_macros'
2904483Sgblack@eecs.umich.edu
2914483Sgblack@eecs.umich.edudef p_rom_or_macros_0(t):
2924483Sgblack@eecs.umich.edu    'rom_or_macros : rom_or_macro'
2934483Sgblack@eecs.umich.edu
2944483Sgblack@eecs.umich.edudef p_rom_or_macros_1(t):
2954483Sgblack@eecs.umich.edu    'rom_or_macros : rom_or_macros rom_or_macro'
2964483Sgblack@eecs.umich.edu
2974483Sgblack@eecs.umich.edudef p_rom_or_macro_0(t):
2984483Sgblack@eecs.umich.edu    '''rom_or_macro : rom_block'''
2994483Sgblack@eecs.umich.edu
3004483Sgblack@eecs.umich.edudef p_rom_or_macro_1(t):
3014483Sgblack@eecs.umich.edu    '''rom_or_macro : macroop_def'''
3024483Sgblack@eecs.umich.edu
3034483Sgblack@eecs.umich.edu# A block of statements
3044483Sgblack@eecs.umich.edudef p_block(t):
3054483Sgblack@eecs.umich.edu    'block : LBRACE statements RBRACE'
3064483Sgblack@eecs.umich.edu    block = Block()
3074483Sgblack@eecs.umich.edu    block.statements = t[2]
3084483Sgblack@eecs.umich.edu    t[0] = block
3094483Sgblack@eecs.umich.edu
3104483Sgblack@eecs.umich.edu# Defines a section of microcode that should go in the current ROM
3114483Sgblack@eecs.umich.edudef p_rom_block(t):
3124483Sgblack@eecs.umich.edu    'rom_block : DEF ROM block SEMI'
3134483Sgblack@eecs.umich.edu    for statement in t[3].statements:
3144483Sgblack@eecs.umich.edu        handle_statement(t.parser, t.parser.rom, statement)
3154483Sgblack@eecs.umich.edu    t[0] = t.parser.rom
3164483Sgblack@eecs.umich.edu
3174483Sgblack@eecs.umich.edu# Defines a macroop that jumps to an external label in the ROM
3184483Sgblack@eecs.umich.edudef p_macroop_def_0(t):
3194502Sgblack@eecs.umich.edu    'macroop_def : DEF MACROOP ID LPAREN ID RPAREN SEMI'
3204483Sgblack@eecs.umich.edu    t[0] = t[4]
3214483Sgblack@eecs.umich.edu
3224483Sgblack@eecs.umich.edu# Defines a macroop that is combinationally generated
3234483Sgblack@eecs.umich.edudef p_macroop_def_1(t):
3244483Sgblack@eecs.umich.edu    'macroop_def : DEF MACROOP ID block SEMI'
3254483Sgblack@eecs.umich.edu    try:
3264483Sgblack@eecs.umich.edu        curop = t.parser.macro_type(t[3])
3274483Sgblack@eecs.umich.edu    except TypeError:
3284483Sgblack@eecs.umich.edu        print_error("Error creating macroop object.")
3294483Sgblack@eecs.umich.edu        raise
3304483Sgblack@eecs.umich.edu    for statement in t[4].statements:
3314483Sgblack@eecs.umich.edu        handle_statement(t.parser, curop, statement)
3324502Sgblack@eecs.umich.edu    t.parser.macroops[t[3]] = curop
3334483Sgblack@eecs.umich.edu
3344483Sgblack@eecs.umich.edudef p_statements_0(t):
3354483Sgblack@eecs.umich.edu    'statements : statement'
3364483Sgblack@eecs.umich.edu    if t[1]:
3374483Sgblack@eecs.umich.edu        t[0] = [t[1]]
3384483Sgblack@eecs.umich.edu    else:
3394483Sgblack@eecs.umich.edu        t[0] = []
3404483Sgblack@eecs.umich.edu
3414483Sgblack@eecs.umich.edudef p_statements_1(t):
3424483Sgblack@eecs.umich.edu    'statements : statements statement'
3434483Sgblack@eecs.umich.edu    if t[2]:
3444483Sgblack@eecs.umich.edu        t[1].append(t[2])
3454483Sgblack@eecs.umich.edu    t[0] = t[1]
3464483Sgblack@eecs.umich.edu
3474483Sgblack@eecs.umich.edudef p_statement(t):
3484483Sgblack@eecs.umich.edu    'statement : content_of_statement end_of_statement'
3494483Sgblack@eecs.umich.edu    t[0] = t[1]
3504483Sgblack@eecs.umich.edu
3514483Sgblack@eecs.umich.edu# A statement can be a microop or an assembler directive
3524483Sgblack@eecs.umich.edudef p_content_of_statement_0(t):
3534483Sgblack@eecs.umich.edu    '''content_of_statement : microop
3544483Sgblack@eecs.umich.edu                            | directive'''
3554483Sgblack@eecs.umich.edu    t[0] = t[1]
3564483Sgblack@eecs.umich.edu
3574483Sgblack@eecs.umich.edudef p_content_of_statement_1(t):
3584483Sgblack@eecs.umich.edu    'content_of_statement : '
3594483Sgblack@eecs.umich.edu    pass
3604483Sgblack@eecs.umich.edu
3614483Sgblack@eecs.umich.edu# Statements are ended by newlines or a semi colon
3624483Sgblack@eecs.umich.edudef p_end_of_statement(t):
3634483Sgblack@eecs.umich.edu    '''end_of_statement : NEWLINE
3644483Sgblack@eecs.umich.edu                        | SEMI'''
3654483Sgblack@eecs.umich.edu    pass
3664483Sgblack@eecs.umich.edu
3674483Sgblack@eecs.umich.edudef p_microop_0(t):
3684483Sgblack@eecs.umich.edu    'microop : labels ID'
3694483Sgblack@eecs.umich.edu    microop = Microop()
3704483Sgblack@eecs.umich.edu    microop.labels = t[1]
3714483Sgblack@eecs.umich.edu    microop.mnemonic = t[2]
3724483Sgblack@eecs.umich.edu    t[0] = microop
3734483Sgblack@eecs.umich.edu
3744483Sgblack@eecs.umich.edudef p_microop_1(t):
3754483Sgblack@eecs.umich.edu    'microop : ID'
3764483Sgblack@eecs.umich.edu    microop = Microop()
3774483Sgblack@eecs.umich.edu    microop.mnemonic = t[1]
3784483Sgblack@eecs.umich.edu    t[0] = microop
3794483Sgblack@eecs.umich.edu
3804483Sgblack@eecs.umich.edudef p_microop_2(t):
3814483Sgblack@eecs.umich.edu    'microop : labels ID PARAMS'
3824483Sgblack@eecs.umich.edu    microop = Microop()
3834483Sgblack@eecs.umich.edu    microop.labels = t[1]
3844483Sgblack@eecs.umich.edu    microop.mnemonic = t[2]
3854483Sgblack@eecs.umich.edu    microop.params = t[3]
3864483Sgblack@eecs.umich.edu    t[0] = microop
3874483Sgblack@eecs.umich.edu
3884483Sgblack@eecs.umich.edudef p_microop_3(t):
3894483Sgblack@eecs.umich.edu    'microop : ID PARAMS'
3904483Sgblack@eecs.umich.edu    microop = Microop()
3914483Sgblack@eecs.umich.edu    microop.mnemonic = t[1]
3924483Sgblack@eecs.umich.edu    microop.params = t[2]
3934483Sgblack@eecs.umich.edu    t[0] = microop
3944483Sgblack@eecs.umich.edu
3954483Sgblack@eecs.umich.edudef p_labels_0(t):
3964483Sgblack@eecs.umich.edu    'labels : label'
3974483Sgblack@eecs.umich.edu    t[0] = [t[1]]
3984483Sgblack@eecs.umich.edu
3994483Sgblack@eecs.umich.edudef p_labels_1(t):
4004483Sgblack@eecs.umich.edu    'labels : labels label'
4014483Sgblack@eecs.umich.edu    t[1].append(t[2])
4024483Sgblack@eecs.umich.edu    t[0] = t[1]
4034483Sgblack@eecs.umich.edu
4044483Sgblack@eecs.umich.edudef p_label_0(t):
4054483Sgblack@eecs.umich.edu    'label : ID COLON'
4064483Sgblack@eecs.umich.edu    label = Label()
4074483Sgblack@eecs.umich.edu    label.is_extern = False
4084483Sgblack@eecs.umich.edu    label.text = t[1]
4094483Sgblack@eecs.umich.edu    t[0] = label
4104483Sgblack@eecs.umich.edu
4114483Sgblack@eecs.umich.edudef p_label_1(t):
4124483Sgblack@eecs.umich.edu    'label : EXTERN ID COLON'
4134483Sgblack@eecs.umich.edu    label = Label()
4144483Sgblack@eecs.umich.edu    label.is_extern = True
4154483Sgblack@eecs.umich.edu    label.text = t[2]
4164483Sgblack@eecs.umich.edu    t[0] = label
4174483Sgblack@eecs.umich.edu
4184503Sgblack@eecs.umich.edudef p_directive_0(t):
4194483Sgblack@eecs.umich.edu    'directive : DOT ID'
4204483Sgblack@eecs.umich.edu    directive = Directive()
4214483Sgblack@eecs.umich.edu    directive.name = t[2]
4224483Sgblack@eecs.umich.edu    t[0] = directive
4234483Sgblack@eecs.umich.edu
4244503Sgblack@eecs.umich.edudef p_directive_1(t):
4254503Sgblack@eecs.umich.edu    'directive : DOT ID PARAMS'
4264503Sgblack@eecs.umich.edu    directive = Directive()
4274503Sgblack@eecs.umich.edu    directive.name = t[2]
4284503Sgblack@eecs.umich.edu    directive.params = t[3]
4294503Sgblack@eecs.umich.edu    t[0] = directive
4304503Sgblack@eecs.umich.edu
4314483Sgblack@eecs.umich.edu# Parse error handler.  Note that the argument here is the offending
4324483Sgblack@eecs.umich.edu# *token*, not a grammar symbol (hence the need to use t.value)
4334483Sgblack@eecs.umich.edudef p_error(t):
4344483Sgblack@eecs.umich.edu    if t:
4354483Sgblack@eecs.umich.edu        error(t.lineno, "syntax error at '%s'" % t.value)
4364483Sgblack@eecs.umich.edu    else:
4374483Sgblack@eecs.umich.edu        error(0, "unknown syntax error", True)
4384483Sgblack@eecs.umich.edu
4394483Sgblack@eecs.umich.educlass MicroAssembler(object):
4404483Sgblack@eecs.umich.edu
4414483Sgblack@eecs.umich.edu    def __init__(self, macro_type, microops, rom):
4424483Sgblack@eecs.umich.edu        self.lexer = lex.lex()
4434483Sgblack@eecs.umich.edu        self.parser = yacc.yacc()
4444483Sgblack@eecs.umich.edu        self.parser.macro_type = macro_type
4454502Sgblack@eecs.umich.edu        self.parser.macroops = {}
4464483Sgblack@eecs.umich.edu        self.parser.microops = microops
4474483Sgblack@eecs.umich.edu        self.parser.rom = rom
4484483Sgblack@eecs.umich.edu
4494483Sgblack@eecs.umich.edu    def assemble(self, asm):
4504483Sgblack@eecs.umich.edu        self.parser.parse(asm, lexer=self.lexer)
4514502Sgblack@eecs.umich.edu        # Begin debug printing
4524502Sgblack@eecs.umich.edu        for macroop in self.parser.macroops.values():
4534483Sgblack@eecs.umich.edu            print macroop
4544483Sgblack@eecs.umich.edu        print self.parser.rom
4554502Sgblack@eecs.umich.edu        # End debug printing
4564483Sgblack@eecs.umich.edu        macroops = self.parser.macroops
4574502Sgblack@eecs.umich.edu        self.parser.macroops = {}
4584483Sgblack@eecs.umich.edu        return macroops
459