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

Side by Side Diff: src/trusted/validator_ragel/gen_dfa.py

Issue 12090047: Validator_ragel: REX prefix support in gen_dfa.py. (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: comments Created 7 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/trusted/validator_ragel/gen_dfa_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 import itertools 6 import itertools
7 import re 7 import re
8 import StringIO 8 import StringIO
9 9
10 10
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 'att-show-name-suffix-q', 107 'att-show-name-suffix-q',
108 'att-show-name-suffix-x', 108 'att-show-name-suffix-x',
109 'att-show-name-suffix-y', 109 'att-show-name-suffix-y',
110 'att-show-name-suffix-w', 110 'att-show-name-suffix-w',
111 111
112 # Spurious REX.W bits (instructions 'in', 'out', 'nop', etc). 112 # Spurious REX.W bits (instructions 'in', 'out', 'nop', etc).
113 'spurious-rex.w' 113 'spurious-rex.w'
114 ] 114 ]
115 115
116 116
117 def Attribute(name):
118 assert name in SUPPORTED_ATTRIBUTES
119 return name
120
121
117 class Operand(object): 122 class Operand(object):
118 123
119 __slots__ = [ 124 __slots__ = [
120 'read_write_attr', 125 'read_write_attr',
121 'arg_type', 126 'arg_type',
122 'size', 127 'size',
123 'implicit', 128 'implicit',
124 'index'] 129 'index']
125 130
126 # Operand read/write modes. 131 # Operand read/write modes.
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 185
181 TODO(shcherbina): it is possible that format will also be needed by 186 TODO(shcherbina): it is possible that format will also be needed by
182 validator64 in order to identify zero-extending instruction, but I'm not 187 validator64 in order to identify zero-extending instruction, but I'm not
183 sure how it will be done. 188 sure how it will be done.
184 189
185 Returns: 190 Returns:
186 String like '8bit', '32bit', 'xmm', 'mmx', etc. 191 String like '8bit', '32bit', 'xmm', 'mmx', etc.
187 """ 192 """
188 if self.size == 'b': 193 if self.size == 'b':
189 return '8bit' 194 return '8bit'
195 if self.size == 'w':
196 return '16bit'
197 if self.size == 'd':
198 return '32bit'
199 if self.size == 'q':
200 return '64bit'
190 # TODO(shcherbina): support other formats. 201 # TODO(shcherbina): support other formats.
191 raise NotImplementedError() 202 raise NotImplementedError()
192 203
193 def __str__(self): 204 def __str__(self):
194 return '%s%s%s%s' % ( 205 return '%s%s%s%s' % (
195 self.read_write_attr, 206 self.read_write_attr,
196 self.arg_type, 207 self.arg_type,
197 self.size, 208 self.size,
198 '*' if self.implicit else '') 209 '*' if self.implicit else '')
199 210
200 211
201 class Instruction(object): 212 class Instruction(object):
202 213
203 __slots__ = [ 214 __slots__ = [
204 'name', 215 'name',
205 'operands', 216 'operands',
206 'opcodes', 217 'opcodes',
207 'attributes'] 218 'attributes',
219 'rex']
220
221 class RexStatus(object):
222 __slots__ = [
223 'b_matters',
224 'x_matters',
225 'r_matters',
226 'w_matters',
227 'w_set']
228
229 def __init__(self):
230 self.rex = self.RexStatus()
231 self.rex.b_matters = False
232 self.rex.x_matters = False
233 self.rex.r_matters = False
234 self.rex.w_matters = True
235 self.rex.w_set = False
208 236
209 @staticmethod 237 @staticmethod
210 def Parse(line): 238 def Parse(line):
211 """Parse one line of def file and return initialized Instruction object. 239 """Parse one line of def file and return initialized Instruction object.
212 240
213 Args: 241 Args:
214 line: One line of def file (two or three columns separated by 242 line: One line of def file (two or three columns separated by
215 COLUMN_SEPARATOR). First column defines instruction name and operands, 243 COLUMN_SEPARATOR). First column defines instruction name and operands,
216 second one - opcodes and encoding details, third (optional) 244 second one - opcodes and encoding details, third (optional)
217 one - instruction attributes. 245 one - instruction attributes.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 """Return name in a form suitable to use as part of C identifier. 350 """Return name in a form suitable to use as part of C identifier.
323 351
324 In principle, collisions are possible, but will result in compilation, 352 In principle, collisions are possible, but will result in compilation,
325 failure, so we are not checking for them here for simplicity. 353 failure, so we are not checking for them here for simplicity.
326 354
327 Returns: 355 Returns:
328 Instruction name with all non-alphanumeric characters replaced with '_'. 356 Instruction name with all non-alphanumeric characters replaced with '_'.
329 """ 357 """
330 return re.sub(r'\W', '_', self.name) 358 return re.sub(r'\W', '_', self.name)
331 359
360 def IsVexOrXop(self):
361 return (self.opcodes[0] == '0xc4' and self.name != 'les' or
362 self.opcodes[0] == '0x8f' and self.name != 'pop')
363
332 def __str__(self): 364 def __str__(self):
333 return ' '.join([self.name] + map(str, self.operands)) 365 return ' '.join([self.name] + map(str, self.operands))
334 366
335 367
336 DECODER = object() 368 DECODER = object()
337 VALIDATOR = object() 369 VALIDATOR = object()
338 370
339 371
340 class InstructionPrinter(object): 372 class InstructionPrinter(object):
341 373
342 def __init__(self, mode, bitness): 374 def __init__(self, mode, bitness):
343 assert mode in [DECODER, VALIDATOR] 375 assert mode in [DECODER, VALIDATOR]
344 assert bitness in [32, 64] 376 assert bitness in [32, 64]
345 self._mode = mode 377 self._mode = mode
346 self._bitness = bitness 378 self._bitness = bitness
347 self._out = StringIO.StringIO() 379 self._out = StringIO.StringIO()
348 380
349 def GetContent(self): 381 def GetContent(self):
350 return self._out.getvalue() 382 return self._out.getvalue()
351 383
384 def _PrintRexPrefix(self, instruction):
385 """Print machine for REX prefix."""
386 if self._bitness != 64:
387 return
388 if instruction.IsVexOrXop():
389 return
390 if Attribute('norex') in instruction.attributes:
391 return
392
393 if instruction.rex.w_set:
394 self._out.write('REXW_RXB\n')
395 else:
396 self._out.write('REX_RXB?\n')
397
352 def _PrintOpcode(self, instruction): 398 def _PrintOpcode(self, instruction):
399 """Print machine for opcode."""
353 main_opcode_part = instruction.GetMainOpcodePart() 400 main_opcode_part = instruction.GetMainOpcodePart()
354 if instruction.HasRegisterInOpcode(): 401 if instruction.HasRegisterInOpcode():
355 assert not instruction.HasModRM() 402 assert not instruction.HasModRM()
356 assert not instruction.HasOpcodeInsteadOfImmediate() 403 assert not instruction.HasOpcodeInsteadOfImmediate()
357 404
358 self._out.write(' '.join(main_opcode_part[:-1])) 405 self._out.write(' '.join(main_opcode_part[:-1]))
359 406
360 # Register is encoded in three least significant bits of the last byte 407 # Register is encoded in three least significant bits of the last byte
361 # of the opcode (in 64-bit case REX.B bit also will be involved, but it 408 # of the opcode (in 64-bit case REX.B bit also will be involved, but it
362 # will be handled elsewhere). 409 # will be handled elsewhere).
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 self._out.write('@operand%d_%s\n' % (i, operand.GetFormat())) 443 self._out.write('@operand%d_%s\n' % (i, operand.GetFormat()))
397 444
398 # TODO(shcherbina): print operand sources and extract implicit operands. 445 # TODO(shcherbina): print operand sources and extract implicit operands.
399 446
400 # TODO(shcherbina): print '@last_byte_is_not_immediate' when approptiate. 447 # TODO(shcherbina): print '@last_byte_is_not_immediate' when approptiate.
401 # TODO(shcherbina): print '@modifiable_instruction' in validator64 if 448 # TODO(shcherbina): print '@modifiable_instruction' in validator64 if
402 # attribute 'nacl-amd64-modifiable' is present. 449 # attribute 'nacl-amd64-modifiable' is present.
403 # TODO(shcherbina): print info about CPU features. 450 # TODO(shcherbina): print info about CPU features.
404 # TODO(shcherbina): att_show_name_suffix. 451 # TODO(shcherbina): att_show_name_suffix.
405 452
406 # TODO(shcherbina): print spurious REX stuff (probably not in this 453 if (self._mode == DECODER and
407 # function). 454 self._bitness == 64 and
455 not instruction.IsVexOrXop()):
456 # Note that even if 'norex' attribute is present, we print
457 # @spurious_rex_... actions because NOP needs them (and it has REX
458 # prefix specified as part of the opcode).
459 # TODO(shcherbina): fix that?
460 if not instruction.rex.b_matters:
461 self._out.write('@set_spurious_rex_b\n')
462 if not instruction.rex.x_matters:
463 self._out.write('@set_spurious_rex_x\n')
464 if not instruction.rex.r_matters:
465 self._out.write('@set_spurious_rex_r\n')
466 if not instruction.rex.w_matters:
467 self._out.write('@set_spurious_rex_w\n')
408 468
409 def _PrintOperandSource(self, operand, source): 469 def _PrintOperandSource(self, operand, source):
470 """Print action specifying operand source."""
410 # TODO(shcherbina): add mechanism to check that all operand sources are 471 # TODO(shcherbina): add mechanism to check that all operand sources are
411 # printed. 472 # printed.
412 self._out.write('@operand%d_%s\n' % (operand.index, source)) 473 self._out.write('@operand%d_%s\n' % (operand.index, source))
413 474
414 def _PrintImplicitOperandSources(self, instruction): 475 def _PrintImplicitOperandSources(self, instruction):
415 """Print actions specifying sources of implicit operands. 476 """Print actions specifying sources of implicit operands.
416 477
417 Args: 478 Args:
418 instruction: instruction. 479 instruction: instruction.
419 480
420 Returns: 481 Returns:
421 None. 482 None.
422 """ 483 """
423 operand = instruction.FindOperand('a') 484 operand = instruction.FindOperand('a')
424 if operand is not None: 485 if operand is not None:
425 self._PrintOperandSource(operand, 'rax') 486 self._PrintOperandSource(operand, 'rax')
426 # TODO(shcherbina): handle other implicit operands. 487 # TODO(shcherbina): handle other implicit operands.
427 488
428 def PrintInstructionWithoutModRM(self, instruction): 489 def PrintInstructionWithoutModRM(self, instruction):
429 # TODO(shcherbina): print legacy prefixes. 490 # TODO(shcherbina): print legacy prefixes.
430 # TODO(shcherbina): print REX prefix.
431 491
492 assert not instruction.IsVexOrXop(), 'not supported yet'
432 assert not instruction.HasModRM() 493 assert not instruction.HasModRM()
494
495 self._PrintRexPrefix(instruction)
496
433 assert not instruction.HasOpcodeInsteadOfImmediate(), 'not supported yet' 497 assert not instruction.HasOpcodeInsteadOfImmediate(), 'not supported yet'
434 498
435 self._PrintOpcode(instruction) 499 self._PrintOpcode(instruction)
436 self._out.write('\n') 500 self._out.write('\n')
437 501
438 self._PrintSignature(instruction) 502 self._PrintSignature(instruction)
439 self._PrintImplicitOperandSources(instruction) 503 self._PrintImplicitOperandSources(instruction)
440 504
441 # TODO(shcherbina): print immediate args. 505 # TODO(shcherbina): print immediate args.
442 506
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 594
531 return result 595 return result
532 596
533 597
534 def main(): 598 def main():
535 pass 599 pass
536 600
537 601
538 if __name__ == '__main__': 602 if __name__ == '__main__':
539 main() 603 main()
OLDNEW
« no previous file with comments | « no previous file | src/trusted/validator_ragel/gen_dfa_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698