micro_asm.py revision 4507
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
674507Sgblack@eecs.umich.educlass Combinational_Macroop(Micro_Container):
684483Sgblack@eecs.umich.edu    pass
694483Sgblack@eecs.umich.edu
704507Sgblack@eecs.umich.educlass Rom_Macroop(object):
714507Sgblack@eecs.umich.edu    def __init__(self, name, target):
724507Sgblack@eecs.umich.edu        self.name = name
734507Sgblack@eecs.umich.edu        self.target = target
744507Sgblack@eecs.umich.edu
754483Sgblack@eecs.umich.educlass Rom(Micro_Container):
764483Sgblack@eecs.umich.edu    def __init__(self, name):
774483Sgblack@eecs.umich.edu        super(Rom, self).__init__(name)
784483Sgblack@eecs.umich.edu        self.externs = {}
794483Sgblack@eecs.umich.edu
804483Sgblack@eecs.umich.edu##########################################################################
814483Sgblack@eecs.umich.edu#
824483Sgblack@eecs.umich.edu# Support classes
834483Sgblack@eecs.umich.edu#
844483Sgblack@eecs.umich.edu##########################################################################
854483Sgblack@eecs.umich.edu
864483Sgblack@eecs.umich.educlass Label(object):
874483Sgblack@eecs.umich.edu    def __init__(self):
884483Sgblack@eecs.umich.edu        self.extern = False
894483Sgblack@eecs.umich.edu        self.name = ""
904483Sgblack@eecs.umich.edu
914483Sgblack@eecs.umich.educlass Block(object):
924483Sgblack@eecs.umich.edu    def __init__(self):
934483Sgblack@eecs.umich.edu        self.statements = []
944483Sgblack@eecs.umich.edu
954483Sgblack@eecs.umich.educlass Statement(object):
964483Sgblack@eecs.umich.edu    def __init__(self):
974483Sgblack@eecs.umich.edu        self.is_microop = False
984483Sgblack@eecs.umich.edu        self.is_directive = False
994503Sgblack@eecs.umich.edu        self.params = ""
1004483Sgblack@eecs.umich.edu
1014483Sgblack@eecs.umich.educlass Microop(Statement):
1024483Sgblack@eecs.umich.edu    def __init__(self):
1034483Sgblack@eecs.umich.edu        super(Microop, self).__init__()
1044483Sgblack@eecs.umich.edu        self.mnemonic = ""
1054483Sgblack@eecs.umich.edu        self.labels = []
1064483Sgblack@eecs.umich.edu        self.is_microop = True
1074483Sgblack@eecs.umich.edu
1084483Sgblack@eecs.umich.educlass Directive(Statement):
1094483Sgblack@eecs.umich.edu    def __init__(self):
1104483Sgblack@eecs.umich.edu        super(Directive, self).__init__()
1114483Sgblack@eecs.umich.edu        self.name = ""
1124483Sgblack@eecs.umich.edu        self.is_directive = True
1134483Sgblack@eecs.umich.edu
1144483Sgblack@eecs.umich.edu##########################################################################
1154483Sgblack@eecs.umich.edu#
1164483Sgblack@eecs.umich.edu# Functions that handle common tasks
1174483Sgblack@eecs.umich.edu#
1184483Sgblack@eecs.umich.edu##########################################################################
1194483Sgblack@eecs.umich.edu
1204483Sgblack@eecs.umich.edudef print_error(message):
1214483Sgblack@eecs.umich.edu    print
1224483Sgblack@eecs.umich.edu    print "*** %s" % message
1234483Sgblack@eecs.umich.edu    print
1244483Sgblack@eecs.umich.edu
1254483Sgblack@eecs.umich.edudef handle_statement(parser, container, statement):
1264483Sgblack@eecs.umich.edu    if statement.is_microop:
1274483Sgblack@eecs.umich.edu        try:
1284483Sgblack@eecs.umich.edu            microop = eval('parser.microops[statement.mnemonic](%s)' %
1294483Sgblack@eecs.umich.edu                    statement.params)
1304483Sgblack@eecs.umich.edu        except:
1314483Sgblack@eecs.umich.edu            print_error("Error creating microop object.")
1324483Sgblack@eecs.umich.edu            raise
1334483Sgblack@eecs.umich.edu        try:
1344483Sgblack@eecs.umich.edu            for label in statement.labels:
1354483Sgblack@eecs.umich.edu                container.labels[label.name] = microop
1364483Sgblack@eecs.umich.edu                if label.extern:
1374483Sgblack@eecs.umich.edu                    container.externs[label.name] = microop
1384483Sgblack@eecs.umich.edu            container.add_microop(microop)
1394483Sgblack@eecs.umich.edu        except:
1404483Sgblack@eecs.umich.edu            print_error("Error adding microop.")
1414483Sgblack@eecs.umich.edu            raise
1424483Sgblack@eecs.umich.edu    elif statement.is_directive:
1434483Sgblack@eecs.umich.edu        try:
1444503Sgblack@eecs.umich.edu            eval('container.directives[statement.name](%s)' % statement.params)
1454483Sgblack@eecs.umich.edu        except:
1464483Sgblack@eecs.umich.edu            print_error("Error executing directive.")
1474483Sgblack@eecs.umich.edu            print container.directives
1484483Sgblack@eecs.umich.edu            raise
1494483Sgblack@eecs.umich.edu    else:
1504483Sgblack@eecs.umich.edu        raise Exception, "Didn't recognize the type of statement", statement
1514483Sgblack@eecs.umich.edu
1524483Sgblack@eecs.umich.edu##########################################################################
1534483Sgblack@eecs.umich.edu#
1544483Sgblack@eecs.umich.edu# Lexer specification
1554483Sgblack@eecs.umich.edu#
1564483Sgblack@eecs.umich.edu##########################################################################
1574483Sgblack@eecs.umich.edu
1584483Sgblack@eecs.umich.edu# Error handler.  Just call exit.  Output formatted to work under
1594483Sgblack@eecs.umich.edu# Emacs compile-mode.  Optional 'print_traceback' arg, if set to True,
1604483Sgblack@eecs.umich.edu# prints a Python stack backtrace too (can be handy when trying to
1614483Sgblack@eecs.umich.edu# debug the parser itself).
1624483Sgblack@eecs.umich.edudef error(lineno, string, print_traceback = False):
1634483Sgblack@eecs.umich.edu    # Print a Python stack backtrace if requested.
1644483Sgblack@eecs.umich.edu    if (print_traceback):
1654483Sgblack@eecs.umich.edu        traceback.print_exc()
1664483Sgblack@eecs.umich.edu    if lineno != 0:
1674483Sgblack@eecs.umich.edu        line_str = "%d:" % lineno
1684483Sgblack@eecs.umich.edu    else:
1694483Sgblack@eecs.umich.edu        line_str = ""
1704483Sgblack@eecs.umich.edu    sys.exit("%s %s" % (line_str, string))
1714483Sgblack@eecs.umich.edu
1724483Sgblack@eecs.umich.edureserved = ('DEF', 'MACROOP', 'ROM', 'EXTERN')
1734483Sgblack@eecs.umich.edu
1744483Sgblack@eecs.umich.edutokens = reserved + (
1754483Sgblack@eecs.umich.edu        # identifier
1764483Sgblack@eecs.umich.edu        'ID',
1774483Sgblack@eecs.umich.edu        # arguments for microops and directives
1784483Sgblack@eecs.umich.edu        'PARAMS',
1794483Sgblack@eecs.umich.edu
1804483Sgblack@eecs.umich.edu        'LPAREN', 'RPAREN',
1814483Sgblack@eecs.umich.edu        'LBRACE', 'RBRACE',
1824483Sgblack@eecs.umich.edu        'COLON', 'SEMI', 'DOT',
1834483Sgblack@eecs.umich.edu        'NEWLINE'
1844483Sgblack@eecs.umich.edu        )
1854483Sgblack@eecs.umich.edu
1864483Sgblack@eecs.umich.edu# New lines are ignored at the top level, but they end statements in the
1874483Sgblack@eecs.umich.edu# assembler
1884483Sgblack@eecs.umich.edustates = (
1894483Sgblack@eecs.umich.edu    ('asm', 'exclusive'),
1904483Sgblack@eecs.umich.edu    ('params', 'exclusive'),
1914483Sgblack@eecs.umich.edu)
1924483Sgblack@eecs.umich.edu
1934483Sgblack@eecs.umich.edureserved_map = { }
1944483Sgblack@eecs.umich.edufor r in reserved:
1954483Sgblack@eecs.umich.edu    reserved_map[r.lower()] = r
1964483Sgblack@eecs.umich.edu
1974502Sgblack@eecs.umich.edudef t_ANY_COMMENT(t):
1984502Sgblack@eecs.umich.edu    r'\#[^\n]*(?=\n)'
1994502Sgblack@eecs.umich.edu    #print "t_ANY_COMMENT %s" % t.value
2004502Sgblack@eecs.umich.edu
2014502Sgblack@eecs.umich.edudef t_ANY_MULTILINECOMMENT(t):
2024502Sgblack@eecs.umich.edu    r'/\*([^/]|((?<!\*)/))*\*/'
2034502Sgblack@eecs.umich.edu    #print "t_ANY_MULTILINECOMMENT %s" % t.value
2044502Sgblack@eecs.umich.edu
2054483Sgblack@eecs.umich.edudef t_params_COLON(t):
2064483Sgblack@eecs.umich.edu    r':'
2074483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2084502Sgblack@eecs.umich.edu    #print "t_params_COLON %s" % t.value
2094483Sgblack@eecs.umich.edu    return t
2104483Sgblack@eecs.umich.edu
2114483Sgblack@eecs.umich.edudef t_asm_ID(t):
2124483Sgblack@eecs.umich.edu    r'[A-Za-z_]\w*'
2134483Sgblack@eecs.umich.edu    t.type = reserved_map.get(t.value, 'ID')
2144483Sgblack@eecs.umich.edu    t.lexer.begin('params')
2154502Sgblack@eecs.umich.edu    #print "t_asm_ID %s" % t.value
2164483Sgblack@eecs.umich.edu    return t
2174483Sgblack@eecs.umich.edu
2184483Sgblack@eecs.umich.edudef t_ANY_ID(t):
2194483Sgblack@eecs.umich.edu    r'[A-Za-z_]\w*'
2204483Sgblack@eecs.umich.edu    t.type = reserved_map.get(t.value, 'ID')
2214502Sgblack@eecs.umich.edu    #print "t_ANY_ID %s" % t.value
2224483Sgblack@eecs.umich.edu    return t
2234483Sgblack@eecs.umich.edu
2244483Sgblack@eecs.umich.edudef t_params_PARAMS(t):
2254483Sgblack@eecs.umich.edu    r'([^\n;]|((?<=\\)[\n;]))+'
2264483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2274483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2284502Sgblack@eecs.umich.edu    #print "t_params_PARAMS %s" % t.value
2294483Sgblack@eecs.umich.edu    return t
2304483Sgblack@eecs.umich.edu
2314483Sgblack@eecs.umich.edudef t_INITIAL_LBRACE(t):
2324483Sgblack@eecs.umich.edu    r'\{'
2334483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2344502Sgblack@eecs.umich.edu    #print "t_INITIAL_LBRACE %s" % t.value
2354483Sgblack@eecs.umich.edu    return t
2364483Sgblack@eecs.umich.edu
2374483Sgblack@eecs.umich.edudef t_asm_RBRACE(t):
2384483Sgblack@eecs.umich.edu    r'\}'
2394483Sgblack@eecs.umich.edu    t.lexer.begin('INITIAL')
2404502Sgblack@eecs.umich.edu    #print "t_asm_RBRACE %s" % t.value
2414483Sgblack@eecs.umich.edu    return t
2424483Sgblack@eecs.umich.edu
2434483Sgblack@eecs.umich.edudef t_INITIAL_NEWLINE(t):
2444483Sgblack@eecs.umich.edu    r'\n+'
2454483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2464502Sgblack@eecs.umich.edu    #print "t_INITIAL_NEWLINE %s" % t.value
2474483Sgblack@eecs.umich.edu
2484483Sgblack@eecs.umich.edudef t_asm_NEWLINE(t):
2494483Sgblack@eecs.umich.edu    r'\n+'
2504483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2514502Sgblack@eecs.umich.edu    #print "t_asm_NEWLINE %s" % t.value
2524483Sgblack@eecs.umich.edu    return t
2534483Sgblack@eecs.umich.edu
2544483Sgblack@eecs.umich.edudef t_params_NEWLINE(t):
2554483Sgblack@eecs.umich.edu    r'\n+'
2564483Sgblack@eecs.umich.edu    t.lineno += t.value.count('\n')
2574483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2584502Sgblack@eecs.umich.edu    #print "t_params_NEWLINE %s" % t.value
2594483Sgblack@eecs.umich.edu    return t
2604483Sgblack@eecs.umich.edu
2614483Sgblack@eecs.umich.edudef t_params_SEMI(t):
2624483Sgblack@eecs.umich.edu    r';'
2634483Sgblack@eecs.umich.edu    t.lexer.begin('asm')
2644502Sgblack@eecs.umich.edu    #print "t_params_SEMI %s" % t.value
2654483Sgblack@eecs.umich.edu    return t
2664483Sgblack@eecs.umich.edu
2674483Sgblack@eecs.umich.edu# Basic regular expressions to pick out simple tokens
2684483Sgblack@eecs.umich.edut_ANY_LPAREN = r'\('
2694483Sgblack@eecs.umich.edut_ANY_RPAREN = r'\)'
2704483Sgblack@eecs.umich.edut_ANY_SEMI   = r';'
2714483Sgblack@eecs.umich.edut_ANY_DOT    = r'\.'
2724483Sgblack@eecs.umich.edu
2734483Sgblack@eecs.umich.edut_ANY_ignore = ' \t\x0c'
2744483Sgblack@eecs.umich.edu
2754483Sgblack@eecs.umich.edudef t_ANY_error(t):
2764483Sgblack@eecs.umich.edu    error(t.lineno, "illegal character '%s'" % t.value[0])
2774483Sgblack@eecs.umich.edu    t.skip(1)
2784483Sgblack@eecs.umich.edu
2794483Sgblack@eecs.umich.edu##########################################################################
2804483Sgblack@eecs.umich.edu#
2814483Sgblack@eecs.umich.edu# Parser specification
2824483Sgblack@eecs.umich.edu#
2834483Sgblack@eecs.umich.edu##########################################################################
2844483Sgblack@eecs.umich.edu
2854483Sgblack@eecs.umich.edu# Start symbol for a file which may have more than one macroop or rom
2864483Sgblack@eecs.umich.edu# specification.
2874483Sgblack@eecs.umich.edudef p_file(t):
2884483Sgblack@eecs.umich.edu    'file : opt_rom_or_macros'
2894483Sgblack@eecs.umich.edu
2904483Sgblack@eecs.umich.edudef p_opt_rom_or_macros_0(t):
2914483Sgblack@eecs.umich.edu    'opt_rom_or_macros : '
2924483Sgblack@eecs.umich.edu
2934483Sgblack@eecs.umich.edudef p_opt_rom_or_macros_1(t):
2944483Sgblack@eecs.umich.edu    'opt_rom_or_macros : rom_or_macros'
2954483Sgblack@eecs.umich.edu
2964483Sgblack@eecs.umich.edudef p_rom_or_macros_0(t):
2974483Sgblack@eecs.umich.edu    'rom_or_macros : rom_or_macro'
2984483Sgblack@eecs.umich.edu
2994483Sgblack@eecs.umich.edudef p_rom_or_macros_1(t):
3004483Sgblack@eecs.umich.edu    'rom_or_macros : rom_or_macros rom_or_macro'
3014483Sgblack@eecs.umich.edu
3024483Sgblack@eecs.umich.edudef p_rom_or_macro_0(t):
3034483Sgblack@eecs.umich.edu    '''rom_or_macro : rom_block'''
3044483Sgblack@eecs.umich.edu
3054483Sgblack@eecs.umich.edudef p_rom_or_macro_1(t):
3064483Sgblack@eecs.umich.edu    '''rom_or_macro : macroop_def'''
3074483Sgblack@eecs.umich.edu
3084483Sgblack@eecs.umich.edu# A block of statements
3094483Sgblack@eecs.umich.edudef p_block(t):
3104483Sgblack@eecs.umich.edu    'block : LBRACE statements RBRACE'
3114483Sgblack@eecs.umich.edu    block = Block()
3124483Sgblack@eecs.umich.edu    block.statements = t[2]
3134483Sgblack@eecs.umich.edu    t[0] = block
3144483Sgblack@eecs.umich.edu
3154483Sgblack@eecs.umich.edu# Defines a section of microcode that should go in the current ROM
3164483Sgblack@eecs.umich.edudef p_rom_block(t):
3174483Sgblack@eecs.umich.edu    'rom_block : DEF ROM block SEMI'
3184507Sgblack@eecs.umich.edu    if not t.parser.rom:
3194507Sgblack@eecs.umich.edu        print_error("Rom block found, but no Rom object specified.")
3204507Sgblack@eecs.umich.edu        raise TypeError, "Rom block found, but no Rom object was specified."
3214483Sgblack@eecs.umich.edu    for statement in t[3].statements:
3224483Sgblack@eecs.umich.edu        handle_statement(t.parser, t.parser.rom, statement)
3234483Sgblack@eecs.umich.edu    t[0] = t.parser.rom
3244483Sgblack@eecs.umich.edu
3254483Sgblack@eecs.umich.edu# Defines a macroop that jumps to an external label in the ROM
3264483Sgblack@eecs.umich.edudef p_macroop_def_0(t):
3274502Sgblack@eecs.umich.edu    'macroop_def : DEF MACROOP ID LPAREN ID RPAREN SEMI'
3284507Sgblack@eecs.umich.edu    if not t.parser.rom_macroop_type:
3294507Sgblack@eecs.umich.edu        print_error("ROM based macroop found, but no ROM macroop class was specified.")
3304507Sgblack@eecs.umich.edu        raise TypeError, "ROM based macroop found, but no ROM macroop class was specified."
3314507Sgblack@eecs.umich.edu    macroop = t.parser.rom_macroop_type(t[3], t[5])
3324507Sgblack@eecs.umich.edu    t[0] = macroop
3334507Sgblack@eecs.umich.edu
3344483Sgblack@eecs.umich.edu
3354483Sgblack@eecs.umich.edu# Defines a macroop that is combinationally generated
3364483Sgblack@eecs.umich.edudef p_macroop_def_1(t):
3374483Sgblack@eecs.umich.edu    'macroop_def : DEF MACROOP ID block SEMI'
3384483Sgblack@eecs.umich.edu    try:
3394483Sgblack@eecs.umich.edu        curop = t.parser.macro_type(t[3])
3404483Sgblack@eecs.umich.edu    except TypeError:
3414483Sgblack@eecs.umich.edu        print_error("Error creating macroop object.")
3424483Sgblack@eecs.umich.edu        raise
3434483Sgblack@eecs.umich.edu    for statement in t[4].statements:
3444483Sgblack@eecs.umich.edu        handle_statement(t.parser, curop, statement)
3454502Sgblack@eecs.umich.edu    t.parser.macroops[t[3]] = curop
3464483Sgblack@eecs.umich.edu
3474483Sgblack@eecs.umich.edudef p_statements_0(t):
3484483Sgblack@eecs.umich.edu    'statements : statement'
3494483Sgblack@eecs.umich.edu    if t[1]:
3504483Sgblack@eecs.umich.edu        t[0] = [t[1]]
3514483Sgblack@eecs.umich.edu    else:
3524483Sgblack@eecs.umich.edu        t[0] = []
3534483Sgblack@eecs.umich.edu
3544483Sgblack@eecs.umich.edudef p_statements_1(t):
3554483Sgblack@eecs.umich.edu    'statements : statements statement'
3564483Sgblack@eecs.umich.edu    if t[2]:
3574483Sgblack@eecs.umich.edu        t[1].append(t[2])
3584483Sgblack@eecs.umich.edu    t[0] = t[1]
3594483Sgblack@eecs.umich.edu
3604483Sgblack@eecs.umich.edudef p_statement(t):
3614483Sgblack@eecs.umich.edu    'statement : content_of_statement end_of_statement'
3624483Sgblack@eecs.umich.edu    t[0] = t[1]
3634483Sgblack@eecs.umich.edu
3644483Sgblack@eecs.umich.edu# A statement can be a microop or an assembler directive
3654483Sgblack@eecs.umich.edudef p_content_of_statement_0(t):
3664483Sgblack@eecs.umich.edu    '''content_of_statement : microop
3674483Sgblack@eecs.umich.edu                            | directive'''
3684483Sgblack@eecs.umich.edu    t[0] = t[1]
3694483Sgblack@eecs.umich.edu
3704483Sgblack@eecs.umich.edudef p_content_of_statement_1(t):
3714483Sgblack@eecs.umich.edu    'content_of_statement : '
3724483Sgblack@eecs.umich.edu    pass
3734483Sgblack@eecs.umich.edu
3744483Sgblack@eecs.umich.edu# Statements are ended by newlines or a semi colon
3754483Sgblack@eecs.umich.edudef p_end_of_statement(t):
3764483Sgblack@eecs.umich.edu    '''end_of_statement : NEWLINE
3774483Sgblack@eecs.umich.edu                        | SEMI'''
3784483Sgblack@eecs.umich.edu    pass
3794483Sgblack@eecs.umich.edu
3804483Sgblack@eecs.umich.edudef p_microop_0(t):
3814483Sgblack@eecs.umich.edu    'microop : labels ID'
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    t[0] = microop
3864483Sgblack@eecs.umich.edu
3874483Sgblack@eecs.umich.edudef p_microop_1(t):
3884483Sgblack@eecs.umich.edu    'microop : ID'
3894483Sgblack@eecs.umich.edu    microop = Microop()
3904483Sgblack@eecs.umich.edu    microop.mnemonic = t[1]
3914483Sgblack@eecs.umich.edu    t[0] = microop
3924483Sgblack@eecs.umich.edu
3934483Sgblack@eecs.umich.edudef p_microop_2(t):
3944483Sgblack@eecs.umich.edu    'microop : labels ID PARAMS'
3954483Sgblack@eecs.umich.edu    microop = Microop()
3964483Sgblack@eecs.umich.edu    microop.labels = t[1]
3974483Sgblack@eecs.umich.edu    microop.mnemonic = t[2]
3984483Sgblack@eecs.umich.edu    microop.params = t[3]
3994483Sgblack@eecs.umich.edu    t[0] = microop
4004483Sgblack@eecs.umich.edu
4014483Sgblack@eecs.umich.edudef p_microop_3(t):
4024483Sgblack@eecs.umich.edu    'microop : ID PARAMS'
4034483Sgblack@eecs.umich.edu    microop = Microop()
4044483Sgblack@eecs.umich.edu    microop.mnemonic = t[1]
4054483Sgblack@eecs.umich.edu    microop.params = t[2]
4064483Sgblack@eecs.umich.edu    t[0] = microop
4074483Sgblack@eecs.umich.edu
4084483Sgblack@eecs.umich.edudef p_labels_0(t):
4094483Sgblack@eecs.umich.edu    'labels : label'
4104483Sgblack@eecs.umich.edu    t[0] = [t[1]]
4114483Sgblack@eecs.umich.edu
4124483Sgblack@eecs.umich.edudef p_labels_1(t):
4134483Sgblack@eecs.umich.edu    'labels : labels label'
4144483Sgblack@eecs.umich.edu    t[1].append(t[2])
4154483Sgblack@eecs.umich.edu    t[0] = t[1]
4164483Sgblack@eecs.umich.edu
4174483Sgblack@eecs.umich.edudef p_label_0(t):
4184483Sgblack@eecs.umich.edu    'label : ID COLON'
4194483Sgblack@eecs.umich.edu    label = Label()
4204483Sgblack@eecs.umich.edu    label.is_extern = False
4214483Sgblack@eecs.umich.edu    label.text = t[1]
4224483Sgblack@eecs.umich.edu    t[0] = label
4234483Sgblack@eecs.umich.edu
4244483Sgblack@eecs.umich.edudef p_label_1(t):
4254483Sgblack@eecs.umich.edu    'label : EXTERN ID COLON'
4264483Sgblack@eecs.umich.edu    label = Label()
4274483Sgblack@eecs.umich.edu    label.is_extern = True
4284483Sgblack@eecs.umich.edu    label.text = t[2]
4294483Sgblack@eecs.umich.edu    t[0] = label
4304483Sgblack@eecs.umich.edu
4314503Sgblack@eecs.umich.edudef p_directive_0(t):
4324483Sgblack@eecs.umich.edu    'directive : DOT ID'
4334483Sgblack@eecs.umich.edu    directive = Directive()
4344483Sgblack@eecs.umich.edu    directive.name = t[2]
4354483Sgblack@eecs.umich.edu    t[0] = directive
4364483Sgblack@eecs.umich.edu
4374503Sgblack@eecs.umich.edudef p_directive_1(t):
4384503Sgblack@eecs.umich.edu    'directive : DOT ID PARAMS'
4394503Sgblack@eecs.umich.edu    directive = Directive()
4404503Sgblack@eecs.umich.edu    directive.name = t[2]
4414503Sgblack@eecs.umich.edu    directive.params = t[3]
4424503Sgblack@eecs.umich.edu    t[0] = directive
4434503Sgblack@eecs.umich.edu
4444483Sgblack@eecs.umich.edu# Parse error handler.  Note that the argument here is the offending
4454483Sgblack@eecs.umich.edu# *token*, not a grammar symbol (hence the need to use t.value)
4464483Sgblack@eecs.umich.edudef p_error(t):
4474483Sgblack@eecs.umich.edu    if t:
4484483Sgblack@eecs.umich.edu        error(t.lineno, "syntax error at '%s'" % t.value)
4494483Sgblack@eecs.umich.edu    else:
4504483Sgblack@eecs.umich.edu        error(0, "unknown syntax error", True)
4514483Sgblack@eecs.umich.edu
4524483Sgblack@eecs.umich.educlass MicroAssembler(object):
4534483Sgblack@eecs.umich.edu
4544507Sgblack@eecs.umich.edu    def __init__(self, macro_type, microops,
4554507Sgblack@eecs.umich.edu            rom = None, rom_macroop_type = None):
4564483Sgblack@eecs.umich.edu        self.lexer = lex.lex()
4574483Sgblack@eecs.umich.edu        self.parser = yacc.yacc()
4584483Sgblack@eecs.umich.edu        self.parser.macro_type = macro_type
4594502Sgblack@eecs.umich.edu        self.parser.macroops = {}
4604483Sgblack@eecs.umich.edu        self.parser.microops = microops
4614483Sgblack@eecs.umich.edu        self.parser.rom = rom
4624507Sgblack@eecs.umich.edu        self.parser.rom_macroop_type = rom_macroop_type
4634483Sgblack@eecs.umich.edu
4644483Sgblack@eecs.umich.edu    def assemble(self, asm):
4654483Sgblack@eecs.umich.edu        self.parser.parse(asm, lexer=self.lexer)
4664502Sgblack@eecs.umich.edu        # Begin debug printing
4674502Sgblack@eecs.umich.edu        for macroop in self.parser.macroops.values():
4684483Sgblack@eecs.umich.edu            print macroop
4694483Sgblack@eecs.umich.edu        print self.parser.rom
4704502Sgblack@eecs.umich.edu        # End debug printing
4714483Sgblack@eecs.umich.edu        macroops = self.parser.macroops
4724502Sgblack@eecs.umich.edu        self.parser.macroops = {}
4734483Sgblack@eecs.umich.edu        return macroops
474