| Index: src/trusted/validator_arm/dgen_decoder_output.py
|
| diff --git a/src/trusted/validator_arm/dgen_decoder_output.py b/src/trusted/validator_arm/dgen_decoder_output.py
|
| deleted file mode 100644
|
| index 0efee0eb97617371cdd5188c92ec6da1417ce0d4..0000000000000000000000000000000000000000
|
| --- a/src/trusted/validator_arm/dgen_decoder_output.py
|
| +++ /dev/null
|
| @@ -1,273 +0,0 @@
|
| -#!/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)
|
|
|