misc: string.join has been removed in python3
[gem5.git] / src / arch / micro_asm.py
index a8a63e1f80ca920e43f3c3ee4f10c7008011404b..536f70994a9fc7775257c3ccf843cb1cb40f595e 100644 (file)
 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# Authors: Gabe Black
+
+from __future__ import print_function
 
 import os
 import sys
 import re
-import string
 import traceback
 # get type names
 from types import *
 
-# Prepend the directory where the PLY lex & yacc modules are found
-# to the search path.
-sys.path[0:0] = [os.environ['M5_PLY']]
-
 from ply import lex
 from ply import yacc
 
@@ -55,7 +50,7 @@ class Micro_Container(object):
         self.micro_classes = {}
         self.labels = {}
 
-    def add_microop(self, microop):
+    def add_microop(self, mnemonic, microop):
         self.microops.append(microop)
 
     def __str__(self):
@@ -121,33 +116,43 @@ class Directive(Statement):
 ##########################################################################
 
 def print_error(message):
-    print
-    print "*** %s" % message
-    print
+    print()
+    print("*** %s" % message)
+    print()
 
 def handle_statement(parser, container, statement):
     if statement.is_microop:
+        if statement.mnemonic not in parser.microops.keys():
+            raise Exception, "Unrecognized mnemonic: %s" % statement.mnemonic
+        parser.symbols["__microopClassFromInsideTheAssembler"] = \
+            parser.microops[statement.mnemonic]
         try:
-            microop = eval('parser.microops[statement.mnemonic](%s)' %
-                    statement.params)
+            microop = eval('__microopClassFromInsideTheAssembler(%s)' %
+                    statement.params, {}, parser.symbols)
         except:
-            print_error("Error creating microop object.")
+            print_error("Error creating microop object with mnemonic %s." % \
+                    statement.mnemonic)
             raise
         try:
             for label in statement.labels:
-                container.labels[label.name] = microop
-                if label.extern:
-                    container.externs[label.name] = microop
-            container.add_microop(microop)
+                container.labels[label.text] = microop
+                if label.is_extern:
+                    container.externs[label.text] = microop
+            container.add_microop(statement.mnemonic, microop)
         except:
             print_error("Error adding microop.")
             raise
     elif statement.is_directive:
+        if statement.name not in container.directives.keys():
+            raise Exception, "Unrecognized directive: %s" % statement.name
+        parser.symbols["__directiveFunctionFromInsideTheAssembler"] = \
+            container.directives[statement.name]
         try:
-            eval('container.directives[statement.name](%s)' % statement.params)
+            eval('__directiveFunctionFromInsideTheAssembler(%s)' %
+                    statement.params, {}, parser.symbols)
         except:
             print_error("Error executing directive.")
-            print container.directives
+            print(container.directives)
             raise
     else:
         raise Exception, "Didn't recognize the type of statement", statement
@@ -212,6 +217,19 @@ def t_params_COLON(t):
     t.lexer.begin('asm')
     return t
 
+# Parameters are a string of text which don't contain an unescaped statement
+# statement terminator, ie a newline or semi colon.
+def t_params_PARAMS(t):
+    r'([^\n;\\]|(\\[\n;\\]))+'
+    t.lineno += t.value.count('\n')
+    unescapeParamsRE = re.compile(r'(\\[\n;\\])')
+    def unescapeParams(mo):
+        val = mo.group(0)
+        return val[1]
+    t.value = unescapeParamsRE.sub(unescapeParams, t.value)
+    t.lexer.begin('asm')
+    return t
+
 # An "ID" in the micro assembler is either a label, directive, or mnemonic
 # If it's either a directive or a mnemonic, it will be optionally followed by
 # parameters. If it's a label, the following colon will make the lexer stop
@@ -219,31 +237,19 @@ def t_params_COLON(t):
 def t_asm_ID(t):
     r'[A-Za-z_]\w*'
     t.type = reserved_map.get(t.value, 'ID')
-    t.lexer.begin('params')
+    # If the ID is really "extern", we shouldn't start looking for parameters
+    # yet. The real ID, the label itself, is coming up.
+    if t.type != 'EXTERN':
+        t.lexer.begin('params')
     return t
 
-# If there is a label and you're -not- in the assember (which would be caught
+# If there is a label and you're -not- in the assembler (which would be caught
 # above), don't start looking for parameters.
 def t_ANY_ID(t):
     r'[A-Za-z_]\w*'
     t.type = reserved_map.get(t.value, 'ID')
     return t
 
-# Parameters are a string of text which don't contain an unescaped statement
-# statement terminator, ie a newline or semi colon.
-def t_params_PARAMS(t):
-    r'([^\n;\\]|(\\[\n;\\]))+'
-    t.lineno += t.value.count('\n')
-    unescapeParamsRE = re.compile(r'(\\[\n;\\])')
-    def unescapeParams(mo):
-        val = mo.group(0)
-        print "About to sub %s for %s" % (val[1], val)
-        return val[1]
-    print "Looking for matches in %s" % t.value
-    t.value = unescapeParamsRE.sub(unescapeParams, t.value)
-    t.lexer.begin('asm')
-    return t
-
 # Braces enter and exit micro assembly
 def t_INITIAL_LBRACE(t):
     r'\{'
@@ -431,6 +437,11 @@ def p_labels_1(t):
     t[1].append(t[2])
     t[0] = t[1]
 
+# labels on lines by themselves are attached to the following instruction.
+def p_labels_2(t):
+    'labels : labels NEWLINE'
+    t[0] = t[1]
+
 def p_label_0(t):
     'label : ID COLON'
     label = Label()
@@ -478,14 +489,11 @@ class MicroAssembler(object):
         self.parser.microops = microops
         self.parser.rom = rom
         self.parser.rom_macroop_type = rom_macroop_type
+        self.parser.symbols = {}
+        self.symbols = self.parser.symbols
 
     def assemble(self, asm):
         self.parser.parse(asm, lexer=self.lexer)
-        # Begin debug printing
-        for macroop in self.parser.macroops.values():
-            print macroop
-        print self.parser.rom
-        # End debug printing
         macroops = self.parser.macroops
         self.parser.macroops = {}
         return macroops