OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2011 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 | 6 |
7 /* | 7 /* |
8 * ncdecode.c - table driven decoder for Native Client | 8 * ncdecode.c - table driven decoder for Native Client |
9 * | 9 * |
10 * Most x86 decoders I've looked at are big case statements. While | 10 * Most x86 decoders I've looked at are big case statements. While |
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 */ | 468 */ |
469 static void NCDecoderStateInitFields(NCDecoderState* this) { | 469 static void NCDecoderStateInitFields(NCDecoderState* this) { |
470 size_t dbindex; | 470 size_t dbindex; |
471 this->error_reporter = &kNCNullErrorReporter; | 471 this->error_reporter = &kNCNullErrorReporter; |
472 NCRemainingMemoryInit(this->mbase, this->size, &this->memory); | 472 NCRemainingMemoryInit(this->mbase, this->size, &this->memory); |
473 this->memory.error_fn = NCRemainingMemoryInternalError; | 473 this->memory.error_fn = NCRemainingMemoryInternalError; |
474 this->memory.error_fn_state = (void*) this; | 474 this->memory.error_fn_state = (void*) this; |
475 for (dbindex = 0; dbindex < this->inst_buffer_size; ++dbindex) { | 475 for (dbindex = 0; dbindex < this->inst_buffer_size; ++dbindex) { |
476 this->inst_buffer[dbindex].dstate = this; | 476 this->inst_buffer[dbindex].dstate = this; |
477 this->inst_buffer[dbindex].inst_index = dbindex; | 477 this->inst_buffer[dbindex].inst_index = dbindex; |
478 this->inst_buffer[dbindex].inst_count = 0; | 478 this->inst_buffer[dbindex].inst_count = 1; |
479 this->inst_buffer[dbindex].vpc = 0; | 479 this->inst_buffer[dbindex].vpc = 0; |
| 480 this->inst_buffer[dbindex].unchanged = FALSE; |
480 NCInstBytesInitMemory(&this->inst_buffer[dbindex].inst.bytes, | 481 NCInstBytesInitMemory(&this->inst_buffer[dbindex].inst.bytes, |
481 &this->memory); | 482 &this->memory); |
482 NCInstBytesPtrInit((NCInstBytesPtr*) &this->inst_buffer[dbindex].inst_bytes, | 483 NCInstBytesPtrInit((NCInstBytesPtr*) &this->inst_buffer[dbindex].inst_bytes, |
483 &this->inst_buffer[dbindex].inst.bytes); | 484 &this->inst_buffer[dbindex].inst.bytes); |
484 } | 485 } |
485 this->cur_inst_index = 0; | 486 this->cur_inst_index = 0; |
486 this->inst_buffer[0].vpc = this->vbase; | 487 this->inst_buffer[0].vpc = this->vbase; |
487 } | 488 } |
488 | 489 |
489 void NCDecoderStateConstruct(NCDecoderState* this, | 490 void NCDecoderStateConstruct(NCDecoderState* this, |
(...skipping 26 matching lines...) Expand all Loading... |
516 * in the ring buffer. Reset the state of that next instruction. | 517 * in the ring buffer. Reset the state of that next instruction. |
517 */ | 518 */ |
518 static NCDecoderInst* IncrementInst(NCDecoderInst* inst) { | 519 static NCDecoderInst* IncrementInst(NCDecoderInst* inst) { |
519 /* giving PreviousInst a positive number will get NextInst | 520 /* giving PreviousInst a positive number will get NextInst |
520 * better to keep the buffer switching logic in one place | 521 * better to keep the buffer switching logic in one place |
521 */ | 522 */ |
522 NCDecoderInst* next_inst = NCGetInstDiff(inst, 1); | 523 NCDecoderInst* next_inst = NCGetInstDiff(inst, 1); |
523 next_inst->vpc = inst->vpc + inst->inst.bytes.length; | 524 next_inst->vpc = inst->vpc + inst->inst.bytes.length; |
524 next_inst->dstate->cur_inst_index = next_inst->inst_index; | 525 next_inst->dstate->cur_inst_index = next_inst->inst_index; |
525 next_inst->inst_count = inst->inst_count + 1; | 526 next_inst->inst_count = inst->inst_count + 1; |
| 527 next_inst->unchanged = FALSE; |
526 return next_inst; | 528 return next_inst; |
527 } | 529 } |
528 | 530 |
529 /* Get the i-th byte of the current instruction being parsed. */ | 531 /* Get the i-th byte of the current instruction being parsed. */ |
530 static uint8_t GetInstByte(NCDecoderInst* dinst, ssize_t i) { | 532 static uint8_t GetInstByte(NCDecoderInst* dinst, ssize_t i) { |
531 if (i < dinst->inst.bytes.length) { | 533 if (i < dinst->inst.bytes.length) { |
532 return dinst->inst.bytes.byte[i]; | 534 return dinst->inst.bytes.byte[i]; |
533 } else { | 535 } else { |
534 return NCRemainingMemoryLookaheadInline(&dinst->dstate->memory, | 536 return NCRemainingMemoryLookaheadInline(&dinst->dstate->memory, |
535 i - dinst->inst.bytes.length); | 537 i - dinst->inst.bytes.length); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 (NaClPrintInst) NCNullErrorPrintInst, | 632 (NaClPrintInst) NCNullErrorPrintInst, |
631 }; | 633 }; |
632 | 634 |
633 Bool NCDecoderStateDecode(NCDecoderState* this) { | 635 Bool NCDecoderStateDecode(NCDecoderState* this) { |
634 NCDecoderInst* dinst = &this->inst_buffer[this->cur_inst_index]; | 636 NCDecoderInst* dinst = &this->inst_buffer[this->cur_inst_index]; |
635 const NaClPcAddress vlimit = this->vbase + this->size; | 637 const NaClPcAddress vlimit = this->vbase + this->size; |
636 DEBUG( printf("DecodeSegment(%p[%"NACL_PRIxNaClPcAddress | 638 DEBUG( printf("DecodeSegment(%p[%"NACL_PRIxNaClPcAddress |
637 "-%"NACL_PRIxNaClPcAddress"])\n", | 639 "-%"NACL_PRIxNaClPcAddress"])\n", |
638 (void*) this->memory.mpc, this->vbase, vlimit) ); | 640 (void*) this->memory.mpc, this->vbase, vlimit) ); |
639 NCDecoderStateNewSegment(this); | 641 NCDecoderStateNewSegment(this); |
640 dinst->inst_count = 1; | |
641 while (dinst->vpc < vlimit) { | 642 while (dinst->vpc < vlimit) { |
642 ConsumeNextInstruction(dinst); | 643 ConsumeNextInstruction(dinst); |
643 if (this->memory.overflow_count) { | 644 if (this->memory.overflow_count) { |
644 NaClPcAddress newpc = dinst->vpc + dinst->inst.bytes.length; | 645 NaClPcAddress newpc = dinst->vpc + dinst->inst.bytes.length; |
645 (*this->error_reporter->printf)( | 646 (*this->error_reporter->printf)( |
646 this->error_reporter, | 647 this->error_reporter, |
647 "%"NACL_PRIxNaClPcAddress" > %"NACL_PRIxNaClPcAddress | 648 "%"NACL_PRIxNaClPcAddress" > %"NACL_PRIxNaClPcAddress |
648 " (read overflow of %d bytes)\n", | 649 " (read overflow of %d bytes)\n", |
649 newpc, vlimit, this->memory.overflow_count); | 650 newpc, vlimit, this->memory.overflow_count); |
650 ErrorSegmentation(dinst); | 651 ErrorSegmentation(dinst); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 if (! (tthis->action_fn)(tthis, old_dinst, new_dinst)) { | 750 if (! (tthis->action_fn)(tthis, old_dinst, new_dinst)) { |
750 return FALSE; | 751 return FALSE; |
751 } | 752 } |
752 | 753 |
753 /* Move to next instruction. */ | 754 /* Move to next instruction. */ |
754 old_dinst = IncrementInst(old_dinst); | 755 old_dinst = IncrementInst(old_dinst); |
755 new_dinst = IncrementInst(new_dinst); | 756 new_dinst = IncrementInst(new_dinst); |
756 } | 757 } |
757 return TRUE; | 758 return TRUE; |
758 } | 759 } |
OLD | NEW |