micro_asm.py revision 4613
1360SN/A# Copyright (c) 2003-2005 The Regents of The University of Michigan 21458SN/A# All rights reserved. 3360SN/A# 4360SN/A# Redistribution and use in source and binary forms, with or without 5360SN/A# modification, are permitted provided that the following conditions are 6360SN/A# met: redistributions of source code must retain the above copyright 7360SN/A# notice, this list of conditions and the following disclaimer; 8360SN/A# redistributions in binary form must reproduce the above copyright 9360SN/A# notice, this list of conditions and the following disclaimer in the 10360SN/A# documentation and/or other materials provided with the distribution; 11360SN/A# neither the name of the copyright holders nor the names of its 12360SN/A# contributors may be used to endorse or promote products derived from 13360SN/A# this software without specific prior written permission. 14360SN/A# 15360SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16360SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17360SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18360SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19360SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20360SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21360SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22360SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23360SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24360SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25360SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26360SN/A# 272665Ssaidi@eecs.umich.edu# Authors: Gabe Black 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.eduimport os 30360SN/Aimport sys 31360SN/Aimport re 3211793Sbrandon.potter@amd.comimport string 3311793Sbrandon.potter@amd.comimport traceback 342093SN/A# get type names 3513479Santhony.gutierrez@amd.comfrom types import * 36360SN/A 37360SN/A# Prepend the directory where the PLY lex & yacc modules are found 3811911SBrandon.Potter@amd.com# to the search path. 396712Snate@binkert.orgsys.path[0:0] = [os.environ['M5_PLY']] 4013031Sbrandon.potter@amd.com 41360SN/Afrom ply import lex 42360SN/Afrom ply import yacc 437680Sgblack@eecs.umich.edu 442474SN/A########################################################################## 45360SN/A# 466658Snate@binkert.org# Base classes for use outside of the assembler 472680Sktlim@umich.edu# 4812716Smichael.lebeane@amd.com########################################################################## 492474SN/A 5013031Sbrandon.potter@amd.comclass Micro_Container(object): 51360SN/A def __init__(self, name): 528229Snate@binkert.org self.microops = [] 5311794Sbrandon.potter@amd.com self.name = name 5411794Sbrandon.potter@amd.com self.directives = {} 556029Ssteve.reinhardt@amd.com self.micro_classes = {} 56360SN/A self.labels = {} 57360SN/A 582107SN/A def add_microop(self, microop): 59360SN/A self.microops.append(microop) 6013933Sbrandon.potter@amd.com 6113933Sbrandon.potter@amd.com def __str__(self): 6213933Sbrandon.potter@amd.com string = "%s:\n" % self.name 6313933Sbrandon.potter@amd.com for microop in self.microops: 6413933Sbrandon.potter@amd.com string += " %s\n" % microop 6513933Sbrandon.potter@amd.com return string 661450SN/A 6713995Sbrandon.potter@amd.comclass Combinational_Macroop(Micro_Container): 68360SN/A pass 6911794Sbrandon.potter@amd.com 702484SN/Aclass Rom_Macroop(object): 712484SN/A def __init__(self, name, target): 72360SN/A self.name = name 73360SN/A self.target = target 74360SN/A 751450SN/A def __str__(self): 7613995Sbrandon.potter@amd.com return "%s: %s\n" % (self.name, self.target) 77360SN/A 7811794Sbrandon.potter@amd.comclass Rom(Micro_Container): 7911794Sbrandon.potter@amd.com def __init__(self, name): 8011794Sbrandon.potter@amd.com super(Rom, self).__init__(name) 8110831Ssteve.reinhardt@amd.com self.externs = {} 82360SN/A 838149SChris.Emmons@ARM.com########################################################################## 848149SChris.Emmons@ARM.com# 858149SChris.Emmons@ARM.com# Support classes 8611886Sbrandon.potter@amd.com# 8711911SBrandon.Potter@amd.com########################################################################## 8811886Sbrandon.potter@amd.com 8911911SBrandon.Potter@amd.comclass Label(object): 9011911SBrandon.Potter@amd.com def __init__(self): 9111911SBrandon.Potter@amd.com self.extern = False 9211911SBrandon.Potter@amd.com self.name = "" 9314024Sgabeblack@google.com 9411886Sbrandon.potter@amd.comclass Block(object): 9511911SBrandon.Potter@amd.com def __init__(self): 9611911SBrandon.Potter@amd.com self.statements = [] 9711911SBrandon.Potter@amd.com 9811911SBrandon.Potter@amd.comclass Statement(object): 9911911SBrandon.Potter@amd.com def __init__(self): 10011911SBrandon.Potter@amd.com self.is_microop = False 10113995Sbrandon.potter@amd.com self.is_directive = False 10211911SBrandon.Potter@amd.com self.params = "" 10311911SBrandon.Potter@amd.com 10413995Sbrandon.potter@amd.comclass Microop(Statement): 10511911SBrandon.Potter@amd.com def __init__(self): 10611911SBrandon.Potter@amd.com super(Microop, self).__init__() 10711911SBrandon.Potter@amd.com self.mnemonic = "" 10811911SBrandon.Potter@amd.com self.labels = [] 10911911SBrandon.Potter@amd.com self.is_microop = True 11011911SBrandon.Potter@amd.com 11111911SBrandon.Potter@amd.comclass Directive(Statement): 11211911SBrandon.Potter@amd.com def __init__(self): 11311911SBrandon.Potter@amd.com super(Directive, self).__init__() 11411911SBrandon.Potter@amd.com self.name = "" 11511911SBrandon.Potter@amd.com self.is_directive = True 11611911SBrandon.Potter@amd.com 11711911SBrandon.Potter@amd.com########################################################################## 11811911SBrandon.Potter@amd.com# 11911911SBrandon.Potter@amd.com# Functions that handle common tasks 12011911SBrandon.Potter@amd.com# 12111911SBrandon.Potter@amd.com########################################################################## 12211911SBrandon.Potter@amd.com 12311911SBrandon.Potter@amd.comdef print_error(message): 12411911SBrandon.Potter@amd.com print 12511911SBrandon.Potter@amd.com print "*** %s" % message 12611911SBrandon.Potter@amd.com print 12711911SBrandon.Potter@amd.com 12811911SBrandon.Potter@amd.comdef handle_statement(parser, container, statement): 12911911SBrandon.Potter@amd.com if statement.is_microop: 13011911SBrandon.Potter@amd.com if statement.mnemonic not in parser.microops.keys(): 13113644Sqtt2@cornell.edu raise Exception, "Unrecognized mnemonic: %s" % statement.mnemonic 13213644Sqtt2@cornell.edu parser.symbols["__microopClassFromInsideTheAssembler"] = \ 13313644Sqtt2@cornell.edu parser.microops[statement.mnemonic] 13411911SBrandon.Potter@amd.com try: 13511911SBrandon.Potter@amd.com microop = eval('__microopClassFromInsideTheAssembler(%s)' % 13611911SBrandon.Potter@amd.com statement.params, {}, parser.symbols) 13711911SBrandon.Potter@amd.com except: 13811911SBrandon.Potter@amd.com print_error("Error creating microop object with mnemonic %s." % \ 13911911SBrandon.Potter@amd.com statement.mnemonic) 14013644Sqtt2@cornell.edu raise 14113644Sqtt2@cornell.edu try: 14213644Sqtt2@cornell.edu for label in statement.labels: 14313644Sqtt2@cornell.edu container.labels[label.name] = microop 14413644Sqtt2@cornell.edu if label.extern: 14513644Sqtt2@cornell.edu container.externs[label.name] = microop 14613644Sqtt2@cornell.edu container.add_microop(microop) 14713644Sqtt2@cornell.edu except: 14813644Sqtt2@cornell.edu print_error("Error adding microop.") 14913644Sqtt2@cornell.edu raise 15013644Sqtt2@cornell.edu elif statement.is_directive: 15113644Sqtt2@cornell.edu if statement.name not in container.directives.keys(): 15213644Sqtt2@cornell.edu raise Exception, "Unrecognized directive: %s" % statement.name 15313644Sqtt2@cornell.edu parser.symbols["__directiveFunctionFromInsideTheAssembler"] = \ 15413644Sqtt2@cornell.edu container.directives[statement.name] 15513644Sqtt2@cornell.edu try: 15613644Sqtt2@cornell.edu eval('__directiveFunctionFromInsideTheAssembler(%s)' % 15713644Sqtt2@cornell.edu statement.params, {}, parser.symbols) 15813644Sqtt2@cornell.edu except: 15911911SBrandon.Potter@amd.com print_error("Error executing directive.") 16011911SBrandon.Potter@amd.com print container.directives 16111911SBrandon.Potter@amd.com raise 16211911SBrandon.Potter@amd.com else: 16311911SBrandon.Potter@amd.com raise Exception, "Didn't recognize the type of statement", statement 16411911SBrandon.Potter@amd.com 16511911SBrandon.Potter@amd.com########################################################################## 16611911SBrandon.Potter@amd.com# 16711911SBrandon.Potter@amd.com# Lexer specification 16811911SBrandon.Potter@amd.com# 16911911SBrandon.Potter@amd.com########################################################################## 17011911SBrandon.Potter@amd.com 17111886Sbrandon.potter@amd.com# Error handler. Just call exit. Output formatted to work under 17211886Sbrandon.potter@amd.com# Emacs compile-mode. Optional 'print_traceback' arg, if set to True, 17311911SBrandon.Potter@amd.com# prints a Python stack backtrace too (can be handy when trying to 17411911SBrandon.Potter@amd.com# debug the parser itself). 17511911SBrandon.Potter@amd.comdef error(lineno, string, print_traceback = False): 17611911SBrandon.Potter@amd.com # Print a Python stack backtrace if requested. 17711911SBrandon.Potter@amd.com if (print_traceback): 17811911SBrandon.Potter@amd.com traceback.print_exc() 17911911SBrandon.Potter@amd.com if lineno != 0: 18011911SBrandon.Potter@amd.com line_str = "%d:" % lineno 18111911SBrandon.Potter@amd.com else: 18211911SBrandon.Potter@amd.com line_str = "" 18311911SBrandon.Potter@amd.com sys.exit("%s %s" % (line_str, string)) 18411911SBrandon.Potter@amd.com 18511911SBrandon.Potter@amd.comreserved = ('DEF', 'MACROOP', 'ROM', 'EXTERN') 18611911SBrandon.Potter@amd.com 18711911SBrandon.Potter@amd.comtokens = reserved + ( 18811911SBrandon.Potter@amd.com # identifier 18911911SBrandon.Potter@amd.com 'ID', 19011911SBrandon.Potter@amd.com # arguments for microops and directives 19111911SBrandon.Potter@amd.com 'PARAMS', 19213644Sqtt2@cornell.edu 19313644Sqtt2@cornell.edu 'LPAREN', 'RPAREN', 19413644Sqtt2@cornell.edu 'LBRACE', 'RBRACE', 19513644Sqtt2@cornell.edu 'COLON', 'SEMI', 'DOT', 19613644Sqtt2@cornell.edu 'NEWLINE' 19713644Sqtt2@cornell.edu ) 19813644Sqtt2@cornell.edu 19913644Sqtt2@cornell.edu# New lines are ignored at the top level, but they end statements in the 20013644Sqtt2@cornell.edu# assembler 20113644Sqtt2@cornell.edustates = ( 20213644Sqtt2@cornell.edu ('asm', 'exclusive'), 20313644Sqtt2@cornell.edu ('params', 'exclusive'), 20413644Sqtt2@cornell.edu) 20513644Sqtt2@cornell.edu 20613644Sqtt2@cornell.edureserved_map = { } 20713644Sqtt2@cornell.edufor r in reserved: 20813644Sqtt2@cornell.edu reserved_map[r.lower()] = r 20913644Sqtt2@cornell.edu 21013644Sqtt2@cornell.edu# Ignore comments 21113644Sqtt2@cornell.edudef t_ANY_COMMENT(t): 21213644Sqtt2@cornell.edu r'\#[^\n]*(?=\n)' 21313644Sqtt2@cornell.edu 21413644Sqtt2@cornell.edudef t_ANY_MULTILINECOMMENT(t): 21513644Sqtt2@cornell.edu r'/\*([^/]|((?<!\*)/))*\*/' 21613644Sqtt2@cornell.edu 21713644Sqtt2@cornell.edu# A colon marks the end of a label. It should follow an ID which will 21813644Sqtt2@cornell.edu# put the lexer in the "params" state. Seeing the colon will put it back 21911911SBrandon.Potter@amd.com# in the "asm" state since it knows it saw a label and not a mnemonic. 22011886Sbrandon.potter@amd.comdef t_params_COLON(t): 2218149SChris.Emmons@ARM.com r':' 2228149SChris.Emmons@ARM.com t.lexer.begin('asm') 22313995Sbrandon.potter@amd.com return t 224360SN/A 22513995Sbrandon.potter@amd.com# Parameters are a string of text which don't contain an unescaped statement 226360SN/A# statement terminator, ie a newline or semi colon. 227360SN/Adef t_params_PARAMS(t): 2281450SN/A r'([^\n;\\]|(\\[\n;\\]))+' 22913995Sbrandon.potter@amd.com t.lineno += t.value.count('\n') 2306109Ssanchezd@stanford.edu unescapeParamsRE = re.compile(r'(\\[\n;\\])') 23113995Sbrandon.potter@amd.com def unescapeParams(mo): 2326109Ssanchezd@stanford.edu val = mo.group(0) 2336109Ssanchezd@stanford.edu return val[1] 2346109Ssanchezd@stanford.edu t.value = unescapeParamsRE.sub(unescapeParams, t.value) 23513995Sbrandon.potter@amd.com t.lexer.begin('asm') 236360SN/A return t 23710318Sandreas.hansson@arm.com 238360SN/A# An "ID" in the micro assembler is either a label, directive, or mnemonic 239360SN/A# If it's either a directive or a mnemonic, it will be optionally followed by 240360SN/A# parameters. If it's a label, the following colon will make the lexer stop 2411450SN/A# looking for parameters. 24213995Sbrandon.potter@amd.comdef t_asm_ID(t): 243360SN/A r'[A-Za-z_]\w*' 244360SN/A t.type = reserved_map.get(t.value, 'ID') 2456701Sgblack@eecs.umich.edu t.lexer.begin('params') 24613995Sbrandon.potter@amd.com return t 2476701Sgblack@eecs.umich.edu 2485748SSteve.Reinhardt@amd.com# If there is a label and you're -not- in the assembler (which would be caught 24911905SBrandon.Potter@amd.com# above), don't start looking for parameters. 25011905SBrandon.Potter@amd.comdef t_ANY_ID(t): 25111905SBrandon.Potter@amd.com r'[A-Za-z_]\w*' 2525748SSteve.Reinhardt@amd.com t.type = reserved_map.get(t.value, 'ID') 2535748SSteve.Reinhardt@amd.com return t 2545748SSteve.Reinhardt@amd.com 25511905SBrandon.Potter@amd.com# Braces enter and exit micro assembly 2565748SSteve.Reinhardt@amd.comdef t_INITIAL_LBRACE(t): 25711905SBrandon.Potter@amd.com r'\{' 2585748SSteve.Reinhardt@amd.com t.lexer.begin('asm') 25911905SBrandon.Potter@amd.com return t 26011905SBrandon.Potter@amd.com 26110318Sandreas.hansson@arm.comdef t_asm_RBRACE(t): 2625748SSteve.Reinhardt@amd.com r'\}' 26310318Sandreas.hansson@arm.com t.lexer.begin('INITIAL') 2646687Stjones1@inf.ed.ac.uk return t 2656687Stjones1@inf.ed.ac.uk 2666687Stjones1@inf.ed.ac.uk# At the top level, keep track of newlines only for line counting. 26711905SBrandon.Potter@amd.comdef t_INITIAL_NEWLINE(t): 26814024Sgabeblack@google.com r'\n+' 2696687Stjones1@inf.ed.ac.uk t.lineno += t.value.count('\n') 2706687Stjones1@inf.ed.ac.uk 27110318Sandreas.hansson@arm.com# In the micro assembler, do line counting but also return a token. The 2726687Stjones1@inf.ed.ac.uk# token is needed by the parser to detect the end of a statement. 2738852Sandreas.hansson@arm.comdef t_asm_NEWLINE(t): 27410318Sandreas.hansson@arm.com r'\n+' 2756687Stjones1@inf.ed.ac.uk t.lineno += t.value.count('\n') 27611906SBrandon.Potter@amd.com return t 27710318Sandreas.hansson@arm.com 2788852Sandreas.hansson@arm.com# A newline or semi colon when looking for params signals that the statement 2796687Stjones1@inf.ed.ac.uk# is over and the lexer should go back to looking for regular assembly. 2806687Stjones1@inf.ed.ac.ukdef t_params_NEWLINE(t): 2812474SN/A r'\n+' 2821450SN/A t.lineno += t.value.count('\n') 2835748SSteve.Reinhardt@amd.com t.lexer.begin('asm') 28411905SBrandon.Potter@amd.com return t 28511380Salexandru.dutu@amd.com 28611905SBrandon.Potter@amd.comdef t_params_SEMI(t): 28711905SBrandon.Potter@amd.com r';' 288360SN/A t.lexer.begin('asm') 289360SN/A return t 29011886Sbrandon.potter@amd.com 29113995Sbrandon.potter@amd.com# Basic regular expressions to pick out simple tokens 29211886Sbrandon.potter@amd.comt_ANY_LPAREN = r'\(' 29311886Sbrandon.potter@amd.comt_ANY_RPAREN = r'\)' 29413995Sbrandon.potter@amd.comt_ANY_SEMI = r';' 29511886Sbrandon.potter@amd.comt_ANY_DOT = r'\.' 29611886Sbrandon.potter@amd.com 29711886Sbrandon.potter@amd.comt_ANY_ignore = ' \t\x0c' 29811886Sbrandon.potter@amd.com 29911886Sbrandon.potter@amd.comdef t_ANY_error(t): 300360SN/A error(t.lineno, "illegal character '%s'" % t.value[0]) 3011450SN/A t.skip(1) 30213995Sbrandon.potter@amd.com 303360SN/A########################################################################## 3046701Sgblack@eecs.umich.edu# 30513995Sbrandon.potter@amd.com# Parser specification 30610931Sbrandon.potter@amd.com# 30710931Sbrandon.potter@amd.com########################################################################## 30811856Sbrandon.potter@amd.com 309360SN/A# Start symbol for a file which may have more than one macroop or rom 310360SN/A# specification. 3111450SN/Adef p_file(t): 31213995Sbrandon.potter@amd.com 'file : opt_rom_or_macros' 313360SN/A 3146701Sgblack@eecs.umich.edudef p_opt_rom_or_macros_0(t): 31513995Sbrandon.potter@amd.com 'opt_rom_or_macros : ' 31610931Sbrandon.potter@amd.com 3176701Sgblack@eecs.umich.edudef p_opt_rom_or_macros_1(t): 3186701Sgblack@eecs.umich.edu 'opt_rom_or_macros : rom_or_macros' 319360SN/A 32011856Sbrandon.potter@amd.comdef p_rom_or_macros_0(t): 32111856Sbrandon.potter@amd.com 'rom_or_macros : rom_or_macro' 32210931Sbrandon.potter@amd.com 32311856Sbrandon.potter@amd.comdef p_rom_or_macros_1(t): 32410931Sbrandon.potter@amd.com 'rom_or_macros : rom_or_macros rom_or_macro' 32510931Sbrandon.potter@amd.com 326360SN/Adef p_rom_or_macro_0(t): 3271458SN/A '''rom_or_macro : rom_block 328360SN/A | macroop_def''' 329360SN/A 330360SN/A# Defines a section of microcode that should go in the current ROM 3311450SN/Adef p_rom_block(t): 33213995Sbrandon.potter@amd.com 'rom_block : DEF ROM block SEMI' 3334118Sgblack@eecs.umich.edu if not t.parser.rom: 3346701Sgblack@eecs.umich.edu print_error("Rom block found, but no Rom object specified.") 33513995Sbrandon.potter@amd.com raise TypeError, "Rom block found, but no Rom object was specified." 33610931Sbrandon.potter@amd.com for statement in t[3].statements: 3376701Sgblack@eecs.umich.edu handle_statement(t.parser, t.parser.rom, statement) 3386701Sgblack@eecs.umich.edu t[0] = t.parser.rom 3396701Sgblack@eecs.umich.edu 3406701Sgblack@eecs.umich.edu# Defines a macroop that jumps to an external label in the ROM 3414118Sgblack@eecs.umich.edudef p_macroop_def_0(t): 34211856Sbrandon.potter@amd.com 'macroop_def : DEF MACROOP ID LPAREN ID RPAREN SEMI' 34311856Sbrandon.potter@amd.com if not t.parser.rom_macroop_type: 34410931Sbrandon.potter@amd.com print_error("ROM based macroop found, but no ROM macroop class was specified.") 34511856Sbrandon.potter@amd.com raise TypeError, "ROM based macroop found, but no ROM macroop class was specified." 34610931Sbrandon.potter@amd.com macroop = t.parser.rom_macroop_type(t[3], t[5]) 3474118Sgblack@eecs.umich.edu t.parser.macroops[t[3]] = macroop 3484118Sgblack@eecs.umich.edu 34910931Sbrandon.potter@amd.com 3504118Sgblack@eecs.umich.edu# Defines a macroop that is combinationally generated 3514118Sgblack@eecs.umich.edudef p_macroop_def_1(t): 35211379Sbrandon.potter@amd.com 'macroop_def : DEF MACROOP ID block SEMI' 3534118Sgblack@eecs.umich.edu try: 35411379Sbrandon.potter@amd.com curop = t.parser.macro_type(t[3]) 35511379Sbrandon.potter@amd.com except TypeError: 35611379Sbrandon.potter@amd.com print_error("Error creating macroop object.") 35714024Sgabeblack@google.com raise 35811379Sbrandon.potter@amd.com for statement in t[4].statements: 3594118Sgblack@eecs.umich.edu handle_statement(t.parser, curop, statement) 3604118Sgblack@eecs.umich.edu t.parser.macroops[t[3]] = curop 3614118Sgblack@eecs.umich.edu 3624118Sgblack@eecs.umich.edu# A block of statements 36313995Sbrandon.potter@amd.comdef p_block(t): 364360SN/A 'block : LBRACE statements RBRACE' 36511383Sbrandon.potter@amd.com block = Block() 36611383Sbrandon.potter@amd.com block.statements = t[2] 36711383Sbrandon.potter@amd.com t[0] = block 3681458SN/A 369360SN/Adef p_statements_0(t): 370360SN/A 'statements : statement' 371360SN/A if t[1]: 372360SN/A t[0] = [t[1]] 373360SN/A else: 3741450SN/A t[0] = [] 37513995Sbrandon.potter@amd.com 376360SN/Adef p_statements_1(t): 3776701Sgblack@eecs.umich.edu 'statements : statements statement' 37813995Sbrandon.potter@amd.com if t[2]: 37911906SBrandon.Potter@amd.com t[1].append(t[2]) 3806701Sgblack@eecs.umich.edu t[0] = t[1] 38111906SBrandon.Potter@amd.com 382360SN/Adef p_statement(t): 383360SN/A 'statement : content_of_statement end_of_statement' 384360SN/A t[0] = t[1] 38514024Sgabeblack@google.com 386360SN/A# A statement can be a microop or an assembler directive 3871458SN/Adef p_content_of_statement_0(t): 388360SN/A '''content_of_statement : microop 389360SN/A | directive''' 3901450SN/A t[0] = t[1] 39113995Sbrandon.potter@amd.com 3925513SMichael.Adler@intel.com# Ignore empty statements 3935513SMichael.Adler@intel.comdef p_content_of_statement_1(t): 3946731Svince@csl.cornell.edu 'content_of_statement : ' 39513995Sbrandon.potter@amd.com pass 39611906SBrandon.Potter@amd.com 3976701Sgblack@eecs.umich.edu# Statements are ended by newlines or a semi colon 39811906SBrandon.Potter@amd.comdef p_end_of_statement(t): 3995513SMichael.Adler@intel.com '''end_of_statement : NEWLINE 4005513SMichael.Adler@intel.com | SEMI''' 40113883Sdavid.hashe@amd.com pass 4025513SMichael.Adler@intel.com 4035513SMichael.Adler@intel.com# Different flavors of microop to avoid shift/reduce errors 4045513SMichael.Adler@intel.comdef p_microop_0(t): 4055513SMichael.Adler@intel.com 'microop : labels ID' 4065513SMichael.Adler@intel.com microop = Microop() 4075513SMichael.Adler@intel.com microop.labels = t[1] 4085513SMichael.Adler@intel.com microop.mnemonic = t[2] 40910955Sdavid.hashe@amd.com t[0] = microop 41011856Sbrandon.potter@amd.com 4115513SMichael.Adler@intel.comdef p_microop_1(t): 41210955Sdavid.hashe@amd.com 'microop : ID' 4135513SMichael.Adler@intel.com microop = Microop() 4145513SMichael.Adler@intel.com microop.mnemonic = t[1] 4155513SMichael.Adler@intel.com t[0] = microop 4165513SMichael.Adler@intel.com 41714024Sgabeblack@google.comdef p_microop_2(t): 4185513SMichael.Adler@intel.com 'microop : labels ID PARAMS' 4195513SMichael.Adler@intel.com microop = Microop() 4205513SMichael.Adler@intel.com microop.labels = t[1] 4215513SMichael.Adler@intel.com microop.mnemonic = t[2] 42210203SAli.Saidi@ARM.com microop.params = t[3] 42313995Sbrandon.potter@amd.com t[0] = microop 42410203SAli.Saidi@ARM.com 42513995Sbrandon.potter@amd.comdef p_microop_3(t): 42610203SAli.Saidi@ARM.com 'microop : ID PARAMS' 4275513SMichael.Adler@intel.com microop = Microop() 4285513SMichael.Adler@intel.com microop.mnemonic = t[1] 42913995Sbrandon.potter@amd.com microop.params = t[2] 4305513SMichael.Adler@intel.com t[0] = microop 4315513SMichael.Adler@intel.com 43213995Sbrandon.potter@amd.com# Labels in the microcode 4335513SMichael.Adler@intel.comdef p_labels_0(t): 43414024Sgabeblack@google.com 'labels : label' 43510223Ssteve.reinhardt@amd.com t[0] = [t[1]] 4365513SMichael.Adler@intel.com 43713883Sdavid.hashe@amd.comdef p_labels_1(t): 43813883Sdavid.hashe@amd.com 'labels : labels label' 4395513SMichael.Adler@intel.com t[1].append(t[2]) 44011906SBrandon.Potter@amd.com t[0] = t[1] 4416701Sgblack@eecs.umich.edu 4426701Sgblack@eecs.umich.edudef p_label_0(t): 44311906SBrandon.Potter@amd.com 'label : ID COLON' 4445513SMichael.Adler@intel.com label = Label() 44510955Sdavid.hashe@amd.com label.is_extern = False 44610955Sdavid.hashe@amd.com label.text = t[1] 44710955Sdavid.hashe@amd.com t[0] = label 44810955Sdavid.hashe@amd.com 44911140Sjthestness@gmail.comdef p_label_1(t): 45011140Sjthestness@gmail.com 'label : EXTERN ID COLON' 45111851Sbrandon.potter@amd.com label = Label() 45211140Sjthestness@gmail.com label.is_extern = True 45311140Sjthestness@gmail.com label.text = t[2] 45411140Sjthestness@gmail.com t[0] = label 45511140Sjthestness@gmail.com 45611140Sjthestness@gmail.com# Directives for the macroop 45711140Sjthestness@gmail.comdef p_directive_0(t): 45811140Sjthestness@gmail.com 'directive : DOT ID' 45911140Sjthestness@gmail.com directive = Directive() 46011140Sjthestness@gmail.com directive.name = t[2] 46111140Sjthestness@gmail.com t[0] = directive 46211140Sjthestness@gmail.com 46311140Sjthestness@gmail.comdef p_directive_1(t): 46411140Sjthestness@gmail.com 'directive : DOT ID PARAMS' 46511140Sjthestness@gmail.com directive = Directive() 46611140Sjthestness@gmail.com directive.name = t[2] 46711140Sjthestness@gmail.com directive.params = t[3] 46811140Sjthestness@gmail.com t[0] = directive 46911140Sjthestness@gmail.com 47010955Sdavid.hashe@amd.com# Parse error handler. Note that the argument here is the offending 47110955Sdavid.hashe@amd.com# *token*, not a grammar symbol (hence the need to use t.value) 47210955Sdavid.hashe@amd.comdef p_error(t): 47310955Sdavid.hashe@amd.com if t: 47411140Sjthestness@gmail.com error(t.lineno, "syntax error at '%s'" % t.value) 47510955Sdavid.hashe@amd.com else: 47611140Sjthestness@gmail.com error(0, "unknown syntax error", True) 47711140Sjthestness@gmail.com 47811140Sjthestness@gmail.comclass MicroAssembler(object): 47911140Sjthestness@gmail.com 48011140Sjthestness@gmail.com def __init__(self, macro_type, microops, 48110955Sdavid.hashe@amd.com rom = None, rom_macroop_type = None): 4825513SMichael.Adler@intel.com self.lexer = lex.lex() 48314024Sgabeblack@google.com self.parser = yacc.yacc() 4845513SMichael.Adler@intel.com self.parser.macro_type = macro_type 4855513SMichael.Adler@intel.com self.parser.macroops = {} 4865513SMichael.Adler@intel.com self.parser.microops = microops 4875513SMichael.Adler@intel.com self.parser.rom = rom 4885513SMichael.Adler@intel.com self.parser.rom_macroop_type = rom_macroop_type 48913995Sbrandon.potter@amd.com self.parser.symbols = {} 490511SN/A self.symbols = self.parser.symbols 49113995Sbrandon.potter@amd.com 49210633Smichaelupton@gmail.com def assemble(self, asm): 49310633Smichaelupton@gmail.com self.parser.parse(asm, lexer=self.lexer) 49410633Smichaelupton@gmail.com macroops = self.parser.macroops 49513995Sbrandon.potter@amd.com self.parser.macroops = {} 49610633Smichaelupton@gmail.com return macroops 4971706SN/A