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

Side by Side Diff: src/arm64/simulator-arm64.cc

Issue 268353005: ARM64: Fix and improve MacroAssembler::Printf. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Reorganise Simulator::DoPrintf as suggested. Created 6 years, 7 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 | « src/arm64/simulator-arm64.h ('k') | test/cctest/test-assembler-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdlib.h> 5 #include <stdlib.h>
6 #include <cmath> 6 #include <cmath>
7 #include <cstdarg> 7 #include <cstdarg>
8 #include "v8.h" 8 #include "v8.h"
9 9
10 #if V8_TARGET_ARCH_ARM64 10 #if V8_TARGET_ARCH_ARM64
(...skipping 3563 matching lines...) Expand 10 before | Expand all | Expand 10 after
3574 ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable); 3574 ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable);
3575 // - Skip past the unreachable marker. 3575 // - Skip past the unreachable marker.
3576 set_pc(pc_->following()); 3576 set_pc(pc_->following());
3577 3577
3578 // Check if the debugger should break. 3578 // Check if the debugger should break.
3579 if (parameters & BREAK) Debug(); 3579 if (parameters & BREAK) Debug();
3580 3580
3581 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) { 3581 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
3582 DoRuntimeCall(instr); 3582 DoRuntimeCall(instr);
3583 } else if (instr->ImmException() == kImmExceptionIsPrintf) { 3583 } else if (instr->ImmException() == kImmExceptionIsPrintf) {
3584 // Read the argument encoded inline in the instruction stream. 3584 DoPrintf(instr);
3585 uint32_t type;
3586 memcpy(&type,
3587 pc_->InstructionAtOffset(kPrintfTypeOffset),
3588 sizeof(type));
3589
3590 const char* format = reg<const char*>(0);
3591
3592 // Pass all of the relevant PCS registers onto printf. It doesn't
3593 // matter if we pass too many as the extra ones won't be read.
3594 int result;
3595 fputs(clr_printf, stream_);
3596 if (type == CPURegister::kRegister) {
3597 result = fprintf(stream_, format,
3598 xreg(1), xreg(2), xreg(3), xreg(4),
3599 xreg(5), xreg(6), xreg(7));
3600 } else if (type == CPURegister::kFPRegister) {
3601 result = fprintf(stream_, format,
3602 dreg(0), dreg(1), dreg(2), dreg(3),
3603 dreg(4), dreg(5), dreg(6), dreg(7));
3604 } else {
3605 ASSERT(type == CPURegister::kNoRegister);
3606 result = fprintf(stream_, "%s", format);
3607 }
3608 fputs(clr_normal, stream_);
3609
3610 #ifdef DEBUG
3611 CorruptAllCallerSavedCPURegisters();
3612 #endif
3613
3614 set_xreg(0, result);
3615
3616 // The printf parameters are inlined in the code, so skip them.
3617 set_pc(pc_->InstructionAtOffset(kPrintfLength));
3618
3619 // Set LR as if we'd just called a native printf function.
3620 set_lr(pc());
3621 3585
3622 } else if (instr->ImmException() == kImmExceptionIsUnreachable) { 3586 } else if (instr->ImmException() == kImmExceptionIsUnreachable) {
3623 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n", 3587 fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n",
3624 reinterpret_cast<void*>(pc_)); 3588 reinterpret_cast<void*>(pc_));
3625 abort(); 3589 abort();
3626 3590
3627 } else { 3591 } else {
3628 OS::DebugBreak(); 3592 OS::DebugBreak();
3629 } 3593 }
3630 break; 3594 break;
3631 } 3595 }
3632 3596
3633 default: 3597 default:
3634 UNIMPLEMENTED(); 3598 UNIMPLEMENTED();
3635 } 3599 }
3636 } 3600 }
3637 3601
3602
3603 void Simulator::DoPrintf(Instruction* instr) {
3604 ASSERT((instr->Mask(ExceptionMask) == HLT) &&
3605 (instr->ImmException() == kImmExceptionIsPrintf));
3606
3607 // Read the arguments encoded inline in the instruction stream.
3608 uint32_t arg_count;
3609 uint32_t arg_pattern_list;
3610 STATIC_ASSERT(sizeof(*instr) == 1);
3611 memcpy(&arg_count,
3612 instr + kPrintfArgCountOffset,
3613 sizeof(arg_count));
3614 memcpy(&arg_pattern_list,
3615 instr + kPrintfArgPatternListOffset,
3616 sizeof(arg_pattern_list));
3617
3618 ASSERT(arg_count <= kPrintfMaxArgCount);
3619 ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
3620
3621 // We need to call the host printf function with a set of arguments defined by
3622 // arg_pattern_list. Because we don't know the types and sizes of the
3623 // arguments, this is very difficult to do in a robust and portable way. To
3624 // work around the problem, we pick apart the format string, and print one
3625 // format placeholder at a time.
3626
3627 // Allocate space for the format string. We take a copy, so we can modify it.
3628 // Leave enough space for one extra character per expected argument (plus the
3629 // '\0' termination).
3630 const char * format_base = reg<const char *>(0);
3631 ASSERT(format_base != NULL);
3632 size_t length = strlen(format_base) + 1;
3633 char * const format = new char[length + arg_count];
3634
3635 // A list of chunks, each with exactly one format placeholder.
3636 const char * chunks[kPrintfMaxArgCount];
3637
3638 // Copy the format string and search for format placeholders.
3639 uint32_t placeholder_count = 0;
3640 char * format_scratch = format;
3641 for (size_t i = 0; i < length; i++) {
3642 if (format_base[i] != '%') {
3643 *format_scratch++ = format_base[i];
3644 } else {
3645 if (format_base[i + 1] == '%') {
3646 // Ignore explicit "%%" sequences.
3647 *format_scratch++ = format_base[i];
3648
3649 if (placeholder_count == 0) {
3650 // The first chunk is passed to printf using "%s", so we need to
3651 // unescape "%%" sequences in this chunk. (Just skip the next '%'.)
3652 i++;
3653 } else {
3654 // Otherwise, pass through "%%" unchanged.
3655 *format_scratch++ = format_base[++i];
3656 }
3657 } else {
3658 CHECK(placeholder_count < arg_count);
3659 // Insert '\0' before placeholders, and store their locations.
3660 *format_scratch++ = '\0';
3661 chunks[placeholder_count++] = format_scratch;
3662 *format_scratch++ = format_base[i];
3663 }
3664 }
3665 }
3666 ASSERT(format_scratch <= (format + length + arg_count));
3667 CHECK(placeholder_count == arg_count);
3668
3669 // Finally, call printf with each chunk, passing the appropriate register
3670 // argument. Normally, printf returns the number of bytes transmitted, so we
3671 // can emulate a single printf call by adding the result from each chunk. If
3672 // any call returns a negative (error) value, though, just return that value.
3673
3674 fprintf(stream_, "%s", clr_printf);
3675
3676 // Because '\0' is inserted before each placeholder, the first string in
3677 // 'format' contains no format placeholders and should be printed literally.
3678 int result = fprintf(stream_, "%s", format);
3679 int pcs_r = 1; // Start at x1. x0 holds the format string.
3680 int pcs_f = 0; // Start at d0.
3681 if (result >= 0) {
3682 for (uint32_t i = 0; i < placeholder_count; i++) {
3683 int part_result = -1;
3684
3685 uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
3686 arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
3687 switch (arg_pattern) {
3688 case kPrintfArgW:
3689 part_result = fprintf(stream_, chunks[i], wreg(pcs_r++));
3690 break;
3691 case kPrintfArgX:
3692 part_result = fprintf(stream_, chunks[i], xreg(pcs_r++));
3693 break;
3694 case kPrintfArgD:
3695 part_result = fprintf(stream_, chunks[i], dreg(pcs_f++));
3696 break;
3697 default: UNREACHABLE();
3698 }
3699
3700 if (part_result < 0) {
3701 // Handle error values.
3702 result = part_result;
3703 break;
3704 }
3705
3706 result += part_result;
3707 }
3708 }
3709
3710 fprintf(stream_, "%s", clr_normal);
3711
3712 #ifdef DEBUG
3713 CorruptAllCallerSavedCPURegisters();
3714 #endif
3715
3716 // Printf returns its result in x0 (just like the C library's printf).
3717 set_xreg(0, result);
3718
3719 // The printf parameters are inlined in the code, so skip them.
3720 set_pc(instr->InstructionAtOffset(kPrintfLength));
3721
3722 // Set LR as if we'd just called a native printf function.
3723 set_lr(pc());
3724
3725 delete[] format;
3726 }
3727
3728
3638 #endif // USE_SIMULATOR 3729 #endif // USE_SIMULATOR
3639 3730
3640 } } // namespace v8::internal 3731 } } // namespace v8::internal
3641 3732
3642 #endif // V8_TARGET_ARCH_ARM64 3733 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm64/simulator-arm64.h ('k') | test/cctest/test-assembler-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698