1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 5f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <stdlib.h> 6f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <cmath> 7f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#include <cstdarg> 8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 9f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#if V8_TARGET_ARCH_ARM64 11f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/decoder-arm64-inl.h" 13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/simulator-arm64.h" 144b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/assembler.h" 154b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/disasm.h" 16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/macro-assembler.h" 177d299ad4dc0ca26e0017b190b48362ad71328ce4machenbach@chromium.org#include "src/ostreams.h" 18f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 19f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 { 20f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal { 21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#if defined(USE_SIMULATOR) 23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// This macro provides a platform independent use of sscanf. The reason for 26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// SScanF not being implemented in a platform independent way through 27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// ::v8::internal::OS in the same way as SNPrintF is that the 28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Windows C Run-Time Library does not provide vsscanf. 29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define SScanF sscanf // NOLINT 30f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 31f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Helpers for colors. 332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define COLOUR(colour_code) "\033[0;" colour_code "m" 342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m" 352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define NORMAL "" 362c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define GREY "30" 372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define RED "31" 382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define GREEN "32" 392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define YELLOW "33" 402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define BLUE "34" 412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define MAGENTA "35" 422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define CYAN "36" 432c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org#define WHITE "37" 447010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef char const * const TEXT_COLOUR; 457010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : ""; 462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) : ""; 472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : ""; 482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : ""; 492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : ""; 502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : ""; 512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : ""; 522c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : ""; 532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : ""; 542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : ""; 557010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : ""; 567010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 577010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 58f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// This is basically the same as PrintF, with a guard for FLAG_trace_sim. 599e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.orgvoid Simulator::TraceSim(const char* format, ...) { 60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim) { 61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org va_list arguments; 62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org va_start(arguments, format); 635de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org base::OS::VFPrint(stream_, format, arguments); 64f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org va_end(arguments); 65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst Instruction* Simulator::kEndOfSimAddress = NULL; 70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) { 73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int width = msb - lsb + 1; 74e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_uintn(bits, width) || is_intn(bits, width)); 75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bits <<= lsb; 77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t mask = ((1 << width) - 1) << lsb; 78e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((mask & write_ignore_mask_) == 0); 79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value_ = (value_ & ~mask) | (bits & mask); 81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) { 85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (id) { 86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NZCV: 87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask); 88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPCR: 89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask); 90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SimSystemRegister(); 93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Initialize(Isolate* isolate) { 98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (isolate->simulator_initialized()) return; 99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate->set_simulator_initialized(true); 100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::set_redirector(isolate, &RedirectExternalReference); 101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Get the active Simulator for the current thread. 105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator* Simulator::current(Isolate* isolate) { 106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate::PerIsolateThreadData* isolate_data = 107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate->FindOrAllocatePerThreadDataForThisThread(); 108e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate_data != NULL); 109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Simulator* sim = isolate_data->simulator(); 111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (sim == NULL) { 112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) { 113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sim = new Simulator(new Decoder<DispatchingDecoderVisitor>(), isolate); 114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sim = new Decoder<Simulator>(); 116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sim->isolate_ = isolate; 117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate_data->set_simulator(sim); 119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sim; 121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CallVoid(byte* entry, CallArgument* args) { 125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int index_x = 0; 126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int index_d = 0; 127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org std::vector<int64_t> stack_args(0); 129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; !args[i].IsEnd(); i++) { 130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument arg = args[i]; 131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (arg.IsX() && (index_x < 8)) { 132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(index_x++, arg.bits()); 133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (arg.IsD() && (index_d < 8)) { 134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg_bits(index_d++, arg.bits()); 135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 136e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(arg.IsD() || arg.IsX()); 137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_args.push_back(arg.bits()); 138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Process stack arguments, and make sure the stack is suitably aligned. 142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t original_stack = sp(); 143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t entry_stack = original_stack - 144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_args.size() * sizeof(stack_args[0]); 1455de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org if (base::OS::ActivationFrameAlignment() != 0) { 1465de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org entry_stack &= -base::OS::ActivationFrameAlignment(); 147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char * stack = reinterpret_cast<char*>(entry_stack); 149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org std::vector<int64_t>::const_iterator it; 150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (it = stack_args.begin(); it != stack_args.end(); it++) { 151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org memcpy(stack, &(*it), sizeof(*it)); 152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack += sizeof(*it); 153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 155e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(reinterpret_cast<uintptr_t>(stack) <= original_stack); 156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(entry_stack); 157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the generated code. 159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(entry); 160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_lr(kEndOfSimAddress); 161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CheckPCSComplianceAndRun(); 162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(original_stack); 164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::CallInt64(byte* entry, CallArgument* args) { 168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallVoid(entry, args); 169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return xreg(0); 170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::CallDouble(byte* entry, CallArgument* args) { 174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallVoid(entry, args); 175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return dreg(0); 176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::CallJS(byte* entry, 180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org byte* function_entry, 181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org JSFunction* func, 182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Object* revc, 183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t argc, 184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Object*** argv) { 185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument args[] = { 186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(function_entry), 187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(func), 188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(revc), 189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(argc), 190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(argv), 191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument::End() 192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return CallInt64(entry, args); 194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::CallRegExp(byte* entry, 197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org String* input, 198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t start_offset, 199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const byte* input_start, 200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const byte* input_end, 201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int* output, 202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t output_size, 203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Address stack_base, 204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t direct_call, 205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org void* return_address, 206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate) { 207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument args[] = { 208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(input), 209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(start_offset), 210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(input_start), 211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(input_end), 212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(output), 213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(output_size), 214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(stack_base), 215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(direct_call), 216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(return_address), 217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(isolate), 218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument::End() 219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return CallInt64(entry, args); 221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckPCSComplianceAndRun() { 225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count()); 227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count()); 228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t saved_registers[kNumberOfCalleeSavedRegisters]; 230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters]; 231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList register_list = kCalleeSaved; 233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList fpregister_list = kCalleeSavedFP; 234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) { 236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x31 is not a caller saved register, so no need to specify if we want 237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the stack or zero. 238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org saved_registers[i] = xreg(register_list.PopLowestIndex().code()); 239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) { 241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org saved_fpregisters[i] = 242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dreg_bits(fpregister_list.PopLowestIndex().code()); 243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t original_stack = sp(); 245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Start the simulation! 247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Run(); 248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(original_stack, sp()); 250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check that callee-saved registers have been preserved. 251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list = kCalleeSaved; 252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpregister_list = kCalleeSavedFP; 253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) { 254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code())); 255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) { 257e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(saved_fpregisters[i] == 258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dreg_bits(fpregister_list.PopLowestIndex().code())); 259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Corrupt caller saved register minus the return regiters. 262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1 264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // for now . 265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list = kCallerSaved; 266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list.Remove(x0); 267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list.Remove(x1); 268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // In theory d0 to d7 can be used for return values, but V8 only uses d0 270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // for now . 271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpregister_list = kCallerSavedFP; 272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpregister_list.Remove(d0); 273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue); 275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue); 276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The least significant byte of the curruption value holds the corresponding 282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// register's code. 283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CorruptRegisters(CPURegList* list, uint64_t value) { 284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (list->type() == CPURegister::kRegister) { 285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (!list->IsEmpty()) { 286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned code = list->PopLowestIndex().code(); 287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(code, value | code); 288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 290e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(list->type() == CPURegister::kFPRegister); 291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (!list->IsEmpty()) { 292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned code = list->PopLowestIndex().code(); 293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg_bits(code, value | code); 294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CorruptAllCallerSavedCPURegisters() { 300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Corrupt alters its parameter so copy them first. 301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList register_list = kCallerSaved; 302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList fpregister_list = kCallerSavedFP; 303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue); 305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue); 306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Extending the stack by 2 * 64 bits is required for stack alignment purposes. 311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguintptr_t Simulator::PushAddress(uintptr_t address) { 312e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(sizeof(uintptr_t) < 2 * kXRegSize); 31397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org intptr_t new_sp = sp() - 2 * kXRegSize; 3149801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org uintptr_t* alignment_slot = 3159801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org reinterpret_cast<uintptr_t*>(new_sp + kXRegSize); 3169801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org memcpy(alignment_slot, &kSlotsZapValue, kPointerSize); 317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 3189801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org memcpy(stack_slot, &address, kPointerSize); 319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(new_sp); 320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return new_sp; 321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguintptr_t Simulator::PopAddress() { 325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org intptr_t current_sp = sp(); 326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t address = *stack_slot; 328e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(sizeof(uintptr_t) < 2 * kXRegSize); 32997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_sp(current_sp + 2 * kXRegSize); 330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return address; 331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Returns the limit of the stack area to enable checking for stack overflows. 335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguintptr_t Simulator::StackLimit() const { 336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Leave a safety margin of 1024 bytes to prevent overrunning the stack when 337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // pushing values. 3382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org return stack_limit_ + 1024; 339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder, 343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate, FILE* stream) 344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : decoder_(decoder), 345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_debugger_input_(NULL), 346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org log_parameters_(NO_PARAM), 347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate_(isolate) { 348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Setup the decoder. 349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org decoder_->AppendVisitor(this); 350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Init(stream); 352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim) { 354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org decoder_->InsertVisitorBefore(print_disasm_, this); 355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org log_parameters_ = LOG_ALL; 356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_log_instruction_stats) { 359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org instrument_ = new Instrument(FLAG_log_instruction_file, 360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FLAG_log_instruction_period); 361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org decoder_->AppendVisitor(instrument_); 362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator::Simulator() 367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : decoder_(NULL), 368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_debugger_input_(NULL), 369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org log_parameters_(NO_PARAM), 370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate_(NULL) { 3718f8fe81d7a9cced7a0d30e56124c0428d1a6d229machenbach@chromium.org Init(stdout); 372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats); 373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Init(FILE* stream) { 377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ResetState(); 378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Allocate and setup the simulator stack. 380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_); 3812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org stack_ = reinterpret_cast<uintptr_t>(new byte[stack_size_]); 382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_limit_ = stack_ + stack_protection_size_; 3832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t tos = stack_ + stack_size_ - stack_protection_size_; 3842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The stack pointer must be 16-byte aligned. 3852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_sp(tos & ~0xfUL); 386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stream_ = stream; 388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org print_disasm_ = new PrintDisassembler(stream_); 389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The debugger needs to disassemble code without the simulator executing an 391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // instruction, so we create a dedicated decoder. 392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>(); 393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org disassembler_decoder_->AppendVisitor(print_disasm_); 394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::ResetState() { 398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reset the system registers. 399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv_ = SimSystemRegister::DefaultValueFor(NZCV); 400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpcr_ = SimSystemRegister::DefaultValueFor(FPCR); 401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reset registers to 0. 403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_ = NULL; 404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfRegisters; i++) { 405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(i, 0xbadbeef); 406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP. 409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg_bits(i, 0x7ff000007f800001UL); 410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Returning to address 0 exits the Simulator. 412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_lr(kEndOfSimAddress); 413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reset debug helpers. 415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.empty(); 416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break_on_next_= false; 417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator::~Simulator() { 4212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org delete[] reinterpret_cast<byte*>(stack_); 422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_log_instruction_stats) { 423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete instrument_; 424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete disassembler_decoder_; 426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete print_disasm_; 427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org DeleteArray(last_debugger_input_); 428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete decoder_; 429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Run() { 433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_modified_ = false; 434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (pc_ != kEndOfSimAddress) { 435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExecuteInstruction(); 436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::RunFrom(Instruction* start) { 441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(start); 442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Run(); 443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// When the generated code calls an external reference we need to catch that in 447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// the simulator. The external reference will be a function compiled for the 448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// host architecture. We need to call that function instead of trying to 449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// execute it with the simulator. We do that by redirecting the external 450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// reference to a svc (Supervisor Call) instruction that is handled by 451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// the simulator. We write the original destination of the jump just at a known 452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// offset from the svc instruction so the simulator knows what to call. 453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass Redirection { 454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public: 455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection(void* external_function, ExternalReference::Type type) 456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : external_function_(external_function), 457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org type_(type), 458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org next_(NULL) { 459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org redirect_call_.SetInstructionBits( 460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall)); 461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate = Isolate::Current(); 462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org next_ = isolate->simulator_redirection(); 463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(all): Simulator flush I cache 464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate->set_simulator_redirection(this); 465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org void* address_of_redirect_call() { 468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<void*>(&redirect_call_); 469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 4717010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org template <typename T> 4727010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org T external_function() { return reinterpret_cast<T>(external_function_); } 4737010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type() { return type_; } 475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static Redirection* Get(void* external_function, 477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type) { 478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate = Isolate::Current(); 479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* current = isolate->simulator_redirection(); 480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (; current != NULL; current = current->next_) { 481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (current->external_function_ == external_function) { 482e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK_EQ(current->type(), type); 483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return current; 484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return new Redirection(external_function, type); 487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static Redirection* FromHltInstruction(Instruction* redirect_call) { 490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* addr_of_hlt = reinterpret_cast<char*>(redirect_call); 491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* addr_of_redirection = 492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org addr_of_hlt - OFFSET_OF(Redirection, redirect_call_); 493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<Redirection*>(addr_of_redirection); 494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static void* ReverseRedirection(int64_t reg) { 497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* redirection = 498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FromHltInstruction(reinterpret_cast<Instruction*>(reg)); 4997010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org return redirection->external_function<void*>(); 500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private: 503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org void* external_function_; 504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instruction redirect_call_; 505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type_; 506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* next_; 507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}; 508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 5107010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Calls into the V8 runtime are based on this very simple interface. 5117010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Note: To be able to return two values from some calls the code in runtime.cc 5127010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// uses the ObjectPair structure. 5137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// The simulator assumes all runtime calls return two 64-bits values. If they 5147010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// don't, register x1 is clobbered. This is fine because x1 is caller-saved. 5157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgstruct ObjectPair { 5167010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t res0; 5177010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t res1; 5187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org}; 5197010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, 5227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg1, 5237010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg2, 5247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg3, 5257010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg4, 5267010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg5, 5277010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg6, 5287010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg7); 5297010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5307010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2); 5317010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2); 5327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPCall)(double arg1); 5337010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2); 5347010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5357010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// This signature supports direct call in to API function native callback 5367010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// (refer to InvocationCallback in v8.h). 5377010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); 5387010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); 5397010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5407010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// This signature supports direct call to accessor getter callback. 5417010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); 5427010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1, 5437010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org void* arg2); 5447010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5457010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgvoid Simulator::DoRuntimeCall(Instruction* instr) { 5467010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org Redirection* redirection = Redirection::FromHltInstruction(instr); 5477010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5487010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // The called C code might itself call simulated code, so any 5497010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // caller-saved registers (including lr) could still be clobbered by a 5507010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // redirected call. 5517010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org Instruction* return_address = lr(); 5527010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5537010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t external = redirection->external_function<int64_t>(); 5547010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5557010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Call to host function at %p\n", 5567010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org redirection->external_function<void*>()); 5577010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5587010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // SP must be 16-byte-aligned at the call interface. 5597010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org bool stack_alignment_exception = ((sp() & 0xf) != 0); 5607010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org if (stack_alignment_exception) { 5617010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp()); 5627010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org FATAL("ALIGNMENT EXCEPTION"); 5637010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 5647010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5657010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org switch (redirection->type()) { 5667010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org default: 5677010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: Unknown.\n"); 5687010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org UNREACHABLE(); 5697010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 5707010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5717010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_CALL: { 572a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org // Object* f(v8::internal::Arguments). 5737010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_CALL\n"); 5747010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeCall target = 5757010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCall>(external); 5767010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5777010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // We don't know how many arguments are being passed, but we can 5787010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // pass 8 without touching the stack. They will be ignored by the 5797010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // host function if they aren't used. 5807010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: " 5817010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org "0x%016" PRIx64 ", 0x%016" PRIx64 ", " 5827010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org "0x%016" PRIx64 ", 0x%016" PRIx64 ", " 5837010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org "0x%016" PRIx64 ", 0x%016" PRIx64 ", " 5847010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org "0x%016" PRIx64 ", 0x%016" PRIx64, 5857010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(0), xreg(1), xreg(2), xreg(3), 5867010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(4), xreg(5), xreg(6), xreg(7)); 5877010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3), 5887010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(4), xreg(5), xreg(6), xreg(7)); 5897010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n", 5907010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org result.res0, result.res1); 5917010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 5927010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 5937010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 5947010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_xreg(0, result.res0); 5957010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_xreg(1, result.res1); 5967010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 5977010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 5987010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5997010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::DIRECT_API_CALL: { 6007010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(v8::FunctionCallbackInfo&) 6017010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: DIRECT_API_CALL\n"); 6027010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeDirectApiCall target = 6037010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 6047010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0)); 6057010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0)); 6067010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 6077010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6087010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6097010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6107010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6117010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6127010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_COMPARE_CALL: { 6147010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // int f(double, double) 6157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_COMPARE_CALL\n"); 6167010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeCompareCall target = 6177010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCompareCall>(external); 6187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); 6197010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t result = target(dreg(0), dreg(1)); 6207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %" PRId64 "\n", result); 6217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6237010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_xreg(0, result); 6257010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6267010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6277010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6287010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_FP_CALL: { 6297010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // double f(double) 6307010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_FP_CALL\n"); 6317010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeFPCall target = 6327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPCall>(external); 6337010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Argument: %f\n", dreg(0)); 6347010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org double result = target(dreg(0)); 6357010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %f\n", result); 6367010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6377010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6387010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6397010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_dreg(0, result); 6407010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6417010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6427010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6437010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_FP_FP_CALL: { 6447010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // double f(double, double) 6457010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_FP_FP_CALL\n"); 6467010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeFPFPCall target = 6477010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 6487010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); 6497010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org double result = target(dreg(0), dreg(1)); 6507010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %f\n", result); 6517010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6527010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6537010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6547010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_dreg(0, result); 6557010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6567010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6577010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6587010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_FP_INT_CALL: { 6597010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // double f(double, int) 6607010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_FP_INT_CALL\n"); 6617010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeFPIntCall target = 6627010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 6637010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0)); 6647010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org double result = target(dreg(0), wreg(0)); 6657010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %f\n", result); 6667010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6677010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6687010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6697010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_dreg(0, result); 6707010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6717010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6727010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6737010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::DIRECT_GETTER_CALL: { 6747010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(Local<String> property, PropertyCallbackInfo& info) 6757010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: DIRECT_GETTER_CALL\n"); 6767010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeDirectGetterCall target = 6777010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 6787010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n", 6797010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(0), xreg(1)); 6807010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0), xreg(1)); 6817010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 6827010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6837010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6847010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6857010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6867010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6877010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6887010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::PROFILING_API_CALL: { 6897010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback) 6907010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: PROFILING_API_CALL\n"); 6917010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeProfilingApiCall target = 6927010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 6937010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org void* arg1 = Redirection::ReverseRedirection(xreg(1)); 6947010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1); 6957010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0), arg1); 6967010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 6977010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6987010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6997010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 7007010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 7017010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 7027010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 7037010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::PROFILING_GETTER_CALL: { 7047010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(Local<String> property, PropertyCallbackInfo& info, 705e2a8937454723a720c81acc3f9e4162b18999b43machenbach@chromium.org // AccessorNameGetterCallback callback) 7067010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: PROFILING_GETTER_CALL\n"); 7077010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeProfilingGetterCall target = 7087010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeProfilingGetterCall>( 7097010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org external); 7107010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org void* arg2 = Redirection::ReverseRedirection(xreg(2)); 7117010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n", 7127010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(0), xreg(1), arg2); 7137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0), xreg(1), arg2); 7147010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 7157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 7167010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 7177010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 7187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 7197010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 7207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 7217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 7227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_lr(return_address); 7237010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_pc(return_address); 7247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org} 7257010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 7267010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid* Simulator::RedirectExternalReference(void* external_function, 728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type) { 729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* redirection = Redirection::Get(external_function, type); 730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return redirection->address_of_redirect_call(); 731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::xreg_names[] = { 7352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 7362c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 7372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23", 7382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"}; 739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::wreg_names[] = { 7412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", 7422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", 7432c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", 744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"}; 745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::sreg_names[] = { 747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", 749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", 750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"}; 751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::dreg_names[] = { 753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", 755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", 756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"}; 757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::vreg_names[] = { 759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; 763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) { 7662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org STATIC_ASSERT(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1)); 767e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code < kNumberOfRegisters); 7682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The modulo operator has no effect here, but it silences a broken GCC 7692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // warning about out-of-bounds array accesses. 7702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org code %= kNumberOfRegisters; 7712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the code represents the stack pointer, index the name after zr. 773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { 774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code = kZeroRegCode + 1; 775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 776e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org return wreg_names[code]; 777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { 7812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1)); 782e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code < kNumberOfRegisters); 7832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org code %= kNumberOfRegisters; 7842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the code represents the stack pointer, index the name after zr. 786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { 787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code = kZeroRegCode + 1; 788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 789e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org return xreg_names[code]; 790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::SRegNameForCode(unsigned code) { 7942c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters); 795e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code < kNumberOfFPRegisters); 7962c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org return sreg_names[code % kNumberOfFPRegisters]; 797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::DRegNameForCode(unsigned code) { 8012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters); 802e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code < kNumberOfFPRegisters); 8032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org return dreg_names[code % kNumberOfFPRegisters]; 804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::VRegNameForCode(unsigned code) { 8082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters); 809e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(code < kNumberOfFPRegisters); 8102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org return vreg_names[code % kNumberOfFPRegisters]; 811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint Simulator::CodeFromName(const char* name) { 815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfRegisters; i++) { 816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp(xreg_names[i], name) == 0) || 817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(wreg_names[i], name) == 0)) { 818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return i; 819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp(vreg_names[i], name) == 0) || 823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(dreg_names[i], name) == 0) || 824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(sreg_names[i], name) == 0)) { 825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return i; 826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) { 829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kSPRegInternalCode; 830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -1; 832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 833f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 834f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 835f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Helpers --------------------------------------------------------------------- 8361845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 8371845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgT Simulator::AddWithCarry(bool set_flags, 8381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T src1, 8391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T src2, 8401845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T carry_in) { 8411845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 842e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((carry_in == 0) || (carry_in == 1)); 843f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T signed_sum = src1 + src2 + carry_in; 8451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = signed_sum; 846f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8479801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org bool N, Z, C, V; 848f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // Compute the C flag 8501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT u1 = static_cast<unsignedT>(src1); 8511845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT u2 = static_cast<unsignedT>(src2); 8521845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT urest = std::numeric_limits<unsignedT>::max() - u1; 8531845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1)))); 854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // Overflow iff the sign bit is the same for the two inputs and different 8561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // for the result. 8571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); 858f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org N = CalcNFlag(result); 860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Z = CalcZFlag(result); 861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 862f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (set_flags) { 863f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetN(N); 864f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetZ(Z); 865f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetC(C); 866f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetV(V); 8672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(NZCV); 868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 869f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result; 870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 8741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::AddSubWithCarry(Instruction* instr) { 8751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op2 = reg<T>(instr->Rm()); 8761845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T new_val; 8771845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8781845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) { 8791845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2 = ~op2; 8801845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 8811845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org new_val = AddWithCarry<T>(instr->FlagsUpdate(), 8831845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org reg<T>(instr->Rn()), 8841845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2, 8851845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org nzcv().C()); 8861845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8871845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), new_val); 8881845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 8891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8901845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 8911845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgT Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) { 8921845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 8931845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (amount == 0) { 895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return value; 896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 8971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (shift_type) { 899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSL: 9001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return value << amount; 901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSR: 9021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return static_cast<unsignedT>(value) >> amount; 9031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case ASR: 9041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return value >> amount; 9051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case ROR: 9061845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return (static_cast<unsignedT>(value) >> amount) | 9071845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ((value & ((1L << amount) - 1L)) << 9081845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org (sizeof(unsignedT) * 8 - amount)); 909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0; 912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 9161845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 9171845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgT Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) { 9181845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8; 9191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8; 9201845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8; 9211845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 922f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (extend_type) { 923f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTB: 924f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value &= kByteMask; 925f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 926f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTH: 927f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value &= kHalfWordMask; 928f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 929f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTW: 930f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value &= kWordMask; 931f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 932f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTB: 9331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value = (value << kSignExtendBShift) >> kSignExtendBShift; 934f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 935f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTH: 9361845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value = (value << kSignExtendHShift) >> kSignExtendHShift; 937f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 938f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTW: 9391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value = (value << kSignExtendWShift) >> kSignExtendWShift; 940f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 941f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTX: 942f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTX: 943f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 944f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 945f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 946f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 9471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return value << left_shift; 9481845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 9491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 9501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 9511845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 9521845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::Extract(Instruction* instr) { 9531845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned lsb = instr->ImmS(); 9541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op2 = reg<T>(instr->Rm()); 9551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = op2; 9561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 9571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (lsb) { 9581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op1 = reg<T>(instr->Rn()); 9591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb)); 9601845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 9611845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result); 962f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 963f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 964f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 9656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate<> double Simulator::FPDefaultNaN<double>() const { 9666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return kFP64DefaultNaN; 9676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 9686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 9696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 9706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate<> float Simulator::FPDefaultNaN<float>() const { 9716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return kFP32DefaultNaN; 9726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 9736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 9746b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::FPCompare(double val0, double val1) { 976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(jbramley): This assumes that the C++ implementation handles 979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // comparisons in the way that we expect (as per AssertSupportedFPCR()). 980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) { 981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPUnorderedFlag); 982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (val0 < val1) { 983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPLessThanFlag); 984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (val0 > val1) { 985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPGreaterThanFlag); 986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (val0 == val1) { 987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPEqualFlag); 988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 9912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(NZCV); 992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 993f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::SetBreakpoint(Instruction* location) { 996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < breakpoints_.size(); i++) { 997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (breakpoints_.at(i).location == location) { 9989e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 9999e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org "Existing breakpoint at %p was %s\n", 1000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(location), 1001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled ? "disabled" : "enabled"); 1002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled; 1003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return; 1004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Breakpoint new_breakpoint = {location, true}; 1007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.push_back(new_breakpoint); 10089e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 10099e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org "Set a breakpoint at %p\n", reinterpret_cast<void*>(location)); 1010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::ListBreakpoints() { 10149e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "Breakpoints:\n"); 1015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < breakpoints_.size(); i++) { 10169e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%p : %s\n", 1017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(breakpoints_.at(i).location), 1018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled ? "enabled" : "disabled"); 1019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1022f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1023f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckBreakpoints() { 1024f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool hit_a_breakpoint = false; 1025f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < breakpoints_.size(); i++) { 1026f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((breakpoints_.at(i).location == pc_) && 1027f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled) { 1028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org hit_a_breakpoint = true; 1029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Disable this breakpoint. 1030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled = false; 1031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (hit_a_breakpoint) { 10349e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "Hit and disabled a breakpoint at %p.\n", 1035f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(pc_)); 1036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Debug(); 1037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1038f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1039f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1040f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckBreakNext() { 1042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the current instruction is a BL, insert a breakpoint just after it. 1043f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) { 10444452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org SetBreakpoint(pc_->following()); 1045f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break_on_next_ = false; 1046f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1047f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1048f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1049f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1050f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { 1051f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instruction* end = start->InstructionAtOffset(count * kInstructionSize); 10524452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org for (Instruction* pc = start; pc < end; pc = pc->following()) { 1053f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org disassembler_decoder_->Decode(pc); 1054f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1055f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1056f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10582c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintSystemRegisters() { 10592c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org PrintSystemRegister(NZCV); 10602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org PrintSystemRegister(FPCR); 10612c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org} 10622c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 10632c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 10642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintRegisters() { 10652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org for (unsigned i = 0; i < kNumberOfRegisters; i++) { 10662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org PrintRegister(i); 10672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 10682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org} 1069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 10712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintFPRegisters() { 10722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 10732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org PrintFPRegister(i); 1074f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 10752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org} 10762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 1077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) { 10792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Don't print writes into xzr. 10802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) { 10812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org return; 1082f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1083f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The template is "# x<code>:value". 10852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n", 10862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_name, XRegNameForCode(code, r31mode), 10872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal); 1088f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1089f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) { 10922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The template is "# v<code>:bits (d<code>:value, ...)". 1093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 10942c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(sizes != 0); 10952c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK((sizes & kPrintAllFPRegValues) == sizes); 10962c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 10972c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Print the raw bits. 10982c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (", 10992c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, VRegNameForCode(code), 11002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<uint64_t>(code), clr_normal); 11012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11022c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Print all requested value interpretations. 11032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org bool need_separator = false; 11042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (sizes & kPrintDRegValue) { 11052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "%s%s%s: %s%g%s", 11062c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org need_separator ? ", " : "", 11072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, DRegNameForCode(code), 11082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<double>(code), clr_normal); 11092c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org need_separator = true; 11102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 11112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (sizes & kPrintSRegValue) { 11132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "%s%s%s: %s%g%s", 11142c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org need_separator ? ", " : "", 11152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, SRegNameForCode(code), 11162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<float>(code), clr_normal); 11172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org need_separator = true; 11182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 11192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // End the value list. 11212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, ")\n"); 11222c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org} 11232c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11242c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11252c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintSystemRegister(SystemRegister id) { 11262c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org switch (id) { 11272c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case NZCV: 11282c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n", 11292c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_flag_name, clr_flag_value, 11302c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(), 11312c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_normal); 11322c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 11332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case FPCR: { 11342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org static const char * rmode[] = { 11352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "0b00 (Round to Nearest)", 11362c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "0b01 (Round towards Plus Infinity)", 11372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "0b10 (Round towards Minus Infinity)", 11382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "0b11 (Round towards Zero)" 11392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org }; 11402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(fpcr().RMode() < arraysize(rmode)); 1141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, 11422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", 11432c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_flag_name, clr_flag_value, 11442c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()], 1145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 11462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 1147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 11482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org default: 11492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org UNREACHABLE(); 1150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 11542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintRead(uintptr_t address, 11552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org size_t size, 11562c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org unsigned reg_code) { 11572c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org USE(size); // Size is unused here. 115842ed2fc449e83fab2ccbf1b769a5e83715c9d783machenbach@chromium.org 11592c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The template is "# x<code>:value <- address". 11602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", 11612c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_name, XRegNameForCode(reg_code), 11622c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_value, reg<uint64_t>(reg_code), clr_normal); 11632c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", 11652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_memory_address, address, clr_normal); 11662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org} 11672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintReadFP(uintptr_t address, 11702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org size_t size, 11712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org unsigned reg_code) { 11722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The template is "# reg:bits (reg:value) <- address". 11732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org switch (size) { 11742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kSRegSize: 11752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)", 11762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, VRegNameForCode(reg_code), 11772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, 11782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, SRegNameForCode(reg_code), 11792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<float>(reg_code), clr_normal); 11802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 11812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kDRegSize: 11822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", 11832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, VRegNameForCode(reg_code), 11842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, 11852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, DRegNameForCode(reg_code), 11862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<double>(reg_code), clr_normal); 11872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 11882c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org default: 11892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org UNREACHABLE(); 1190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 11912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 11922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", 11932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_memory_address, address, clr_normal); 1194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 11972c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintWrite(uintptr_t address, 11982c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org size_t size, 11992c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org unsigned reg_code) { 12002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The template is "# reg:value -> address". To keep the trace tidy and 12012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // readable, the value is aligned with the values in the register trace. 12022c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org switch (size) { 12032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kByteSizeInBytes: 12042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s", 12052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_name, WRegNameForCode(reg_code), 12062c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_value, reg<uint8_t>(reg_code), clr_normal); 12072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 12082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kHalfWordSizeInBytes: 12092c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s", 12102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_name, WRegNameForCode(reg_code), 12112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_value, reg<uint16_t>(reg_code), clr_normal); 12122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 12132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kWRegSize: 12142c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s", 12152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_name, WRegNameForCode(reg_code), 12162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_value, reg<uint32_t>(reg_code), clr_normal); 12172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 12182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kXRegSize: 12192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", 12202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_name, XRegNameForCode(reg_code), 12212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_reg_value, reg<uint64_t>(reg_code), clr_normal); 12222c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 12232c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org default: 12242c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org UNREACHABLE(); 12252c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 12262c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 12272c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", 12282c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_memory_address, address, clr_normal); 1229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 12322c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::PrintWriteFP(uintptr_t address, 12332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org size_t size, 12342c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org unsigned reg_code) { 12352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy 12362c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // and readable, the value is aligned with the values in the register trace. 12372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org switch (size) { 12382c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kSRegSize: 12392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)", 12402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, VRegNameForCode(reg_code), 12412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal, 12422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, SRegNameForCode(reg_code), 12432c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<float>(reg_code), clr_normal); 12442c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 12452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case kDRegSize: 12462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", 12472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, VRegNameForCode(reg_code), 12482c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal, 12492c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_name, DRegNameForCode(reg_code), 12502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_fpreg_value, fpreg<double>(reg_code), clr_normal); 12512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 12522c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org default: 12532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org UNREACHABLE(); 12542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 12552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 12562c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", 12572c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org clr_memory_address, address, clr_normal); 1258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Visitors--------------------------------------------------------------------- 1262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnimplemented(Instruction* instr) { 1264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", 1265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(instr), instr->InstructionBits()); 1266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnallocated(Instruction* instr) { 1271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n", 1272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(instr), instr->InstructionBits()); 1273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitPCRelAddressing(Instruction* instr) { 1278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(PCRelAddressingMask)) { 1279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADR: 1280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_reg(instr->Rd(), instr->ImmPCOffsetTarget()); 1281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADRP: // Not implemented in the assembler. 1283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 1287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnconditionalBranch(Instruction* instr) { 1293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(UnconditionalBranchMask)) { 1294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BL: 12954452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org set_lr(instr->following()); 1296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Fall through. 1297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case B: 1298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 1302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalBranch(Instruction* instr) { 1307e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(instr->Mask(ConditionalBranchMask) == B_cond); 1308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) { 1309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) { 1315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instruction* target = reg<Instruction*>(instr->Rn()); 1316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(UnconditionalBranchToRegisterMask)) { 1317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BLR: { 13184452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org set_lr(instr->following()); 1319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->Rn() == 31) { 1320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // BLR XZR is used as a guard for the constant pool. We should never hit 1321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // this, but if we do trap to allow debugging. 1322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Debug(); 1323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Fall through. 1325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BR: 1327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case RET: set_pc(target); break; 1328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitTestBranch(Instruction* instr) { 1334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) | 1335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org instr->ImmTestBranchBit40(); 1336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0); 1337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(TestBranchMask)) { 1338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TBZ: break; 1339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TBNZ: take_branch = !take_branch; break; 1340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (take_branch) { 1343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitCompareBranch(Instruction* instr) { 1349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt = instr->Rt(); 1350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool take_branch = false; 1351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(CompareBranchMask)) { 1352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBZ_w: take_branch = (wreg(rt) == 0); break; 1353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBZ_x: take_branch = (xreg(rt) == 0); break; 1354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBNZ_w: take_branch = (wreg(rt) != 0); break; 1355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBNZ_x: take_branch = (xreg(rt) != 0); break; 1356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (take_branch) { 1359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 13641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 13651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::AddSubHelper(Instruction* instr, T op2) { 1366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool set_flags = instr->FlagsUpdate(); 13671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T new_val = 0; 1368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instr operation = instr->Mask(AddSubOpMask); 1369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (operation) { 1371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADD: 1372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADDS: { 13731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org new_val = AddWithCarry<T>(set_flags, 13741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org reg<T>(instr->Rn(), instr->RnMode()), 13751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2); 1376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SUB: 1379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SUBS: { 13801845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org new_val = AddWithCarry<T>(set_flags, 13811845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org reg<T>(instr->Rn(), instr->RnMode()), 13821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ~op2, 13831845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 1); 1384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 1387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 13891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), new_val, instr->RdMode()); 1390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubShifted(Instruction* instr) { 13941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Shift shift_type = static_cast<Shift>(instr->ShiftDP()); 13951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned shift_amount = instr->ImmDPShift(); 13961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 13971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); 13991845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 14001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14011845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); 14021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 14031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubImmediate(Instruction* instr) { 1408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0); 14091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper<int64_t>(instr, op2); 14111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper<int32_t>(instr, op2); 14131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubExtended(Instruction* instr) { 14181845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Extend ext = static_cast<Extend>(instr->ExtendMode()); 14191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned left_shift = instr->ImmExtendShift(); 14201845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14211845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift); 14221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 14231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift); 14251845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 14261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubWithCarry(Instruction* instr) { 14311845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14321845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubWithCarry<int64_t>(instr); 14331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubWithCarry<int32_t>(instr); 1435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLogicalShifted(Instruction* instr) { 1440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Shift shift_type = static_cast<Shift>(instr->ShiftDP()); 1441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned shift_amount = instr->ImmDPShift(); 14421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 14431845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); 14451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; 14461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int64_t>(instr, op2); 14471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14481845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); 14491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; 14501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int32_t>(instr, op2); 1451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLogicalImmediate(Instruction* instr) { 14561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int64_t>(instr, instr->ImmLogical()); 14581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int32_t>(instr, instr->ImmLogical()); 14601845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 14641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 14651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::LogicalHelper(Instruction* instr, T op2) { 14661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op1 = reg<T>(instr->Rn()); 14671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = 0; 1468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool update_flags = false; 1469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Switch on the logical operation, stripping out the NOT bit, as it has a 1471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // different meaning for logical immediate instructions. 1472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(LogicalOpMask & ~NOT)) { 1473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ANDS: update_flags = true; // Fall through. 1474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case AND: result = op1 & op2; break; 1475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ORR: result = op1 | op2; break; 1476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case EOR: result = op1 ^ op2; break; 1477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (update_flags) { 14821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org nzcv().SetN(CalcNFlag(result)); 1483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetZ(CalcZFlag(result)); 1484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetC(0); 1485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetV(0); 14862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(NZCV); 1487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 14891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result, instr->RdMode()); 1490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalCompareRegister(Instruction* instr) { 14941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper(instr, xreg(instr->Rm())); 14961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper(instr, wreg(instr->Rm())); 14981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalCompareImmediate(Instruction* instr) { 15031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 15041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp()); 15051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 15061845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp()); 15071845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 15111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 15121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::ConditionalCompareHelper(Instruction* instr, T op2) { 15131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op1 = reg<T>(instr->Rn()); 1514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 1516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition passes, set the status flags to the result of comparing 1517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the operands. 1518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->Mask(ConditionalCompareMask) == CCMP) { 15191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddWithCarry<T>(true, op1, ~op2, 1); 1520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 1521e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(instr->Mask(ConditionalCompareMask) == CCMN); 15221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddWithCarry<T>(true, op1, op2, 0); 1523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 1525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition fails, set the status flags to the nzcv immediate. 1526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetFlags(instr->Nzcv()); 15272c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(NZCV); 1528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { 1533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int offset = instr->ImmLSUnsigned() << instr->SizeLS(); 1534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, offset, Offset); 1535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) { 1539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, instr->ImmLS(), Offset); 1540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePreIndex(Instruction* instr) { 1544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, instr->ImmLS(), PreIndex); 1545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePostIndex(Instruction* instr) { 1549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, instr->ImmLS(), PostIndex); 1550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) { 1554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Extend ext = static_cast<Extend>(instr->ExtendMode()); 1555e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); 1556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS(); 1557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 15581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); 1559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, offset, Offset); 1560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::LoadStoreHelper(Instruction* instr, 1564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t offset, 1565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned srcdst = instr->Rt(); 1567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned addr_reg = instr->Rn(); 15682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); 15692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t stack = 0; 1570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for stores before the store. On a CPU the writeback 1572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and the store are atomic, but when running on the simulator it is possible 1573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // to be interrupted in between. The simulator is not thread safe and V8 does 1574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not require it to be to run JavaScript therefore the profiler may sample 1575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the "simulated" CPU in the middle of load/store with writeback. The code 1576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // below ensures that push operations are safe even when interrupted: the 1577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack pointer will be decremented before adding an element to the stack. 1578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsStore()) { 1579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For store the address post writeback is used to check access below the 1582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 15832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org stack = sp(); 1584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); 1587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (op) { 15882c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Use _no_log variants to suppress the register trace (LOG_REGS, 15892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // LOG_FP_REGS). We will print a more detailed log. 15902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break; 15912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break; 15922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break; 15932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break; 15942c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; 15952c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; 15962c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; 15972c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; 15982c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break; 15992c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break; 16002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break; 16019aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org 16029aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; 16039aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; 16049aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; 16059aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; 16069aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; 16079aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; 16089aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org 1609f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 16122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Print a detailed trace (including the memory address) instead of the basic 16132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // register:value trace generated by set_*reg(). 16142c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org size_t access_size = 1 << instr->SizeLS(); 16152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (instr->IsLoad()) { 16162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if ((op == LDR_s) || (op == LDR_d)) { 16172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogReadFP(address, access_size, srcdst); 16182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } else { 16192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogRead(address, access_size, srcdst); 16202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 16212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } else { 16222c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if ((op == STR_s) || (op == STR_d)) { 16232c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogWriteFP(address, access_size, srcdst); 16242c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } else { 16252c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogWrite(address, access_size, srcdst); 16262c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 16272c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 16282c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 1629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for loads after the load to ensure safe pop 1630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // operation even when interrupted in the middle of it. The stack pointer 1631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // is only updated after the load so pop(fp) will never break the invariant 1632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sp <= fp expected while walking the stack in the sampler. 1633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsLoad()) { 1634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For loads the address pre writeback is used to check access below the 1635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 16362c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org stack = sp(); 1637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Accesses below the stack pointer (but above the platform stack limit) are 1642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not allowed in the ABI. 1643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CheckMemoryAccess(address, stack); 1644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairOffset(Instruction* instr) { 1648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, Offset); 1649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairPreIndex(Instruction* instr) { 1653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, PreIndex); 1654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairPostIndex(Instruction* instr) { 1658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, PostIndex); 1659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1661f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { 1663f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, Offset); 1664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::LoadStorePairHelper(Instruction* instr, 1668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt = instr->Rt(); 1670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt2 = instr->Rt2(); 1671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned addr_reg = instr->Rn(); 16722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org size_t access_size = 1 << instr->SizeLSPair(); 16732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org int64_t offset = instr->ImmLSPair() * access_size; 16742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); 16752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t address2 = address + access_size; 16762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t stack = 0; 1677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for stores before the store. On a CPU the writeback 1679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and the store are atomic, but when running on the simulator it is possible 1680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // to be interrupted in between. The simulator is not thread safe and V8 does 1681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not require it to be to run JavaScript therefore the profiler may sample 1682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the "simulated" CPU in the middle of load/store with writeback. The code 1683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // below ensures that push operations are safe even when interrupted: the 1684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack pointer will be decremented before adding an element to the stack. 1685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsStore()) { 1686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For store the address post writeback is used to check access below the 1689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 16902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org stack = sp(); 1691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairOp op = 1694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); 1695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 'rt' and 'rt2' can only be aliased for stores. 1697e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); 1698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (op) { 17002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Use _no_log variants to suppress the register trace (LOG_REGS, 17012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // LOG_FP_REGS). We will print a more detailed log. 1702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_w: { 17032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kWRegSize); 17042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); 17052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2)); 1706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_s: { 17092c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kSRegSize); 17102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_sreg_no_log(rt, MemoryRead<float>(address)); 17112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_sreg_no_log(rt2, MemoryRead<float>(address2)); 1712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_x: { 17152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kXRegSize); 17162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); 17172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2)); 1718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_d: { 17212c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kDRegSize); 17222c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_dreg_no_log(rt, MemoryRead<double>(address)); 17232c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_dreg_no_log(rt2, MemoryRead<double>(address2)); 1724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDPSW_x: { 17272c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kWRegSize); 17282c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_xreg_no_log(rt, MemoryRead<int32_t>(address)); 17292c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_xreg_no_log(rt2, MemoryRead<int32_t>(address2)); 1730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_w: { 17332c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kWRegSize); 17349aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MemoryWrite<uint32_t>(address, wreg(rt)); 17352c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org MemoryWrite<uint32_t>(address2, wreg(rt2)); 1736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_s: { 17392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kSRegSize); 17409aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MemoryWrite<float>(address, sreg(rt)); 17412c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org MemoryWrite<float>(address2, sreg(rt2)); 1742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_x: { 17452c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kXRegSize); 17469aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MemoryWrite<uint64_t>(address, xreg(rt)); 17472c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org MemoryWrite<uint64_t>(address2, xreg(rt2)); 1748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_d: { 17512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org DCHECK(access_size == kDRegSize); 17529aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org MemoryWrite<double>(address, dreg(rt)); 17532c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org MemoryWrite<double>(address2, dreg(rt2)); 1754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 1757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 17592c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Print a detailed trace (including the memory address) instead of the basic 17602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // register:value trace generated by set_*reg(). 17612c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (instr->IsLoad()) { 17622c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if ((op == LDP_s) || (op == LDP_d)) { 17632c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogReadFP(address, access_size, rt); 17642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogReadFP(address2, access_size, rt2); 17652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } else { 17662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogRead(address, access_size, rt); 17672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogRead(address2, access_size, rt2); 17682c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 17692c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } else { 17702c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if ((op == STP_s) || (op == STP_d)) { 17712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogWriteFP(address, access_size, rt); 17722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogWriteFP(address2, access_size, rt2); 17732c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } else { 17742c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogWrite(address, access_size, rt); 17752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogWrite(address2, access_size, rt2); 17762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 17772c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org } 17782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org 1779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for loads after the load to ensure safe pop 1780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // operation even when interrupted in the middle of it. The stack pointer 1781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // is only updated after the load so pop(fp) will never break the invariant 1782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sp <= fp expected while walking the stack in the sampler. 1783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsLoad()) { 1784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For loads the address pre writeback is used to check access below the 1785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 17862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org stack = sp(); 1787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Accesses below the stack pointer (but above the platform stack limit) are 1792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not allowed in the ABI. 1793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CheckMemoryAccess(address, stack); 1794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadLiteral(Instruction* instr) { 17982c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uintptr_t address = instr->LiteralAddress(); 1799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt = instr->Rt(); 1800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(LoadLiteralMask)) { 18022c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // Use _no_log variants to suppress the register trace (LOG_REGS, 18032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org // LOG_FP_REGS), then print a more detailed log. 18042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_w_lit: 18052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); 18062c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogRead(address, kWRegSize, rt); 18072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 18082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_x_lit: 18092c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); 18102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogRead(address, kXRegSize, rt); 18112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 18122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_s_lit: 18132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_sreg_no_log(rt, MemoryRead<float>(address)); 18142c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogReadFP(address, kSRegSize, rt); 18152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 18162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case LDR_d_lit: 18172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org set_dreg_no_log(rt, MemoryRead<double>(address)); 18182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogReadFP(address, kDRegSize, rt); 18192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 1820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 1821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 18252c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orguintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset, 18262c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org AddrMode addrmode) { 1827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; 18282c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org uint64_t address = xreg(addr_reg, Reg31IsStackPointer); 1829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) { 1830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // When the base register is SP the stack pointer is required to be 1831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // quadword aligned prior to the address calculation and write-backs. 1832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Misalignment will cause a stack alignment fault. 1833f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FATAL("ALIGNMENT EXCEPTION"); 1834f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1835f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1836f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((addrmode == Offset) || (addrmode == PreIndex)) { 1837f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org address += offset; 1838f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1839f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 18402c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org return address; 1841f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1842f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1843f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1844f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::LoadStoreWriteBack(unsigned addr_reg, 1845f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t offset, 1846f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1847f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((addrmode == PreIndex) || (addrmode == PostIndex)) { 1848e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(offset != 0); 1849f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t address = xreg(addr_reg, Reg31IsStackPointer); 1850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_reg(addr_reg, address + offset, Reg31IsStackPointer); 1851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 18552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgvoid Simulator::CheckMemoryAccess(uintptr_t address, uintptr_t stack) { 1856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((address >= stack_limit_) && (address < stack)) { 1857f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); 185806b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org fprintf(stream_, " sp is here: 0x%016" PRIx64 "\n", 185906b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org static_cast<uint64_t>(stack)); 186006b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org fprintf(stream_, " access was here: 0x%016" PRIx64 "\n", 186106b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org static_cast<uint64_t>(address)); 186206b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org fprintf(stream_, " stack limit is here: 0x%016" PRIx64 "\n", 186306b2696801712948b665372a38f96b1f10be6997machenbach@chromium.org static_cast<uint64_t>(stack_limit_)); 1864f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "\n"); 1865f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FATAL("ACCESS BELOW STACK POINTER"); 1866f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1867f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1869f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitMoveWideImmediate(Instruction* instr) { 1871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MoveWideImmediateOp mov_op = 1872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); 1873f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t new_xn_val = 0; 1874f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1875f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool is_64_bits = instr->SixtyFourBits() == 1; 1876f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Shift is limited for W operations. 1877e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(is_64_bits || (instr->ShiftMoveWide() < 2)); 1878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1879f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the shifted immediate. 1880f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t shift = instr->ShiftMoveWide() * 16; 1881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t shifted_imm16 = instr->ImmMoveWide() << shift; 1882f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Compute the new value. 1884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (mov_op) { 1885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVN_w: 1886f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVN_x: { 1887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org new_xn_val = ~shifted_imm16; 1888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!is_64_bits) new_xn_val &= kWRegMask; 1889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVK_w: 1892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVK_x: { 1893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned reg_code = instr->Rd(); 1894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t prev_xn_val = is_64_bits ? xreg(reg_code) 1895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : wreg(reg_code); 1896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16; 1897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVZ_w: 1900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVZ_x: { 1901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org new_xn_val = shifted_imm16; 1902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 1906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Update the destination register. 1909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(instr->Rd(), new_xn_val); 1910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalSelect(Instruction* instr) { 1914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionFailed(static_cast<Condition>(instr->Condition()))) { 19151845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org uint64_t new_val = xreg(instr->Rm()); 1916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(ConditionalSelectMask)) { 19171845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSEL_w: set_wreg(instr->Rd(), new_val); break; 19181845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSEL_x: set_xreg(instr->Rd(), new_val); break; 19191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINC_w: set_wreg(instr->Rd(), new_val + 1); break; 19201845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINC_x: set_xreg(instr->Rd(), new_val + 1); break; 19211845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINV_w: set_wreg(instr->Rd(), ~new_val); break; 19221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINV_x: set_xreg(instr->Rd(), ~new_val); break; 19231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSNEG_w: set_wreg(instr->Rd(), -new_val); break; 19241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSNEG_x: set_xreg(instr->Rd(), -new_val); break; 1925f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1926f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 19271845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 19281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 19291845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(instr->Rd(), xreg(instr->Rn())); 19301845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 19311845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_wreg(instr->Rd(), wreg(instr->Rn())); 19321845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1933f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1934f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1935f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1936f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1937f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitDataProcessing1Source(Instruction* instr) { 1938f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dst = instr->Rd(); 1939f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned src = instr->Rn(); 1940f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1941f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(DataProcessing1SourceMask)) { 194297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSizeInBits)); break; 194397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSizeInBits)); break; 1944f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break; 1945f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break; 1946f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break; 1947f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break; 1948f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break; 194997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits)); 195097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org break; 195197b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits)); 195297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org break; 1953f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CLS_w: { 195497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits)); 1955f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1956f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1957f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CLS_x: { 195897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits)); 1959f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1960f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1961f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1962f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1963f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1964f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1965f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1966f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) { 1967e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((num_bits == kWRegSizeInBits) || (num_bits == kXRegSizeInBits)); 1968f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t result = 0; 1969f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < num_bits; i++) { 1970f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = (result << 1) | (value & 1); 1971f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value >>= 1; 1972f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1973f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result; 1974f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) { 1978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Split the 64-bit value into an 8-bit array, where b[0] is the least 1979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // significant byte, and b[7] is the most significant. 1980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t bytes[8]; 1981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mask = 0xff00000000000000UL; 1982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 7; i >= 0; i--) { 1983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bytes[i] = (value & mask) >> (i * 8); 1984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mask >>= 8; 1985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Permutation tables for REV instructions. 1988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // permute_table[Reverse16] is used by REV16_x, REV16_w 1989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // permute_table[Reverse32] is used by REV32_x, REV_w 1990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // permute_table[Reverse64] is used by REV_x 1991e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2)); 1992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1}, 1993f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org {4, 5, 6, 7, 0, 1, 2, 3}, 1994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org {0, 1, 2, 3, 4, 5, 6, 7} }; 1995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t result = 0; 1996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < 8; i++) { 1997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result <<= 8; 1998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result |= bytes[permute_table[mode][i]]; 1999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result; 2001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 20041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 20051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::DataProcessing2Source(Instruction* instr) { 2006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Shift shift_op = NO_SHIFT; 20071845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = 0; 2008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(DataProcessing2SourceMask)) { 20091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case SDIV_w: 2010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SDIV_x: { 20111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T rn = reg<T>(instr->Rn()); 20121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T rm = reg<T>(instr->Rm()); 20131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) { 20141845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result = std::numeric_limits<T>::min(); 2015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (rm == 0) { 2016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Division by zero can be trapped, but not on A-class processors. 2017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = 0; 2018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = rn / rm; 2020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2022f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 20231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case UDIV_w: 2024f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UDIV_x: { 20251845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 20261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn())); 20271845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm())); 2028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (rm == 0) { 2029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Division by zero can be trapped, but not on A-class processors. 2030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = 0; 2031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = rn / rm; 2033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2034f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2035f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSLV_w: 2037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSLV_x: shift_op = LSL; break; 2038f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSRV_w: 2039f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSRV_x: shift_op = LSR; break; 2040f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ASRV_w: 2041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ASRV_x: shift_op = ASR; break; 2042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case RORV_w: 2043f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case RORV_x: shift_op = ROR; break; 2044f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2045f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2046f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2047f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (shift_op != NO_SHIFT) { 2048f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Shift distance encoded in the least-significant five/six bits of the 2049f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // register. 20501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned shift = wreg(instr->Rm()); 20511845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (sizeof(T) == kWRegSize) { 20521845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org shift &= kShiftAmountWRegMask; 20531845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 20541845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org shift &= kShiftAmountXRegMask; 20551845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 20561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift); 20571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 20581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result); 20591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 20601845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 20611845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 20621845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::VisitDataProcessing2Source(Instruction* instr) { 20631845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 20641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org DataProcessing2Source<int64_t>(instr); 20651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 20661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org DataProcessing2Source<int32_t>(instr); 2067f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2068f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2071f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The algorithm used is described in section 8.2 of 2072f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Hacker's Delight, by Henry S. Warren, Jr. 2073f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// It assumes that a right shift on a signed integer is an arithmetic shift. 2074f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic int64_t MultiplyHighSigned(int64_t u, int64_t v) { 2075f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t u0, v0, w0; 2076f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t u1, v1, w1, w2, t; 2077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2078f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org u0 = u & 0xffffffffL; 2079f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org u1 = u >> 32; 2080f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org v0 = v & 0xffffffffL; 2081f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org v1 = v >> 32; 2082f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2083f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w0 = u0 * v0; 2084f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org t = u1 * v0 + (w0 >> 32); 2085f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w1 = t & 0xffffffffL; 2086f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w2 = t >> 32; 2087f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w1 = u0 * v1 + w1; 2088f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2089f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return u1 * v1 + w2 + (w1 >> 32); 2090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2091f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2092f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitDataProcessing3Source(Instruction* instr) { 2094f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t result = 0; 2095f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract and sign- or zero-extend 32-bit arguments for widening operations. 2096f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t rn_u32 = reg<uint32_t>(instr->Rn()); 2097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t rm_u32 = reg<uint32_t>(instr->Rm()); 2098f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t rn_s32 = reg<int32_t>(instr->Rn()); 2099f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t rm_s32 = reg<int32_t>(instr->Rm()); 2100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(DataProcessing3SourceMask)) { 2101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MADD_w: 2102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MADD_x: 2103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm())); 2104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MSUB_w: 2106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MSUB_x: 2107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm())); 2108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break; 2110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break; 2111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break; 2112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break; 2113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SMULH_x: 2114e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(instr->Ra() == kZeroRegCode); 2115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm())); 2116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 21191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 21201845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 21211845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(instr->Rd(), result); 21221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 21231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_wreg(instr->Rd(), result); 21241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 2125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 21281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 21291845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::BitfieldHelper(Instruction* instr) { 21301845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 21311845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T reg_size = sizeof(T) * 8; 21321845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T R = instr->ImmR(); 21331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T S = instr->ImmS(); 21341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T diff = S - R; 21351845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T mask; 2136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (diff >= 0) { 21371845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1 21381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org : static_cast<T>(-1); 2139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mask = ((1L << (S + 1)) - 1); 2141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R)); 2142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org diff += reg_size; 2143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // inzero indicates if the extracted bitfield is inserted into the 2146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // destination register value or in zero. 2147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If extend is true, extend the sign of the extracted bitfield. 2148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool inzero = false; 2149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool extend = false; 2150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(BitfieldMask)) { 2151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BFM_x: 2152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BFM_w: 2153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SBFM_x: 2155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SBFM_w: 2156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org inzero = true; 2157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org extend = true; 2158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UBFM_x: 2160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UBFM_w: 2161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org inzero = true; 2162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 2164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 2165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 21671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T dst = inzero ? 0 : reg<T>(instr->Rd()); 21681845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T src = reg<T>(instr->Rn()); 2169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Rotate source bitfield into place. 21701845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R)); 2171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Determine the sign extension. 21721845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1; 21731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0) 21741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org << (diff + 1); 2175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Merge sign extension, dest/zero and bitfield. 2177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = signbits | (result & mask) | (dst & ~mask); 2178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 21791845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result); 2180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 21831845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::VisitBitfield(Instruction* instr) { 21841845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 21851845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org BitfieldHelper<int64_t>(instr); 21861845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 21871845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org BitfieldHelper<int32_t>(instr); 2188011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org } 21891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 21901845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 2191011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 21921845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::VisitExtract(Instruction* instr) { 21931845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 21941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Extract<uint64_t>(instr); 21951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 21961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Extract<uint32_t>(instr); 21971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 2198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPImmediate(Instruction* instr) { 2202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dest = instr->Rd(); 2205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPImmediateMask)) { 2206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break; 2207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break; 2208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 2209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPIntegerConvert(Instruction* instr) { 2214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dst = instr->Rd(); 2217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned src = instr->Rn(); 2218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 22199801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org FPRounding round = fpcr().RMode(); 2220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPIntegerConvertMask)) { 2222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break; 2223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break; 2224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break; 2225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break; 2226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break; 2227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break; 2228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break; 2229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break; 2230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_ws: 2231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity)); 2232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_xs: 2234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity)); 2235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_wd: 2237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity)); 2238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_xd: 2240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity)); 2241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_ws: 2243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity)); 2244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_xs: 2246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity)); 2247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_wd: 2249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity)); 2250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_xd: 2252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity)); 2253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break; 2255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break; 2256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break; 2257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break; 2258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break; 2259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break; 2260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break; 2261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break; 2262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break; 2263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break; 2264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break; 2265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break; 2266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break; 2267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break; 2268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break; 2269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break; 2270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_ws: set_wreg(dst, sreg_bits(src)); break; 2271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_xd: set_xreg(dst, dreg_bits(src)); break; 2272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_sw: set_sreg_bits(dst, wreg(src)); break; 2273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_dx: set_dreg_bits(dst, xreg(src)); break; 2274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // A 32-bit input can be handled in the same way as a 64-bit input, since 2276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the sign- or zero-extension will not affect the conversion. 2277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break; 2278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break; 2279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break; 2280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dw: { 2281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round)); 2282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break; 2285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break; 2286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break; 2287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sw: { 2288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round)); 2289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 2293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPFixedPointConvert(Instruction* instr) { 2298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dst = instr->Rd(); 2301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned src = instr->Rn(); 2302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int fbits = 64 - instr->FPScale(); 2303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 23049801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org FPRounding round = fpcr().RMode(); 2305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPFixedPointConvertMask)) { 2307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // A 32-bit input can be handled in the same way as a 64-bit input, since 2308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the sign- or zero-extension will not affect the conversion. 2309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dx_fixed: 2310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, FixedToDouble(xreg(src), fbits, round)); 2311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dw_fixed: 2313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, FixedToDouble(wreg(src), fbits, round)); 2314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dx_fixed: 2316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, UFixedToDouble(xreg(src), fbits, round)); 2317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dw_fixed: { 2319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, 2320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UFixedToDouble(reg<uint32_t>(src), fbits, round)); 2321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sx_fixed: 2324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, FixedToFloat(xreg(src), fbits, round)); 2325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sw_fixed: 2327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, FixedToFloat(wreg(src), fbits, round)); 2328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sx_fixed: 2330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, UFixedToFloat(xreg(src), fbits, round)); 2331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sw_fixed: { 2333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, 2334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UFixedToFloat(reg<uint32_t>(src), fbits, round)); 2335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 2338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint32_t Simulator::FPToInt32(double value, FPRounding rmode) { 2343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kWMaxInt) { 2345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kWMaxInt; 2346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < kWMinInt) { 2347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kWMinInt; 2348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<int32_t>(value); 2350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::FPToInt64(double value, FPRounding rmode) { 2354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kXMaxInt) { 2356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kXMaxInt; 2357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < kXMinInt) { 2358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kXMinInt; 2359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<int64_t>(value); 2361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint32_t Simulator::FPToUInt32(double value, FPRounding rmode) { 2365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kWMaxUInt) { 2367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kWMaxUInt; 2368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < 0.0) { 2369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0; 2370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<uint32_t>(value); 2372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::FPToUInt64(double value, FPRounding rmode) { 2376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kXMaxUInt) { 2378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kXMaxUInt; 2379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < 0.0) { 2380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0; 2381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<uint64_t>(value); 2383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPCompare(Instruction* instr) { 2387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 23896b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits 23906b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org : kSRegSizeInBits; 2391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double fn_val = fpreg(reg_size, instr->Rn()); 2392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPCompareMask)) { 2394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_s: 2395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break; 2396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_s_zero: 2397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_d_zero: FPCompare(fn_val, 0.0); break; 2398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPConditionalCompare(Instruction* instr) { 2404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPConditionalCompareMask)) { 2407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCCMP_s: 2408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCCMP_d: { 2409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 2410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition passes, set the status flags to the result of 2411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // comparing the operands. 24126b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits 24136b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org : kSRegSizeInBits; 2414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); 2415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition fails, set the status flags to the nzcv immediate. 2417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetFlags(instr->Nzcv()); 24182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(NZCV); 2419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPConditionalSelect(Instruction* instr) { 2428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instr selected; 2431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 2432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org selected = instr->Rn(); 2433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org selected = instr->Rm(); 2435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPConditionalSelectMask)) { 2438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break; 2439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break; 2440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPDataProcessing1Source(Instruction* instr) { 2446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fd = instr->Rd(); 2449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fn = instr->Rn(); 2450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPDataProcessing1SourceMask)) { 2452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_s: set_sreg(fd, sreg(fn)); break; 2453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_d: set_dreg(fd, dreg(fn)); break; 2454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break; 2455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break; 2456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FNEG_s: set_sreg(fd, -sreg(fn)); break; 2457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FNEG_d: set_dreg(fd, -dreg(fn)); break; 24586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break; 24596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break; 2460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break; 2461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break; 2462255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org case FRINTM_s: 2463255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break; 2464255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org case FRINTM_d: 2465255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break; 2466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break; 2467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break; 2468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break; 2469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break; 2470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break; 2471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break; 2472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Assemble the specified IEEE-754 components into the target type and apply 2478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// appropriate rounding. 2479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// sign: 0 = positive, 1 = negative 2480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// exponent: Unbiased IEEE-754 exponent. 2481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// mantissa: The mantissa of the input. The top bit (which is not encoded for 2482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// normal IEEE-754 values) must not be omitted. This bit has the 2483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// value 'pow(2, exponent)'. 2484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// 2485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The input value is assumed to be a normalized value. That is, the input may 2486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// not be infinity or NaN. If the source value is subnormal, it must be 2487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// normalized before calling this function such that the highest set bit in the 2488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// mantissa has the value 'pow(2, exponent)'. 2489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// 2490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than 2491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// calling a templated FPRound. 2492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <class T, int ebits, int mbits> 2493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa, 2494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPRounding round_mode) { 2495e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((sign == 0) || (sign == 1)); 2496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Only the FPTieEven rounding mode is implemented. 2498e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(round_mode == FPTieEven); 2499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org USE(round_mode); 2500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Rounding can promote subnormals to normals, and normals to infinities. For 2502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be 2503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // encodable as a float, but rounding based on the low-order mantissa bits 2504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // could make it overflow. With ties-to-even rounding, this value would become 2505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // an infinity. 2506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ---- Rounding Method ---- 2508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The exponent is irrelevant in the rounding operation, so we treat the 2510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // lowest-order bit that will fit into the result ('onebit') as having 2511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the value '1'. Similarly, the highest-order bit that won't fit into 2512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the result ('halfbit') has the value '0.5'. The 'point' sits between 2513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 'onebit' and 'halfbit': 2514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // These bits fit into the result. 2516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // |---------------------| 2517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 2518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // || 2519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / | 2520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / halfbit 2521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // onebit 2522f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For subnormal outputs, the range of representable bits is smaller and 2524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the position of onebit and halfbit depends on the exponent of the 2525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // input, but the method is otherwise similar. 2526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // onebit(frac) 2528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | 2529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | halfbit(frac) halfbit(adjusted) 2530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | / / 2531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | | | 2532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00 2533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.0... -> 0b00.0... -> 0b00 2534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00 2535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.1... -> 0b00.1... -> 0b01 2536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01 2537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.0... -> 0b01.0... -> 0b01 2538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10 2539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.1... -> 0b01.1... -> 0b10 2540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10 2541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.0... -> 0b10.0... -> 0b10 2542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10 2543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.1... -> 0b10.1... -> 0b11 2544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11 2545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ... / | / | 2546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / | / | 2547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / | 2548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / | 2549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // mantissa = (mantissa >> shift) + halfbit(adjusted); 2551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int mantissa_offset = 0; 2553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int exponent_offset = mantissa_offset + mbits; 2554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int sign_offset = exponent_offset + ebits; 2555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1)); 2556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Bail out early for zero inputs. 2558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (mantissa == 0) { 2559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sign << sign_offset; 2560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If all bits in the exponent are set, the value is infinite or NaN. 2563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This is true for all binary IEEE-754 formats. 2564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int infinite_exponent = (1 << ebits) - 1; 2565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int max_normal_exponent = infinite_exponent - 1; 2566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Apply the exponent bias to encode it for the result. Doing this early makes 2568f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // it easy to detect values that will be infinite or subnormal. 2569f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent += max_normal_exponent >> 1; 2570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (exponent > max_normal_exponent) { 2572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Overflow: The input is too large for the result type to represent. The 2573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // FPTieEven rounding mode handles overflows using infinities. 2574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent = infinite_exponent; 2575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa = 0; 2576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (sign << sign_offset) | 2577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (exponent << exponent_offset) | 2578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (mantissa << mantissa_offset); 2579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the shift required to move the top mantissa bit to the proper 2582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // place in the destination type. 2583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64); 2584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int shift = highest_significant_bit - mbits; 2585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (exponent <= 0) { 2587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The output will be subnormal (before rounding). 2588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For subnormal outputs, the shift must be adjusted by the exponent. The +1 2590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // is necessary because the exponent of a subnormal value (encoded as 0) is 2591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the same as the exponent of the smallest normal value (encoded as 1). 2592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org shift += -exponent + 1; 2593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle inputs that would produce a zero output. 2595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Shifts higher than highest_significant_bit+1 will always produce a zero 2597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // result. A shift of exactly highest_significant_bit+1 might produce a 2598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // non-zero result after rounding. 2599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (shift > (highest_significant_bit + 1)) { 2600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The result will always be +/-0.0. 2601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sign << sign_offset; 2602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Properly encode the exponent for a subnormal output. 2605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent = 0; 2606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Clear the topmost mantissa bit, since this is not encoded in IEEE-754 2608f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // normal values. 2609f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa &= ~(1UL << highest_significant_bit); 2610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2612f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (shift > 0) { 2613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We have to shift the mantissa to the right. Some precision is lost, so we 2614f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // need to apply rounding. 2615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t onebit_mantissa = (mantissa >> (shift)) & 1; 2616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1; 2617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa); 2618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org T halfbit_adjusted = (adjusted >> (shift-1)) & 1; 2619f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2620f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org T result = (sign << sign_offset) | 2621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (exponent << exponent_offset) | 2622f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ((mantissa >> shift) << mantissa_offset); 2623f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2624f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // A very large mantissa can overflow during rounding. If this happens, the 2625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // exponent should be incremented and the mantissa set to 1.0 (encoded as 2626f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0). Applying halfbit_adjusted after assembling the float has the nice 2627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // side-effect that this case is handled for free. 2628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This also handles cases where a very large finite value overflows to 2630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // infinity, or where a very large subnormal value overflows to become 2631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // normal. 2632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result + halfbit_adjusted; 2633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We have to shift the mantissa to the left (or not at all). The input 2635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // mantissa is exactly representable in the output mantissa, so apply no 2636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // rounding correction. 2637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (sign << sign_offset) | 2638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (exponent << exponent_offset) | 2639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ((mantissa << -shift) << mantissa_offset); 2640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// See FPRound for a description of this function. 2645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic inline double FPRoundToDouble(int64_t sign, int64_t exponent, 2646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mantissa, FPRounding round_mode) { 2647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t bits = 2648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign, 2649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent, 2650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa, 2651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org round_mode); 2652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_double(bits); 2653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// See FPRound for a description of this function. 2657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic inline float FPRoundToFloat(int64_t sign, int64_t exponent, 2658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mantissa, FPRounding round_mode) { 2659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int32_t bits = 2660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign, 2661f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent, 2662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa, 2663f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org round_mode); 2664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_float(bits); 2665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) { 2669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src >= 0) { 2670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return UFixedToDouble(src, fbits, round); 2671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This works for all negative values, including INT64_MIN. 2673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -UFixedToDouble(-src, fbits, round); 2674f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) { 2679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // An input of 0 is a special case because the result is effectively 2680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit. 2681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src == 0) { 2682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0.0; 2683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the exponent. The highest significant bit will have the value 2686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2^exponent. 2687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int highest_significant_bit = 63 - CountLeadingZeros(src, 64); 2688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int64_t exponent = highest_significant_bit - fbits; 2689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return FPRoundToDouble(0, exponent, src, round); 2691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) { 2695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src >= 0) { 2696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return UFixedToFloat(src, fbits, round); 2697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This works for all negative values, including INT64_MIN. 2699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -UFixedToFloat(-src, fbits, round); 2700f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2704f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) { 2705f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // An input of 0 is a special case because the result is effectively 2706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit. 2707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src == 0) { 2708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0.0f; 2709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the exponent. The highest significant bit will have the value 2712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2^exponent. 2713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int highest_significant_bit = 63 - CountLeadingZeros(src, 64); 2714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int32_t exponent = highest_significant_bit - fbits; 2715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return FPRoundToFloat(0, exponent, src, round); 2717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::FPRoundInt(double value, FPRounding round_mode) { 2721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((value == 0.0) || (value == kFP64PositiveInfinity) || 27226b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (value == kFP64NegativeInfinity)) { 2723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return value; 27246b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(value)) { 27256b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(value); 2726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double int_result = floor(value); 2729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double error = value - int_result; 2730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (round_mode) { 2731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPTieAway: { 2732255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // Take care of correctly handling the range ]-0.5, -0.0], which must 2733255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // yield -0.0. 2734255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org if ((-0.5 < value) && (value < 0.0)) { 2735255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org int_result = -0.0; 2736255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org 2737255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) { 2738255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // If the error is greater than 0.5, or is equal to 0.5 and the integer 2739255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // result is positive, round up. 2740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int_result++; 2741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPTieEven: { 2745255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // Take care of correctly handling the range [-0.5, -0.0], which must 2746255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // yield -0.0. 2747255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org if ((-0.5 <= value) && (value < 0.0)) { 2748255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org int_result = -0.0; 2749255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org 2750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the error is greater than 0.5, or is equal to 0.5 and the integer 2751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // result is odd, round up. 2752255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org } else if ((error > 0.5) || 2753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ((error == 0.5) && (fmod(int_result, 2) != 0))) { 2754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int_result++; 2755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPZero: { 2759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If value > 0 then we take floor(value) 2760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // otherwise, ceil(value) 2761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value < 0) { 2762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int_result = ceil(value); 2763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2766f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPNegativeInfinity: { 2767f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We always use floor(value). 2768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return int_result; 2773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::FPToDouble(float value) { 2777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (std::fpclassify(value)) { 2778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NAN: { 27799801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org if (fpcr().DN()) return kFP64DefaultNaN; 27806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 27816b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Convert NaNs as the processor would: 2782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The sign is propagated. 2783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The payload (mantissa) is transferred entirely, except that the top 2784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // bit is forced to '1', making the result a quiet NaN. The unused 2785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (low-order) payload bits are set to 0. 2786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t raw = float_to_rawbits(value); 2787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t sign = raw >> 31; 2789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t exponent = (1 << 11) - 1; 2790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t payload = unsigned_bitextract_64(21, 0, raw); 2791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org payload <<= (52 - 23); // The unused low-order bits should be 0. 2792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org payload |= (1L << 51); // Force a quiet NaN. 2793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_double((sign << 63) | (exponent << 52) | payload); 2795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_ZERO: 2798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NORMAL: 2799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_SUBNORMAL: 2800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_INFINITE: { 2801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // All other inputs are preserved in a standard cast, because every value 2802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // representable using an IEEE-754 float is also representable using an 2803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // IEEE-754 double. 2804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return static_cast<double>(value); 2805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 2809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return static_cast<double>(value); 2810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::FPToFloat(double value, FPRounding round_mode) { 2814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Only the FPTieEven rounding mode is implemented. 2815e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(round_mode == FPTieEven); 2816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org USE(round_mode); 2817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (std::fpclassify(value)) { 2819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NAN: { 28209801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org if (fpcr().DN()) return kFP32DefaultNaN; 28216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 28226b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Convert NaNs as the processor would: 2823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The sign is propagated. 2824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The payload (mantissa) is transferred as much as possible, except 2825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // that the top bit is forced to '1', making the result a quiet NaN. 2826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t raw = double_to_rawbits(value); 2827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t sign = raw >> 63; 2829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t exponent = (1 << 8) - 1; 2830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw); 2831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org payload |= (1 << 22); // Force a quiet NaN. 2832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2833f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_float((sign << 31) | (exponent << 23) | payload); 2834f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2835f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2836f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_ZERO: 2837f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_INFINITE: { 2838f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // In a C++ cast, any value representable in the target type will be 2839f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // unchanged. This is always the case for +/-0.0 and infinities. 2840f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return static_cast<float>(value); 2841f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2842f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2843f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NORMAL: 2844f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_SUBNORMAL: { 2845f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Convert double-to-float as the processor would, assuming that FPCR.FZ 2846f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (flush-to-zero) is not set. 2847f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t raw = double_to_rawbits(value); 2848f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract the IEEE-754 double components. 2849f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t sign = raw >> 63; 2850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract the exponent and remove the IEEE-754 encoding bias. 2851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023; 2852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract the mantissa and add the implicit '1' bit. 2853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mantissa = unsigned_bitextract_64(51, 0, raw); 2854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (std::fpclassify(value) == FP_NORMAL) { 2855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa |= (1UL << 52); 2856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2857f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return FPRoundToFloat(sign, exponent, mantissa, round_mode); 2858f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 2862f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return value; 2863f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2864f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2865f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2866f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPDataProcessing2Source(Instruction* instr) { 2867f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2869f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fd = instr->Rd(); 2870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fn = instr->Rn(); 2871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fm = instr->Rm(); 2872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 28736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Fmaxnm and Fminnm have special NaN handling. 28746b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org switch (instr->Mask(FPDataProcessing2SourceMask)) { 28756b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return; 28766b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return; 28776b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return; 28786b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return; 28796b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org default: 28806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; // Fall through. 28816b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 28826b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 28836b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (FPProcessNaNs(instr)) return; 28846b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPDataProcessing2SourceMask)) { 28866b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break; 28876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break; 28886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break; 28896b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break; 28906b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break; 28916b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break; 28926b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break; 28936b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break; 2894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break; 2895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break; 2896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break; 2897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break; 28986b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_s: 28996b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_d: 29006b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_s: 29016b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_d: 29026b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // These were handled before the standard FPProcessNaNs() stage. 29036b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org UNREACHABLE(); 2904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPDataProcessing3Source(Instruction* instr) { 2910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fd = instr->Rd(); 2913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fn = instr->Rn(); 2914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fm = instr->Rm(); 2915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fa = instr->Ra(); 2916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPDataProcessing3SourceMask)) { 2918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // fd = fa +/- (fn * fm) 29196b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break; 29206b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break; 29216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break; 29226b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break; 29236b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Negated variants of the above. 29246b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMADD_s: 29256b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm))); 29266b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 29276b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMSUB_s: 29286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm))); 29296b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 29306b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMADD_d: 29316b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm))); 29326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 29336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMSUB_d: 29346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm))); 29356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 2936f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2937f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2938f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2939f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2940f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2941f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 29426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPAdd(T op1, T op2) { 29436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 2944e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(op1) && !std::isnan(op2)); 29456b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2946a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) { 29476b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf + -inf returns the default NaN. 29486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 29496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 29506b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 29516b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 + op2; 29526b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29536b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 29546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 29576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPDiv(T op1, T op2) { 29586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 2959e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(op1) && !std::isnan(op2)); 29606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2961a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) { 29626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf / inf and 0.0 / 0.0 return the default NaN. 29636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 29646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 29656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 29666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 / op2; 2967f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 29686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 29696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 29726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPMax(T a, T b) { 29736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 2974e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(a) && !std::isnan(b)); 2975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((a == 0.0) && (b == 0.0) && 2977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (copysign(1.0, a) != copysign(1.0, b))) { 2978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // a and b are zero, and the sign differs: return +0.0. 2979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0.0; 2980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (a > b) ? a : b; 2982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 2987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgT Simulator::FPMaxNM(T a, T b) { 2988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (IsQuietNaN(a) && !IsQuietNaN(b)) { 2989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org a = kFP64NegativeInfinity; 2990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { 2991f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org b = kFP64NegativeInfinity; 2992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 29936b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29946b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T result = FPProcessNaNs(a, b); 29956b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return std::isnan(result) ? result : FPMax(a, b); 2996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 2999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgT Simulator::FPMin(T a, T b) { 30006b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 3001e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(a) && !std::isnan(b)); 3002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((a == 0.0) && (b == 0.0) && 3004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (copysign(1.0, a) != copysign(1.0, b))) { 3005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // a and b are zero, and the sign differs: return -0.0. 3006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -0.0; 3007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (a < b) ? a : b; 3009f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 3014f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgT Simulator::FPMinNM(T a, T b) { 3015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (IsQuietNaN(a) && !IsQuietNaN(b)) { 3016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org a = kFP64PositiveInfinity; 3017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { 3018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org b = kFP64PositiveInfinity; 3019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 30206b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T result = FPProcessNaNs(a, b); 3022a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org return std::isnan(result) ? result : FPMin(a, b); 30236b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30246b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30256b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30266b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30276b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPMul(T op1, T op2) { 30286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 3029e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(op1) && !std::isnan(op2)); 30306b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 3031a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) { 30326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf * 0.0 returns the default NaN. 30336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 30346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 30366b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 * op2; 30376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30406b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30416b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate<typename T> 30426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPMulAdd(T a, T op1, T op2) { 30436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T result = FPProcessNaNs3(a, op1, op2); 30446b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30456b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T sign_a = copysign(1.0, a); 30466b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T sign_prod = copysign(1.0, op1) * copysign(1.0, op2); 30476b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org bool isinf_prod = std::isinf(op1) || std::isinf(op2); 30486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org bool operation_generates_nan = 30496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0 30506b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf 30516b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf 30526b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30536b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(result)) { 30546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Generated NaNs override quiet NaNs propagated from a. 30556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (operation_generates_nan && IsQuietNaN(a)) { 30566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 30576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return result; 30596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // If the operation would produce a NaN, return the default NaN. 30636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (operation_generates_nan) { 30646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 30656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Work around broken fma implementations for exact zero results: The sign of 30686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // exact 0.0 results is positive unless both a and op1 * op2 are negative. 30696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) { 30706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0; 30716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org result = FusedMultiplyAdd(op1, op2, a); 3074e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(result)); 30756b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30766b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Work around broken fma implementations for rounded zero results: If a is 30776b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // 0.0, the sign of the result is the sign of op1 * op2 before rounding. 30786b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if ((a == 0.0) && (result == 0.0)) { 30796b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return copysign(0.0, sign_prod); 30806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30816b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30826b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return result; 30836b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30846b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30856b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30866b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPSqrt(T op) { 30886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(op)) { 30896b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op); 30906b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (op < 0.0) { 30916b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 30926b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30936b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return std::sqrt(op); 30946b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30956b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30966b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30976b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30986b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30996b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPSub(T op1, T op2) { 31006b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 3101e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!std::isnan(op1) && !std::isnan(op2)); 31026b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 3103a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) { 31046b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf - inf returns the default NaN. 31056b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 31066b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 31076b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 31086b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 - op2; 31096b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 31106b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 31116b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31126b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31136b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 31146b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPProcessNaN(T op) { 3115e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(std::isnan(op)); 31169801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op); 31176b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 31186b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31196b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31206b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 31216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPProcessNaNs(T op1, T op2) { 31226b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (IsSignallingNaN(op1)) { 31236b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 31246b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (IsSignallingNaN(op2)) { 31256b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 31266b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op1)) { 3127e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsQuietNaN(op1)); 31286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 31296b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op2)) { 3130e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsQuietNaN(op2)); 31316b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 31326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 31336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return 0.0; 31346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 31356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 31366b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 31396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPProcessNaNs3(T op1, T op2, T op3) { 31406b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (IsSignallingNaN(op1)) { 31416b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 31426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (IsSignallingNaN(op2)) { 31436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 31446b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (IsSignallingNaN(op3)) { 31456b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op3); 31466b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op1)) { 3147e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsQuietNaN(op1)); 31486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 31496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op2)) { 3150e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsQuietNaN(op2)); 31516b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 31526b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op3)) { 3153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsQuietNaN(op3)); 31546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op3); 31556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 31566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return 0.0; 31576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 31586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 31596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgbool Simulator::FPProcessNaNs(Instruction* instr) { 31626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned fd = instr->Rd(); 31636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned fn = instr->Rn(); 31646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned fm = instr->Rm(); 31656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org bool done = false; 31666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (instr->Mask(FP64) == FP64) { 31686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org double result = FPProcessNaNs(dreg(fn), dreg(fm)); 31696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(result)) { 31706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_dreg(fd, result); 31716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org done = true; 31726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 31736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 31746b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org float result = FPProcessNaNs(sreg(fn), sreg(fm)); 31756b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(result)) { 31766b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_sreg(fd, result); 31776b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org done = true; 31786b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 31796b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 31806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 31816b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return done; 3182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitSystem(Instruction* instr) { 3186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Some system instructions hijack their Op and Cp fields to represent a 3187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // range of immediates instead of indicating a different instruction. This 3188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // makes the decoding tricky. 3189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) { 3190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(SystemSysRegMask)) { 3191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MRS: { 3192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->ImmSystemRegister()) { 3193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; 3194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; 3195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 3196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MSR: { 3200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->ImmSystemRegister()) { 32012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case NZCV: 32022c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org nzcv().SetRawValue(xreg(instr->Rt())); 32032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(NZCV); 32042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 32052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org case FPCR: 32062c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org fpcr().SetRawValue(xreg(instr->Rt())); 32072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org LogSystemRegister(FPCR); 32082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org break; 3209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 3210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { 3215e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(instr->Mask(SystemHintMask) == HINT); 3216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->ImmHint()) { 3217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NOP: break; 3218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 3219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { 3221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __sync_synchronize(); 3222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 3224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool Simulator::GetValue(const char* desc, int64_t* value) { 3229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int regnum = CodeFromName(desc); 3230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (regnum >= 0) { 3231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned code = regnum; 3232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (code == kZeroRegCode) { 3233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Catch the zero register and return 0. 3234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org *value = 0; 3235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (code == kSPRegInternalCode) { 3237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Translate the stack pointer code to 31, for Reg31IsStackPointer. 3238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code = 31; 3239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (desc[0] == 'w') { 3241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org *value = wreg(code, Reg31IsStackPointer); 3242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org *value = xreg(code, Reg31IsStackPointer); 3244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strncmp(desc, "0x", 2) == 0) { 3247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SScanF(desc + 2, "%" SCNx64, 3248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<uint64_t*>(value)) == 1; 3249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SScanF(desc, "%" SCNu64, 3251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<uint64_t*>(value)) == 1; 3252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool Simulator::PrintValue(const char* desc) { 3257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(desc, "csp") == 0) { 3258e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode)); 32599e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s csp:%s 0x%016" PRIx64 "%s\n", 3260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal); 3261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(desc, "wcsp") == 0) { 3263e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode)); 32649e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n", 3265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal); 3266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int i = CodeFromName(desc); 3270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters); 3271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false; 3272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (desc[0] == 'v') { 32749e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n", 3275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, VRegNameForCode(i), 3276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, double_to_rawbits(dreg(i)), 3277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal, 3278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, DRegNameForCode(i), 3279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, dreg(i), 3280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, SRegNameForCode(i), 3281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, sreg(i), 3282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (desc[0] == 'd') { 32859e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s %g%s\n", 3286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, DRegNameForCode(i), 3287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, dreg(i), 3288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (desc[0] == 's') { 32919e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s %g%s\n", 3292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, SRegNameForCode(i), 3293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, sreg(i), 3294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (desc[0] == 'w') { 32979e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n", 3298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal); 3299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // X register names have a wide variety of starting characters, but anything 3302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // else will be an X register. 33039e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n", 3304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal); 3305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Debug() { 3311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define COMMAND_SIZE 63 3312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define ARG_SIZE 255 3313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define STR(a) #a 3315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define XSTR(a) STR(a) 3316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char cmd[COMMAND_SIZE + 1]; 3318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char arg1[ARG_SIZE + 1]; 3319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char arg2[ARG_SIZE + 1]; 3320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* argv[3] = { cmd, arg1, arg2 }; 3321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Make sure to have a proper terminating character if reaching the limit. 3323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cmd[COMMAND_SIZE] = 0; 3324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org arg1[ARG_SIZE] = 0; 3325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org arg2[ARG_SIZE] = 0; 3326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool done = false; 3328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool cleared_log_disasm_bit = false; 3329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (!done) { 3331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Disassemble the next instruction to execute before doing anything else. 3332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintInstructionsAt(pc_, 1); 3333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Read the command line. 3334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* line = ReadLine("sim> "); 3335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (line == NULL) { 3336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Repeat last command by default. 3339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* last_input = last_debugger_input(); 3340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(line, "\n") == 0 && (last_input != NULL)) { 3341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org DeleteArray(line); 3342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org line = last_input; 3343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Update the latest command ran 3345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_last_debugger_input(line); 3346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Use sscanf to parse the individual parts of the command line. At the 3349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // moment no command expects more than two parameters. 3350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int argc = SScanF(line, 3351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "%" XSTR(COMMAND_SIZE) "s " 3352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "%" XSTR(ARG_SIZE) "s " 3353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "%" XSTR(ARG_SIZE) "s", 3354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cmd, arg1, arg2); 3355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stepi / si ------------------------------------------------------------ 3357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 3358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We are about to execute instructions, after which by default we 3359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // should increment the pc_. If it was set when reaching this debug 3360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // instruction, it has not been cleared because this instruction has not 3361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // completed yet. So clear it manually. 3362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_modified_ = false; 3363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 1) { 3365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExecuteInstruction(); 3366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t number_of_instructions_to_execute = 1; 3368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GetValue(arg1, &number_of_instructions_to_execute); 3369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() | LOG_DISASM); 3371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (number_of_instructions_to_execute-- > 0) { 3372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExecuteInstruction(); 3373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() & ~LOG_DISASM); 3375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If it was necessary, the pc has already been updated or incremented 3379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // when executing the instruction. So we do not want it to be updated 3380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // again. It will be cleared when exiting. 3381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_modified_ = true; 3382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // next / n -------------------------------------------------------------- 3384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) { 3385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Tell the simulator to break after the next executed BL. 3386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break_on_next_ = true; 3387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Continue. 3388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org done = true; 3389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // continue / cont / c --------------------------------------------------- 3391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "continue") == 0) || 3392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(cmd, "cont") == 0) || 3393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(cmd, "c") == 0)) { 3394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Leave the debugger shell. 3395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org done = true; 3396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // disassemble / disasm / di --------------------------------------------- 3398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "disassemble") == 0 || 3399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org strcmp(cmd, "disasm") == 0 || 3400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org strcmp(cmd, "di") == 0) { 3401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t n_of_instrs_to_disasm = 10; // default value. 3402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t address = reinterpret_cast<int64_t>(pc_); // default value. 3403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc >= 2) { // disasm <n of instrs> 3404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GetValue(arg1, &n_of_instrs_to_disasm); 3405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc >= 3) { // disasm <n of instrs> <address> 3407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GetValue(arg2, &address); 3408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Disassemble. 3411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintInstructionsAt(reinterpret_cast<Instruction*>(address), 3412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org n_of_instrs_to_disasm); 3413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // print / p ------------------------------------------------------------- 3416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { 3417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 2) { 3418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(arg1, "all") == 0) { 34192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org PrintRegisters(); 34202c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org PrintFPRegisters(); 3421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!PrintValue(arg1)) { 3423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF( 3428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "print <register>\n" 3429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print the content of a register. (alias 'p')\n" 3430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " 'print all' will print all registers.\n" 3431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Use 'printobject' to get more details about the value.\n"); 3432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // printobject / po ------------------------------------------------------ 3435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "printobject") == 0) || 3436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(cmd, "po") == 0)) { 3437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 2) { 3438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value; 3439f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org OFStream os(stdout); 3440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (GetValue(arg1, &value)) { 3441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Object* obj = reinterpret_cast<Object*>(value); 3442f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org os << arg1 << ": \n"; 3443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 3444f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org obj->Print(os); 3445f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org os << "\n"; 3446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#else 3447f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org os << Brief(obj) << "\n"; 3448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 3449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3450f15d0cdbef11a212e108432465f014a7d3c3aa12machenbach@chromium.org os << arg1 << " unrecognized\n"; 3451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("printobject <value>\n" 3454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "printobject <register>\n" 3455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print details about the value. (alias 'po')\n"); 3456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack / mem ---------------------------------------------------------- 3459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 3460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t* cur = NULL; 3461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t* end = NULL; 3462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int next_arg = 1; 3463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(cmd, "stack") == 0) { 3465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cur = reinterpret_cast<int64_t*>(jssp()); 3466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { // "mem" 3468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value; 3469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!GetValue(arg1, &value)) { 3470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org continue; 3472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cur = reinterpret_cast<int64_t*>(value); 3474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org next_arg++; 3475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t words = 0; 3478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == next_arg) { 3479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org words = 10; 3480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (argc == next_arg + 1) { 3481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!GetValue(argv[next_arg], &words)) { 3482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", argv[next_arg]); 3483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Printing 10 double words by default"); 3484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org words = 10; 3485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 3488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org end = cur + words; 3490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (cur < end) { 3492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64, 3493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<uint64_t>(cur), *cur, *cur); 3494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 3495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value = *cur; 3496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Heap* current_heap = v8::internal::Isolate::Current()->heap(); 3497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (((value & 1) == 0) || current_heap->Contains(obj)) { 3498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF(" ("); 3499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((value & kSmiTagMask) == 0) { 3500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(kSmiValueSize == 32); 3501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int32_t untagged = (value >> kSmiShift) & 0xffffffff; 3502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("smi %" PRId32, untagged); 3503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org obj->ShortPrint(); 3505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF(")"); 3507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cur++; 3510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // trace / t ------------------------------------------------------------- 3513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) { 3514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((log_parameters() & (LOG_DISASM | LOG_REGS)) != 3515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (LOG_DISASM | LOG_REGS)) { 3516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Enabling disassembly and registers tracing\n"); 3517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS); 3518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Disabling disassembly and registers tracing\n"); 3520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS)); 3521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3522f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // break / b ------------------------------------------------------------- 3524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) { 3525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 2) { 3526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value; 3527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (GetValue(arg1, &value)) { 3528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org SetBreakpoint(reinterpret_cast<Instruction*>(value)); 3529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ListBreakpoints(); 3534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Use `break <address>` to set or disable a breakpoint\n"); 3535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // gdb ------------------------------------------------------------------- 3538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "gdb") == 0) { 3539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Relinquishing control to gdb.\n"); 35405de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org base::OS::DebugBreak(); 3541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Regaining control from gdb.\n"); 3542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sysregs --------------------------------------------------------------- 3544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "sysregs") == 0) { 3545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintSystemRegisters(); 3546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // help / h -------------------------------------------------------------- 3548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) { 3549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF( 3550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "stepi / si\n" 3551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " stepi <n>\n" 3552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Step <n> instructions.\n" 3553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "next / n\n" 3554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Continue execution until a BL instruction is reached.\n" 3555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " At this point a breakpoint is set just after this BL.\n" 3556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Then execution is resumed. It will probably later hit the\n" 3557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " breakpoint just set.\n" 3558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "continue / cont / c\n" 3559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Continue execution from here.\n" 3560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "disassemble / disasm / di\n" 3561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " disassemble <n> <address>\n" 3562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Disassemble <n> instructions from current <address>.\n" 3563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " By default <n> is 20 and <address> is the current pc.\n" 3564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "print / p\n" 3565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " print <register>\n" 3566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print the content of a register.\n" 3567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " 'print all' will print all registers.\n" 3568f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Use 'printobject' to get more details about the value.\n" 3569f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "printobject / po\n" 3570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " printobject <value>\n" 3571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " printobject <register>\n" 3572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print details about the value.\n" 3573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "stack\n" 3574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " stack [<words>]\n" 3575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Dump stack content, default dump 10 words\n" 3576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "mem\n" 3577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " mem <address> [<words>]\n" 3578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Dump memory content, default dump 10 words\n" 3579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "trace / t\n" 3580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Toggle disassembly and register tracing\n" 3581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "break / b\n" 3582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " break : list all breakpoints\n" 3583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " break <address> : set / enable / disable a breakpoint.\n" 3584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "gdb\n" 3585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Enter gdb.\n" 3586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "sysregs\n" 3587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print all system registers (including NZCV).\n"); 3588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Unknown command: %s\n", cmd); 3590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Use 'help' for more information.\n"); 3591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (cleared_log_disasm_bit == true) { 3594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters_ | LOG_DISASM); 3595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitException(Instruction* instr) { 3601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(ExceptionMask)) { 3602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case HLT: { 3603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->ImmException() == kImmExceptionIsDebug) { 3604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Read the arguments encoded inline in the instruction stream. 3605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t code; 3606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t parameters; 3607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 36084452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org memcpy(&code, 36094452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_->InstructionAtOffset(kDebugCodeOffset), 36104452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org sizeof(code)); 36114452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org memcpy(¶meters, 36124452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_->InstructionAtOffset(kDebugParamsOffset), 36134452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org sizeof(parameters)); 36144452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org char const *message = 36154452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org reinterpret_cast<char const*>( 36164452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_->InstructionAtOffset(kDebugMessageOffset)); 3617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Always print something when we hit a debug point that breaks. 3619f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We are going to break, so printing something is not an issue in 3620f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // terms of speed. 3621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) { 3622f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (message != NULL) { 36239e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 36242c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "# %sDebugger hit %d: %s%s%s\n", 3625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_debug_number, 3626f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code, 3627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_debug_message, 3628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org message, 3629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 36319e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 36322c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org "# %sDebugger hit %d.%s\n", 3633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_debug_number, 3634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code, 3635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Other options. 3640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (parameters & kDebuggerTracingDirectivesMask) { 3641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TRACE_ENABLE: 3642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() | parameters); 3643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } 3644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_REGS) { PrintRegisters(); } 3645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } 3646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TRACE_DISABLE: 3648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() & ~parameters); 3649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TRACE_OVERRIDE: 3651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(parameters); 3652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 3654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We don't support a one-shot LOG_DISASM. 3655e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((parameters & LOG_DISASM) == 0); 3656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Don't print information that is already being traced. 3657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org parameters &= ~log_parameters(); 3658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Print the requested information. 36592c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (parameters & LOG_SYS_REGS) PrintSystemRegisters(); 36602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (parameters & LOG_REGS) PrintRegisters(); 36612c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org if (parameters & LOG_FP_REGS) PrintFPRegisters(); 3662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3663f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The stop parameters are inlined in the code. Skip them: 3665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Skip to the end of the message string. 36664452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org size_t size = kDebugMessageOffset + strlen(message) + 1; 36674452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); 3668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Verify that the unreachable marker is present. 3669e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(pc_->Mask(ExceptionMask) == HLT); 3670e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable); 3671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Skip past the unreachable marker. 36724452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org set_pc(pc_->following()); 3673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3674f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check if the debugger should break. 3675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & BREAK) Debug(); 3676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) { 36787010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org DoRuntimeCall(instr); 3679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->ImmException() == kImmExceptionIsPrintf) { 3680a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org DoPrintf(instr); 3681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->ImmException() == kImmExceptionIsUnreachable) { 3683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n", 3684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(pc_)); 3685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org abort(); 3686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 36885de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org base::OS::DebugBreak(); 3689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 3694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 3695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3698a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3699a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.orgvoid Simulator::DoPrintf(Instruction* instr) { 3700e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((instr->Mask(ExceptionMask) == HLT) && 3701a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org (instr->ImmException() == kImmExceptionIsPrintf)); 3702a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3703a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Read the arguments encoded inline in the instruction stream. 3704a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t arg_count; 3705a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t arg_pattern_list; 3706a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org STATIC_ASSERT(sizeof(*instr) == 1); 3707a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org memcpy(&arg_count, 3708a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org instr + kPrintfArgCountOffset, 3709a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org sizeof(arg_count)); 3710a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org memcpy(&arg_pattern_list, 3711a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org instr + kPrintfArgPatternListOffset, 3712a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org sizeof(arg_pattern_list)); 3713a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3714e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(arg_count <= kPrintfMaxArgCount); 3715e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0); 3716a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3717a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // We need to call the host printf function with a set of arguments defined by 3718a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // arg_pattern_list. Because we don't know the types and sizes of the 3719a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // arguments, this is very difficult to do in a robust and portable way. To 3720a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // work around the problem, we pick apart the format string, and print one 3721a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // format placeholder at a time. 3722a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3723a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Allocate space for the format string. We take a copy, so we can modify it. 3724a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Leave enough space for one extra character per expected argument (plus the 3725a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // '\0' termination). 3726a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org const char * format_base = reg<const char *>(0); 3727e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(format_base != NULL); 3728a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org size_t length = strlen(format_base) + 1; 3729a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org char * const format = new char[length + arg_count]; 3730a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3731a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // A list of chunks, each with exactly one format placeholder. 3732a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org const char * chunks[kPrintfMaxArgCount]; 3733a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3734a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Copy the format string and search for format placeholders. 3735a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t placeholder_count = 0; 3736a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org char * format_scratch = format; 3737a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org for (size_t i = 0; i < length; i++) { 3738a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (format_base[i] != '%') { 3739a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[i]; 3740a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } else { 3741a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (format_base[i + 1] == '%') { 3742a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Ignore explicit "%%" sequences. 3743a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[i]; 3744a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3745a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (placeholder_count == 0) { 3746a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // The first chunk is passed to printf using "%s", so we need to 3747a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // unescape "%%" sequences in this chunk. (Just skip the next '%'.) 3748a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org i++; 3749a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } else { 3750a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Otherwise, pass through "%%" unchanged. 3751a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[++i]; 3752a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3753a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } else { 3754a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org CHECK(placeholder_count < arg_count); 3755a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Insert '\0' before placeholders, and store their locations. 3756a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = '\0'; 3757a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org chunks[placeholder_count++] = format_scratch; 3758a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[i]; 3759a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3760a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3761a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3762e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(format_scratch <= (format + length + arg_count)); 3763a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org CHECK(placeholder_count == arg_count); 3764a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3765a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Finally, call printf with each chunk, passing the appropriate register 3766a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // argument. Normally, printf returns the number of bytes transmitted, so we 3767a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // can emulate a single printf call by adding the result from each chunk. If 3768a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // any call returns a negative (error) value, though, just return that value. 3769a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3770a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org fprintf(stream_, "%s", clr_printf); 3771a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3772a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Because '\0' is inserted before each placeholder, the first string in 3773a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // 'format' contains no format placeholders and should be printed literally. 3774a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int result = fprintf(stream_, "%s", format); 3775a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int pcs_r = 1; // Start at x1. x0 holds the format string. 3776a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int pcs_f = 0; // Start at d0. 3777a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (result >= 0) { 3778a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org for (uint32_t i = 0; i < placeholder_count; i++) { 3779a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int part_result = -1; 3780a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3781a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits); 3782a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org arg_pattern &= (1 << kPrintfArgPatternBits) - 1; 3783a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org switch (arg_pattern) { 3784a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org case kPrintfArgW: 3785a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org part_result = fprintf(stream_, chunks[i], wreg(pcs_r++)); 3786a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3787a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org case kPrintfArgX: 3788a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org part_result = fprintf(stream_, chunks[i], xreg(pcs_r++)); 3789a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3790a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org case kPrintfArgD: 3791a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org part_result = fprintf(stream_, chunks[i], dreg(pcs_f++)); 3792a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3793a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org default: UNREACHABLE(); 3794a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3795a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3796a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (part_result < 0) { 3797a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Handle error values. 3798a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org result = part_result; 3799a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3800a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3801a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3802a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org result += part_result; 3803a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3804a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3805a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3806a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org fprintf(stream_, "%s", clr_normal); 3807a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3808a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org#ifdef DEBUG 3809a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 3810a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org#endif 3811a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3812a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Printf returns its result in x0 (just like the C library's printf). 3813a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org set_xreg(0, result); 3814a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3815a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // The printf parameters are inlined in the code, so skip them. 3816a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org set_pc(instr->InstructionAtOffset(kPrintfLength)); 3817a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3818a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Set LR as if we'd just called a native printf function. 3819a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org set_lr(pc()); 3820a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3821a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org delete[] format; 3822a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org} 3823a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3824a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif // USE_SIMULATOR 3826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} } // namespace v8::internal 3828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3829fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#endif // V8_TARGET_ARCH_ARM64 3830