Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Unified Diff: src/trusted/validator_arm/dgen_decoder_output.py

Issue 9960043: Finish separation of testing from sel_ldr validation. Also, automate (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/trusted/validator_arm/dgen_core.py ('k') | src/trusted/validator_arm/dgen_input.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/trusted/validator_arm/dgen_decoder_output.py
===================================================================
--- src/trusted/validator_arm/dgen_decoder_output.py (revision 0)
+++ src/trusted/validator_arm/dgen_decoder_output.py (revision 0)
@@ -0,0 +1,273 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2012 The Native Client Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+
+"""
+Responsible for generating the decoder based on parsed
+table representations.
+"""
+
+
+import dgen_opt
+import dgen_output
+
+# This file generates the class decoder Decoder as defined by the
+# decoder tables. The code is specifically written to minimize the
+# number of decoder classes needed to parse valid ARM
+# instructions. Many rows in the table use the same decoder class. In
+# addition, we optimize tables by merging, so long as the same decoder
+# class is built.
+#
+# The following files are generated:
+#
+# decoder.h
+# decoder.cc
+#
+# decoder.h declares the generated decoder parser class while
+# decoder.cc contains the implementation of that decoder class.
+#
+# For testing purposes (see dgen_test_output.py) different rules are
+# applied. Note: It may be worth reading dgen_test_output.py preamble
+# to get a better understanding of decoder actions, and why we need
+# the "action_filter" methods.
+
+# Defines the header for decoder.h
+H_HEADER="""
+%(FILE_HEADER)s
+
+#ifndef %(IFDEF_NAME)s
+#define %(IFDEF_NAME)s
+
+#include "native_client/src/trusted/validator_arm/decode.h"
+#include "native_client/src/trusted/validator_arm/inst_classes.h"
+
+namespace nacl_arm_dec {
+"""
+
+DECODER_DECLARE_HEADER="""
+// Defines a decoder class selector for instructions.
+class %(decoder_name)s : DecoderState {
+ public:
+ explicit %(decoder_name)s();
+ virtual ~%(decoder_name)s();
+
+ // Parses the given instruction, returning the decoder to use.
+ virtual const ClassDecoder& decode(const Instruction) const;
+
+ private:
+"""
+
+DECODER_DECLARE_METHOD_COMMENTS="""
+ // The following list of methods correspond to each decoder table,
+ // and implements the pattern matching of the corresponding bit
+ // patterns. After matching the corresponding bit patterns, they
+ // either call other methods in this list (corresponding to another
+ // decoder table), or they return the instance field that implements
+ // the class decoder that should be used to decode the particular
+ // instruction.
+"""
+
+DECODER_DECLARE_METHOD="""
+ inline const ClassDecoder& decode_%(table_name)s(
+ const Instruction insn) const;
+"""
+
+DECODER_DECLARE_FIELD_COMMENTS="""
+ // The following fields define the set of class decoders
+ // that can be returned by the API function "decode". They
+ // are created once as instance fields, and then returned
+ // by the table methods above. This speeds up the code since
+ // the class decoders need to only be built once (and reused
+ // for each call to "decode").
+"""
+
+DECODER_DECLARE_FIELD="""
+ const %(decoder)s %(decoder)s_instance_;
+"""
+
+DECODER_DECLARE_FOOTER="""
+};
+"""
+
+H_FOOTER="""
+} // namespace nacl_arm_dec
+#endif // %(IFDEF_NAME)s
+"""
+
+def generate_h(decoder, decoder_name, filename, out):
+ """Entry point to the decoder for .h file.
+
+ Args:
+ decoder: The decoder defined by the list of Table objects to process.
+ decoder_name: The name of the decoder state to build.
+ filename: The (localized) name for the .h file.
+ named_decoders: If true, generate a decoder state with named instances.
+ out: a COutput object to write to.
+ """
+ if not decoder.primary: raise Exception('No tables provided.')
+
+ # Before starting, remove all testing information from the parsed tables.
+ decoder = decoder.action_filter(['name'])
+
+ values = {
+ 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
+ 'IFDEF_NAME': dgen_output.ifdef_name(filename),
+ 'decoder_name': decoder_name,
+ }
+ out.write(H_HEADER % values)
+ out.write(DECODER_DECLARE_HEADER % values)
+ out.write(DECODER_DECLARE_METHOD_COMMENTS)
+ for table in decoder.tables():
+ values['table_name'] = table.name
+ out.write(DECODER_DECLARE_METHOD % values)
+ out.write(DECODER_DECLARE_FIELD_COMMENTS)
+ for action in decoder.decoders():
+ values['decoder'] = action.name;
+ out.write(DECODER_DECLARE_FIELD % values)
+ out.write(DECODER_DECLARE_FOOTER % values)
+ out.write(H_FOOTER % values)
+
+# Defines the header for DECODER.h
+CC_HEADER="""
+%(FILE_HEADER)s
+
+#include "%(header_filename)s"
+
+#include <stdio.h>
+
+namespace nacl_arm_dec {
+
+"""
+
+CONSTRUCTOR_HEADER="""
+%(decoder_name)s::%(decoder_name)s() : DecoderState()
+"""
+
+CONSTRUCTOR_FIELD_INIT="""
+ , %(decoder)s_instance_()
+"""
+
+CONSTRUCTOR_FOOTER="""
+{}
+
+%(decoder_name)s::~%(decoder_name)s() {}
+"""
+
+METHOD_HEADER="""
+// Implementation of table: %(table_name)s.
+// Specified by: %(citation)s
+const ClassDecoder& %(decoder_name)s::decode_%(table_name)s(
+ const Instruction insn) const
+{
+"""
+
+METHOD_DISPATCH="""
+ if (%(tests)s)
+"""
+
+METHOD_DISPATCH_CLASS_DECODER="""
+ return %(decoder)s_instance_;
+"""
+
+METHOD_DISPATCH_SUBMETHOD="""
+ return decode_%(subtable_name)s(insn);
+"""
+
+METHOD_FOOTER="""
+ // Catch any attempt to fall though ...
+ fprintf(stderr, "TABLE IS INCOMPLETE: %(table_name)s could not parse %%08X",
+ insn.bits(31, 0));
+ return Forbidden_instance_;
+}
+"""
+
+DECODER_METHOD="""
+const ClassDecoder& %(decoder_name)s::decode(const Instruction insn) const {
+ return decode_%(entry_table_name)s(insn);
+}
+"""
+
+CC_FOOTER="""
+} // namespace nacl_arm_dec
+"""
+
+def generate_cc(decoder, decoder_name, filename, out):
+ """Implementation of the decoder in .cc file
+
+ Args:
+ decoder: The decoder defined by the list of Table objects to process.
+ decoder_name: The name of the decoder state to build.
+ filename: The (localized) name for the .h file.
+ named_decoders: If true, generate a decoder state with named instances.
+ out: a COutput object to write to.
+ """
+ if not decoder.primary: raise Exception('No tables provided.')
+ assert filename.endswith('.cc')
+
+ # Before starting, remove all testing information from the parsed tables.
+ decoder = decoder.action_filter(['name'])
+ values = {
+ 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
+ 'header_filename': filename[:-2] + 'h',
+ 'decoder_name': decoder_name,
+ 'entry_table_name': decoder.primary.name,
+ }
+ out.write(CC_HEADER % values)
+ _generate_constructors(decoder, values, out)
+ _generate_methods(decoder, values, out)
+ out.write(DECODER_METHOD % values)
+ out.write(CC_FOOTER % values)
+
+def _generate_constructors(decoder, values, out):
+ out.write(CONSTRUCTOR_HEADER % values)
+ for decoder in decoder.decoders():
+ values['decoder'] = decoder.name
+ out.write(CONSTRUCTOR_FIELD_INIT % values)
+ out.write(CONSTRUCTOR_FOOTER % values)
+
+def _generate_methods(decoder, values, out):
+ for table in decoder.tables():
+ opt_rows = sorted(dgen_opt.optimize_rows(table.rows))
+ print ("Table %s: %d rows minimized to %d"
+ % (table.name, len(table.rows), len(opt_rows)))
+
+ values['table_name'] = table.name
+ values['citation'] = table.citation
+ out.write(METHOD_HEADER % values)
+
+ # Add message to stop compilation warnings if this table
+ # doesn't require subtables to select a class decoder.
+ if not [r for r in opt_rows
+ if r.action.__class__.__name__ == 'DecoderMethod']:
+ out.write(" UNREFERENCED_PARAMETER(insn);")
+
+ for row in opt_rows:
+ # Each row consists of a set of bit patterns defining if the row
+ # is applicable. Convert this into a sequence of anded C test
+ # expressions. For example, convert the following pair of bit
+ # patterns:
+ #
+ # xxxx1010xxxxxxxxxxxxxxxxxxxxxxxx
+ # xxxxxxxxxxxxxxxxxxxxxxxxxxxx0101
+ #
+ # Each instruction is masked to get the the bits, and then
+ # tested against the corresponding expected bits. Hence, the
+ # above example is converted to:
+ #
+ # ((insn & 0x0F000000) != 0x0C000000) &&
+ # ((insn & 0x0000000F) != 0x00000005)
+ values['tests'] = ' && '.join(["(%s)" % p.to_c_expr('insn')
+ for p in row.patterns])
+ out.write(METHOD_DISPATCH % values)
+ if row.action.__class__.__name__ == 'DecoderAction':
+ values['decoder'] = row.action.name
+ out.write(METHOD_DISPATCH_CLASS_DECODER % values)
+ elif row.action.__class__.__name__ == 'DecoderMethod':
+ values['subtable_name'] = row.action.name
+ out.write(METHOD_DISPATCH_SUBMETHOD % values)
+ else:
+ raise Exception('Bad table action: %s' % repr(row.action))
+ out.write(METHOD_FOOTER % values)
Property changes on: src/trusted/validator_arm/dgen_decoder_output.py
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « src/trusted/validator_arm/dgen_core.py ('k') | src/trusted/validator_arm/dgen_input.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698