Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright 2009 The Native Client Authors. All rights reserved. | 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 | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # be found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 # Copyright 2009, Google Inc. | |
| 7 # | 6 # |
| 8 | 7 |
| 9 """ | 8 """ |
| 10 The core object model for the Decoder Generator. The dg_input and dg_output | 9 The core object model for the Decoder Generator. The dg_input and dg_output |
| 11 modules both operate in terms of these classes. | 10 modules both operate in terms of these classes. |
| 12 """ | 11 """ |
| 13 | 12 |
| 14 import re | |
| 15 | |
| 16 def _popcount(int): | 13 def _popcount(int): |
| 17 """Returns the number of 1 bits in the input.""" | 14 """Returns the number of 1 bits in the input.""" |
| 18 count = 0 | 15 count = 0 |
| 19 for bit in range(0, 32): | 16 for bit in range(0, 32): |
| 20 count = count + ((int >> bit) & 1) | 17 count = count + ((int >> bit) & 1) |
| 21 return count | 18 return count |
| 22 | 19 |
| 23 | 20 |
| 24 class BitPattern(object): | 21 class BitPattern(object): |
| 25 """A pattern for matching strings of bits. See parse() for syntax.""" | 22 """A pattern for matching strings of bits. See parse() for syntax.""" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 elif c == 'x' or c == 'X': | 75 elif c == 'x' or c == 'X': |
| 79 mask = mask << 1 | 76 mask = mask << 1 |
| 80 value = value << 1 | 77 value = value << 1 |
| 81 else: | 78 else: |
| 82 raise Exception('Invalid characters in pattern %s' % pattern) | 79 raise Exception('Invalid characters in pattern %s' % pattern) |
| 83 | 80 |
| 84 mask = mask << lo_bit | 81 mask = mask << lo_bit |
| 85 value = value << lo_bit | 82 value = value << lo_bit |
| 86 return BitPattern(mask, value, op) | 83 return BitPattern(mask, value, op) |
| 87 | 84 |
| 85 @staticmethod | |
| 86 def parse_catch(pattern, hi_bit, lo_bit): | |
| 87 """"Calls parse with given arguments, and catches exceptions | |
| 88 raised. Prints raised exceptions and returns None. | |
| 89 """ | |
| 90 try: | |
| 91 return BitPattern.parse(pattern, hi_bit, lo_bit); | |
| 92 except Exception as ex: | |
| 93 print "Error: %s" % ex | |
| 94 return None | |
| 95 | |
| 88 def __init__(self, mask, value, op): | 96 def __init__(self, mask, value, op): |
| 89 """Initializes a BitPattern. | 97 """Initializes a BitPattern. |
| 90 | 98 |
| 91 Args: | 99 Args: |
| 92 mask: an integer with 1s in the bit positions we care about (e.g. | 100 mask: an integer with 1s in the bit positions we care about (e.g. |
| 93 those that are not X) | 101 those that are not X) |
| 94 value: an integer that would match our pattern, subject to the mask. | 102 value: an integer that would match our pattern, subject to the mask. |
| 95 op: either '==' or '!=', if the pattern is positive or negative, | 103 op: either '==' or '!=', if the pattern is positive or negative, |
| 96 respectively. | 104 respectively. |
| 97 """ | 105 """ |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 Because we don't use the column information for very much, we don't give | 207 Because we don't use the column information for very much, we don't give |
| 200 it a type -- we store it as a list of tuples. | 208 it a type -- we store it as a list of tuples. |
| 201 | 209 |
| 202 Args: | 210 Args: |
| 203 name: the name of the column (for diagnostic purposes only). | 211 name: the name of the column (for diagnostic purposes only). |
| 204 hi_bit: the leftmost bit included. | 212 hi_bit: the leftmost bit included. |
| 205 lo_bit: the rightmost bit included. | 213 lo_bit: the rightmost bit included. |
| 206 """ | 214 """ |
| 207 self._columns.append( (name, hi_bit, lo_bit) ) | 215 self._columns.append( (name, hi_bit, lo_bit) ) |
| 208 | 216 |
| 209 def add_row(self, col_patterns, action_string): | 217 def add_row(self, patterns, action, arch): |
| 210 """Adds a row to the table. | 218 """Adds a row to the table. |
| 211 Args: | 219 Args: |
| 212 col_patterns: a list containing a BitPattern for every column in the | 220 patterns: a list containing a BitPattern for every column in the |
| 213 table. | 221 table. |
| 214 action_string: a string indicating the action to take; must begin | 222 action_string: a string indicating the action to take; must begin |
|
sehr (please use chromium)
2012/04/19 19:52:47
s/action_string/action/
Karl
2012/04/24 19:58:27
Done.
| |
| 215 with '=' for a terminal instruction class, or '->' for a | 223 with '=' for a terminal instruction class, or '->' for a |
| 216 table-change. The action may end with an arch revision in | 224 table-change. |
| 217 parentheses. | 225 arg: a string defining the architectures it applies to. None |
|
sehr (please use chromium)
2012/04/19 19:52:47
s/arg/arch/
Karl
2012/04/24 19:58:27
Done.
| |
| 226 implies all. | |
| 218 """ | 227 """ |
| 219 arch = None | 228 self.rows.append(Row(patterns, action, arch)) |
| 220 m = re.match(r'^(=[A-Za-z0-9_]+)\(([^)]+)\)$', action_string) | |
| 221 if m: | |
| 222 action_string = m.group(1) | |
| 223 arch = m.group(2) | |
| 224 | 229 |
| 225 parsed = [] | 230 def define_pattern(self, pattern, column): |
| 226 for i in range(0, len(col_patterns)): | 231 """Converts the given input pattern (for the given column) to the |
| 227 col = self._columns[i] | 232 internal form. Returns None if pattern is bad. |
| 228 parsed.append(BitPattern.parse(col_patterns[i], col[1], col[2])) | 233 """ |
| 229 self.rows.append(Row(parsed, action_string, arch)) | 234 if column >= len(self._columns): return None |
| 235 col = self._columns[column] | |
| 236 return BitPattern.parse_catch(pattern, col[1], col[2]) | |
| 230 | 237 |
| 238 def action_filter(self, names): | |
| 239 """Returns a table with DecoderActions reduced to the given field names. | |
| 240 Used to optimize out duplicates, depending on context. | |
| 241 """ | |
| 242 table = Table(self.name, self.citation) | |
| 243 table._columns = self._columns | |
| 244 for r in self.rows: | |
| 245 table.add_row(r.patterns, r.action.action_filter(names), r.arch) | |
| 246 return table | |
| 247 | |
| 248 class DecoderAction: | |
| 249 """An action defining a class decoder to apply. | |
| 250 | |
| 251 Corresponds to the parsed decoder action: | |
| 252 decoder_action ::= id (id (word (id)?)?)? | |
| 253 | |
| 254 Fields are: | |
| 255 name - Name of class decoder selected. | |
| 256 rule - Name of the rule in ARM manual that defines | |
| 257 the decoder action. | |
| 258 pattern - The placement of 0/1's within any instruction | |
| 259 that is matched by the corresponding rule. | |
| 260 constraints - Additional constraints that apply to the rule. | |
| 261 """ | |
| 262 def __init__(self, name, rule, pattern, constraints): | |
| 263 self.name = name | |
| 264 self.rule = rule | |
| 265 self.pattern = pattern | |
| 266 self.constraints = constraints | |
| 267 | |
| 268 def action_filter(self, names): | |
| 269 return DecoderAction( | |
| 270 self.name if 'name' in names else None, | |
| 271 self.rule if 'rule' in names else None, | |
| 272 self.pattern if 'pattern' in names else None, | |
| 273 self.constraints if 'constraints' in names else None) | |
| 274 | |
| 275 def __eq__(self, other): | |
| 276 return (other.__class__.__name__ == 'DecoderAction' | |
| 277 and self.name == other.name | |
| 278 and self.rule == other.rule | |
| 279 and self.pattern == other.pattern | |
| 280 and self.constraints == other.constraints) | |
| 281 | |
| 282 def __cmp__(self, other): | |
| 283 # Order lexicographically on type/fields. | |
| 284 value = cmp(other.__class__.__name__, 'DecoderAction') | |
| 285 if value != 0: return value | |
| 286 value = cmp(self.name, other.name) | |
| 287 if value != 0: return value | |
| 288 value = cmp(self.rule, other.rule) | |
| 289 if value != 0: return value | |
| 290 value = cmp(self.pattern, other.pattern) | |
| 291 if value != 0: return value | |
| 292 return cmp(self.constraints, other.constraints) | |
| 293 | |
| 294 def __hash__(self): | |
| 295 return (hash('DecoderAction') + hash(self.name) + hash(self.rule) + | |
| 296 hash(self.pattern) + hash(self.constraints)) | |
| 297 | |
| 298 def __repr__(self): | |
| 299 return '=%s %s %s %s' % (self.name, self.rule, | |
| 300 self.pattern, self.constraints) | |
| 301 | |
| 302 class DecoderMethod(object): | |
| 303 """An action defining a parse method to call. | |
| 304 | |
| 305 Corresponds to the parsed decoder method: | |
| 306 decoder_method ::= '->' id | |
| 307 | |
| 308 Fields are: | |
| 309 name - The name of the corresponding table (i.e. method) that | |
| 310 should be used to continue searching for a matching class | |
| 311 decoder. | |
| 312 """ | |
| 313 def __init__(self, name): | |
| 314 self.name = name | |
| 315 | |
| 316 def action_filter(self, unused_names): | |
| 317 return self | |
| 318 | |
| 319 def __eq__(self, other): | |
| 320 return (self.__class__.__name__ == 'DecoderMethod' | |
| 321 and self.name == other.name) | |
| 322 | |
| 323 def __cmp__(self, other): | |
| 324 # Lexicographically compare types/fields. | |
| 325 value = cmp(other.__class__.__name__, 'DecoderMethod') | |
| 326 if value != 0: return value | |
| 327 return cmp(self.name, other.name) | |
| 328 | |
| 329 def __hash__(self): | |
| 330 return hash('DecoderMethod') + hash(self.name) | |
| 331 | |
| 332 def __repr__(self): | |
| 333 return '->%s' % self.name | |
| 231 | 334 |
| 232 class Row(object): | 335 class Row(object): |
| 233 """ A row in a Table.""" | 336 """ A row in a Table.""" |
| 234 def __init__(self, patterns, action, arch): | 337 def __init__(self, patterns, action, arch): |
| 235 """Initializes a Row. | 338 """Initializes a Row. |
| 236 Args: | 339 Args: |
| 237 patterns: a list of BitPatterns that must match for this Row to | 340 patterns: a list of BitPatterns that must match for this Row to |
| 238 match. | 341 match. |
| 239 action: the action to be taken if this Row matches. | 342 action: the action to be taken if this Row matches. |
| 240 arch: the minimum architecture that this Row can match. | 343 arch: the minimum architecture that this Row can match. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 270 self.action, self.arch) | 373 self.action, self.arch) |
| 271 | 374 |
| 272 def __cmp__(self, other): | 375 def __cmp__(self, other): |
| 273 """Compares two rows, so we can order pattern matches by specificity. | 376 """Compares two rows, so we can order pattern matches by specificity. |
| 274 """ | 377 """ |
| 275 return (cmp(self.patterns, other.patterns) | 378 return (cmp(self.patterns, other.patterns) |
| 276 or cmp(self.action, other.action)) | 379 or cmp(self.action, other.action)) |
| 277 | 380 |
| 278 def __repr__(self): | 381 def __repr__(self): |
| 279 return 'Row(%s, %s)' % (repr(self.patterns), repr(self.action)) | 382 return 'Row(%s, %s)' % (repr(self.patterns), repr(self.action)) |
| 383 | |
| 384 class Decoder(object): | |
| 385 """Defines a class decoder which consists of set of tables. | |
| 386 | |
| 387 A decoder has a primary (i.e. start) table to parse intructions (and | |
| 388 select the proper ClassDecoder), as well as a set of additional | |
| 389 tables to complete the selection of a class decoder. Instances of | |
| 390 this class correspond to the internal representation of parsed | |
| 391 decoder tables recognized by dgen_input.py (see that file for | |
| 392 details). | |
| 393 | |
| 394 Fields are: | |
| 395 primary - The entry parse table to find a class decoder. | |
| 396 tables - The (sorted) set of tables defined by a decoder. | |
| 397 | |
| 398 Note: maintains restriction that tables have unique names. | |
| 399 """ | |
| 400 | |
| 401 def __init__(self): | |
| 402 self.primary = None | |
| 403 self._is_sorted = False | |
| 404 self._tables = [] | |
| 405 | |
| 406 def add(self, table): | |
| 407 """Adds the table to the set of tables. Returns true if successful. | |
| 408 """ | |
| 409 if filter(lambda(t): t.name == table.name, self._tables): | |
| 410 # Table with name already defined, report error. | |
| 411 return False | |
| 412 else: | |
| 413 if not self._tables: | |
| 414 self.primary = table | |
| 415 self._tables.append(table) | |
| 416 self.is_sorted = False | |
| 417 return True | |
| 418 | |
| 419 def tables(self): | |
| 420 """Returns the sorted (by table name) list of tables""" | |
| 421 if self._is_sorted: return self._tables | |
| 422 self._tables = sorted(self._tables, key=lambda(tbl): tbl.name) | |
| 423 self._is_sorted = True | |
| 424 return self._tables | |
| 425 | |
| 426 def action_filter(self, names): | |
| 427 """Returns a new set of tables with actions reduced to the set of | |
| 428 field names. | |
| 429 """ | |
| 430 decoder = Decoder() | |
| 431 decoder._tables = sorted([ t.action_filter(names) for t in self._tables ], | |
| 432 key=lambda(tbl): tbl.name) | |
| 433 decoder.primary = filter( | |
| 434 lambda(t): t.name == self.primary.name, self._tables)[0] | |
| 435 return decoder | |
| 436 | |
| 437 def decoders(self): | |
| 438 """Returns the sorted sequence of DecoderAction's defined in the tables.""" | |
| 439 decoders = set() | |
| 440 for t in self._tables: | |
| 441 for r in t.rows: | |
| 442 if r.action.__class__.__name__ == 'DecoderAction': | |
| 443 decoders.add(r.action) | |
| 444 return sorted(decoders) | |
| 445 | |
| 446 def rules(self): | |
| 447 """Returns the sorted sequence of DecoderActions that define | |
| 448 the rule field. | |
| 449 """ | |
| 450 return sorted(filter(lambda (r): r.rule, self.decoders())) | |
| OLD | NEW |