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

Side by Side Diff: src/trusted/validator_arm/dgen_decoder_output.py

Issue 10191011: Moving dgen_ scripts out of validator_arm into a common directory. (Closed)
Patch Set: Updates per code review. 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 unified diff | Download patch
« no previous file with comments | « src/trusted/validator_arm/dgen_core.py ('k') | src/trusted/validator_arm/dgen_dump.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6 #
7
8 """
9 Responsible for generating the decoder based on parsed
10 table representations.
11 """
12
13
14 import dgen_opt
15 import dgen_output
16
17 # This file generates the class decoder Decoder as defined by the
18 # decoder tables. The code is specifically written to minimize the
19 # number of decoder classes needed to parse valid ARM
20 # instructions. Many rows in the table use the same decoder class. In
21 # addition, we optimize tables by merging, so long as the same decoder
22 # class is built.
23 #
24 # The following files are generated:
25 #
26 # decoder.h
27 # decoder.cc
28 #
29 # decoder.h declares the generated decoder parser class while
30 # decoder.cc contains the implementation of that decoder class.
31 #
32 # For testing purposes (see dgen_test_output.py) different rules are
33 # applied. Note: It may be worth reading dgen_test_output.py preamble
34 # to get a better understanding of decoder actions, and why we need
35 # the "action_filter" methods.
36
37 # Defines the header for decoder.h
38 H_HEADER="""
39 %(FILE_HEADER)s
40
41 #ifndef %(IFDEF_NAME)s
42 #define %(IFDEF_NAME)s
43
44 #include "native_client/src/trusted/validator_arm/decode.h"
45 #include "native_client/src/trusted/validator_arm/inst_classes.h"
46
47 namespace nacl_arm_dec {
48 """
49
50 DECODER_DECLARE_HEADER="""
51 // Defines a decoder class selector for instructions.
52 class %(decoder_name)s : DecoderState {
53 public:
54 explicit %(decoder_name)s();
55 virtual ~%(decoder_name)s();
56
57 // Parses the given instruction, returning the decoder to use.
58 virtual const ClassDecoder& decode(const Instruction) const;
59
60 private:
61 """
62
63 DECODER_DECLARE_METHOD_COMMENTS="""
64 // The following list of methods correspond to each decoder table,
65 // and implements the pattern matching of the corresponding bit
66 // patterns. After matching the corresponding bit patterns, they
67 // either call other methods in this list (corresponding to another
68 // decoder table), or they return the instance field that implements
69 // the class decoder that should be used to decode the particular
70 // instruction.
71 """
72
73 DECODER_DECLARE_METHOD="""
74 inline const ClassDecoder& decode_%(table_name)s(
75 const Instruction insn) const;
76 """
77
78 DECODER_DECLARE_FIELD_COMMENTS="""
79 // The following fields define the set of class decoders
80 // that can be returned by the API function "decode". They
81 // are created once as instance fields, and then returned
82 // by the table methods above. This speeds up the code since
83 // the class decoders need to only be built once (and reused
84 // for each call to "decode").
85 """
86
87 DECODER_DECLARE_FIELD="""
88 const %(decoder)s %(decoder)s_instance_;
89 """
90
91 DECODER_DECLARE_FOOTER="""
92 };
93 """
94
95 H_FOOTER="""
96 } // namespace nacl_arm_dec
97 #endif // %(IFDEF_NAME)s
98 """
99
100 def generate_h(decoder, decoder_name, filename, out):
101 """Entry point to the decoder for .h file.
102
103 Args:
104 decoder: The decoder defined by the list of Table objects to process.
105 decoder_name: The name of the decoder state to build.
106 filename: The (localized) name for the .h file.
107 named_decoders: If true, generate a decoder state with named instances.
108 out: a COutput object to write to.
109 """
110 if not decoder.primary: raise Exception('No tables provided.')
111
112 # Before starting, remove all testing information from the parsed tables.
113 decoder = decoder.action_filter(['name'])
114
115 values = {
116 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
117 'IFDEF_NAME': dgen_output.ifdef_name(filename),
118 'decoder_name': decoder_name,
119 }
120 out.write(H_HEADER % values)
121 out.write(DECODER_DECLARE_HEADER % values)
122 out.write(DECODER_DECLARE_METHOD_COMMENTS)
123 for table in decoder.tables():
124 values['table_name'] = table.name
125 out.write(DECODER_DECLARE_METHOD % values)
126 out.write(DECODER_DECLARE_FIELD_COMMENTS)
127 for action in decoder.decoders():
128 values['decoder'] = action.name;
129 out.write(DECODER_DECLARE_FIELD % values)
130 out.write(DECODER_DECLARE_FOOTER % values)
131 out.write(H_FOOTER % values)
132
133 # Defines the header for DECODER.h
134 CC_HEADER="""
135 %(FILE_HEADER)s
136
137 #include "%(header_filename)s"
138
139 #include <stdio.h>
140
141 namespace nacl_arm_dec {
142
143 """
144
145 CONSTRUCTOR_HEADER="""
146 %(decoder_name)s::%(decoder_name)s() : DecoderState()
147 """
148
149 CONSTRUCTOR_FIELD_INIT="""
150 , %(decoder)s_instance_()
151 """
152
153 CONSTRUCTOR_FOOTER="""
154 {}
155
156 %(decoder_name)s::~%(decoder_name)s() {}
157 """
158
159 METHOD_HEADER="""
160 // Implementation of table: %(table_name)s.
161 // Specified by: %(citation)s
162 const ClassDecoder& %(decoder_name)s::decode_%(table_name)s(
163 const Instruction insn) const
164 {
165 """
166
167 METHOD_DISPATCH="""
168 if (%(tests)s)
169 """
170
171 METHOD_DISPATCH_CLASS_DECODER="""
172 return %(decoder)s_instance_;
173 """
174
175 METHOD_DISPATCH_SUBMETHOD="""
176 return decode_%(subtable_name)s(insn);
177 """
178
179 METHOD_FOOTER="""
180 // Catch any attempt to fall though ...
181 fprintf(stderr, "TABLE IS INCOMPLETE: %(table_name)s could not parse %%08X",
182 insn.bits(31, 0));
183 return Forbidden_instance_;
184 }
185 """
186
187 DECODER_METHOD="""
188 const ClassDecoder& %(decoder_name)s::decode(const Instruction insn) const {
189 return decode_%(entry_table_name)s(insn);
190 }
191 """
192
193 CC_FOOTER="""
194 } // namespace nacl_arm_dec
195 """
196
197 def generate_cc(decoder, decoder_name, filename, out):
198 """Implementation of the decoder in .cc file
199
200 Args:
201 decoder: The decoder defined by the list of Table objects to process.
202 decoder_name: The name of the decoder state to build.
203 filename: The (localized) name for the .h file.
204 named_decoders: If true, generate a decoder state with named instances.
205 out: a COutput object to write to.
206 """
207 if not decoder.primary: raise Exception('No tables provided.')
208 assert filename.endswith('.cc')
209
210 # Before starting, remove all testing information from the parsed tables.
211 decoder = decoder.action_filter(['name'])
212 values = {
213 'FILE_HEADER': dgen_output.HEADER_BOILERPLATE,
214 'header_filename': filename[:-2] + 'h',
215 'decoder_name': decoder_name,
216 'entry_table_name': decoder.primary.name,
217 }
218 out.write(CC_HEADER % values)
219 _generate_constructors(decoder, values, out)
220 _generate_methods(decoder, values, out)
221 out.write(DECODER_METHOD % values)
222 out.write(CC_FOOTER % values)
223
224 def _generate_constructors(decoder, values, out):
225 out.write(CONSTRUCTOR_HEADER % values)
226 for decoder in decoder.decoders():
227 values['decoder'] = decoder.name
228 out.write(CONSTRUCTOR_FIELD_INIT % values)
229 out.write(CONSTRUCTOR_FOOTER % values)
230
231 def _generate_methods(decoder, values, out):
232 for table in decoder.tables():
233 opt_rows = sorted(dgen_opt.optimize_rows(table.rows))
234 print ("Table %s: %d rows minimized to %d"
235 % (table.name, len(table.rows), len(opt_rows)))
236
237 values['table_name'] = table.name
238 values['citation'] = table.citation
239 out.write(METHOD_HEADER % values)
240
241 # Add message to stop compilation warnings if this table
242 # doesn't require subtables to select a class decoder.
243 if not [r for r in opt_rows
244 if r.action.__class__.__name__ == 'DecoderMethod']:
245 out.write(" UNREFERENCED_PARAMETER(insn);")
246
247 for row in opt_rows:
248 # Each row consists of a set of bit patterns defining if the row
249 # is applicable. Convert this into a sequence of anded C test
250 # expressions. For example, convert the following pair of bit
251 # patterns:
252 #
253 # xxxx1010xxxxxxxxxxxxxxxxxxxxxxxx
254 # xxxxxxxxxxxxxxxxxxxxxxxxxxxx0101
255 #
256 # Each instruction is masked to get the the bits, and then
257 # tested against the corresponding expected bits. Hence, the
258 # above example is converted to:
259 #
260 # ((insn & 0x0F000000) != 0x0C000000) &&
261 # ((insn & 0x0000000F) != 0x00000005)
262 values['tests'] = ' && '.join(["(%s)" % p.to_c_expr('insn')
263 for p in row.patterns])
264 out.write(METHOD_DISPATCH % values)
265 if row.action.__class__.__name__ == 'DecoderAction':
266 values['decoder'] = row.action.name
267 out.write(METHOD_DISPATCH_CLASS_DECODER % values)
268 elif row.action.__class__.__name__ == 'DecoderMethod':
269 values['subtable_name'] = row.action.name
270 out.write(METHOD_DISPATCH_SUBMETHOD % values)
271 else:
272 raise Exception('Bad table action: %s' % repr(row.action))
273 out.write(METHOD_FOOTER % values)
OLDNEW
« no previous file with comments | « src/trusted/validator_arm/dgen_core.py ('k') | src/trusted/validator_arm/dgen_dump.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698