arch: Allow named constants as decode case values.
authorGabe Black <gabeblack@google.com>
Thu, 4 Dec 2014 23:52:48 +0000 (15:52 -0800)
committerGabe Black <gabeblack@google.com>
Thu, 4 Dec 2014 23:52:48 +0000 (15:52 -0800)
The values in a "bitfield" or in an ExtMachInst structure member may not be a
literal value, it might select from an arbitrary collection of options. Instead
of using the raw value of those constants in the decoder, it's easier to tell
what's going on if they can be referred to as a symbolic constant/enum.

To support that, the ISA description language is extended slightly so that in
addition to integer literals, the case value for decode blobs can also be a
string literal. It's up to the ISA author to ensure that the string evaluates
to a legal constant value when interpretted as C++.

src/arch/isa_parser.py

index aa773ae800e70d631db3d82f73a683681356a7d7..f756161ea6abbb518f097ee61ec535efdbe54a06 100755 (executable)
@@ -1988,53 +1988,60 @@ StaticInstPtr
             error(t, 'instruction format "%s" not defined.' % t[1])
 
     # Nested decode block: if the value of the current field matches
-    # the specified constant, do a nested decode on some other field.
+    # the specified constant(s), do a nested decode on some other field.
     def p_decode_stmt_decode(self, t):
-        'decode_stmt : case_label COLON decode_block'
-        label = t[1]
+        'decode_stmt : case_list COLON decode_block'
+        case_list = t[1]
         codeObj = t[3]
         # just wrap the decoding code from the block as a case in the
         # outer switch statement.
-        codeObj.wrap_decode_block('\n%s:\n' % label)
-        codeObj.has_decode_default = (label == 'default')
+        codeObj.wrap_decode_block('\n%s\n' % ''.join(case_list))
+        codeObj.has_decode_default = (case_list == ['default:'])
         t[0] = codeObj
 
     # Instruction definition (finally!).
     def p_decode_stmt_inst(self, t):
-        'decode_stmt : case_label COLON inst SEMI'
-        label = t[1]
+        'decode_stmt : case_list COLON inst SEMI'
+        case_list = t[1]
         codeObj = t[3]
-        codeObj.wrap_decode_block('\n%s:' % label, 'break;\n')
-        codeObj.has_decode_default = (label == 'default')
+        codeObj.wrap_decode_block('\n%s' % ''.join(case_list), 'break;\n')
+        codeObj.has_decode_default = (case_list == ['default:'])
         t[0] = codeObj
 
-    # The case label is either a list of one or more constants or
-    # 'default'
-    def p_case_label_0(self, t):
-        'case_label : intlit_list'
-        def make_case(intlit):
-            if intlit >= 2**32:
-                return 'case ULL(%#x)' % intlit
-            else:
-                return 'case %#x' % intlit
-        t[0] = ': '.join(map(make_case, t[1]))
+    # The constant list for a decode case label must be non-empty, and must
+    # either be the keyword 'default', or made up of one or more
+    # comma-separated integer literals or strings which evaluate to
+    # constants when compiled as C++.
+    def p_case_list_0(self, t):
+        'case_list : DEFAULT'
+        t[0] = ['default:']
+
+    def prep_int_lit_case_label(self, lit):
+        if lit >= 2**32:
+            return 'case ULL(%#x): ' % lit
+        else:
+            return 'case %#x: ' % lit
 
-    def p_case_label_1(self, t):
-        'case_label : DEFAULT'
-        t[0] = 'default'
+    def prep_str_lit_case_label(self, lit):
+        return 'case %s: ' % lit
 
-    #
-    # The constant list for a decode case label must be non-empty, but
-    # may have one or more comma-separated integer literals in it.
-    #
-    def p_intlit_list_0(self, t):
-        'intlit_list : INTLIT'
-        t[0] = [t[1]]
+    def p_case_list_1(self, t):
+        'case_list : INTLIT'
+        t[0] = [self.prep_int_lit_case_label(t[1])]
+
+    def p_case_list_2(self, t):
+        'case_list : STRLIT'
+        t[0] = [self.prep_str_lit_case_label(t[1])]
+
+    def p_case_list_3(self, t):
+        'case_list : case_list COMMA INTLIT'
+        t[0] = t[1]
+        t[0].append(self.prep_int_lit_case_label(t[3]))
 
-    def p_intlit_list_1(self, t):
-        'intlit_list : intlit_list COMMA INTLIT'
+    def p_case_list_4(self, t):
+        'case_list : case_list COMMA STRLIT'
         t[0] = t[1]
-        t[0].append(t[3])
+        t[0].append(self.prep_str_lit_case_label(t[3]))
 
     # Define an instruction using the current instruction format
     # (specified by an enclosing format block).