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/disasm.h" 13196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/assembler.h" 14196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/decoder-arm64-inl.h" 15196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/arm64/simulator-arm64.h" 16196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/macro-assembler.h" 17f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 18f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 { 19f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal { 20f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#if defined(USE_SIMULATOR) 22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// This macro provides a platform independent use of sscanf. The reason for 25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// SScanF not being implemented in a platform independent way through 26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// ::v8::internal::OS in the same way as SNPrintF is that the 27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Windows C Run-Time Library does not provide vsscanf. 28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define SScanF sscanf // NOLINT 29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 30f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 317010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Helpers for colors. 327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Depending on your terminal configuration, the colour names may not match the 337010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// observed colours. 347010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define COLOUR(colour_code) "\033[" colour_code "m" 357010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define BOLD(colour_code) "1;" colour_code 367010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define NORMAL "" 377010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define GREY "30" 387010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define GREEN "32" 397010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define ORANGE "33" 407010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define BLUE "34" 417010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define PURPLE "35" 427010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define INDIGO "36" 437010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#define WHITE "37" 447010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef char const * const TEXT_COLOUR; 457010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : ""; 467010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR(BOLD(GREY)) : ""; 477010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(BOLD(WHITE)) : ""; 487010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR(BOLD(BLUE)) : ""; 497010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(BOLD(INDIGO)) : ""; 507010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : ""; 517010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(BOLD(PURPLE)) : ""; 527010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_memory_value = FLAG_log_colour ? COLOUR(BOLD(GREEN)) : ""; 537010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR(GREEN) : ""; 547010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : ""; 557010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(ORANGE) : ""; 567010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgTEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : ""; 577010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 587010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 59f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// This is basically the same as PrintF, with a guard for FLAG_trace_sim. 609e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.orgvoid Simulator::TraceSim(const char* format, ...) { 61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim) { 62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org va_list arguments; 63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org va_start(arguments, format); 649e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org OS::VFPrint(stream_, format, arguments); 65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org va_end(arguments); 66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 70f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst Instruction* Simulator::kEndOfSimAddress = NULL; 71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) { 74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int width = msb - lsb + 1; 75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(is_uintn(bits, width) || is_intn(bits, width)); 76f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bits <<= lsb; 78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t mask = ((1 << width) - 1) << lsb; 79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((mask & write_ignore_mask_) == 0); 80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value_ = (value_ & ~mask) | (bits & mask); 82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 83f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 84f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) { 86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (id) { 87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NZCV: 88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask); 89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPCR: 90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask); 91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SimSystemRegister(); 94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Initialize(Isolate* isolate) { 99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (isolate->simulator_initialized()) return; 100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate->set_simulator_initialized(true); 101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::set_redirector(isolate, &RedirectExternalReference); 102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Get the active Simulator for the current thread. 106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator* Simulator::current(Isolate* isolate) { 107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate::PerIsolateThreadData* isolate_data = 108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate->FindOrAllocatePerThreadDataForThisThread(); 109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(isolate_data != NULL); 110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Simulator* sim = isolate_data->simulator(); 112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (sim == NULL) { 113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim || FLAG_log_instruction_stats || FLAG_debug_sim) { 114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sim = new Simulator(new Decoder<DispatchingDecoderVisitor>(), isolate); 115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sim = new Decoder<Simulator>(); 117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sim->isolate_ = isolate; 118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate_data->set_simulator(sim); 120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sim; 122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CallVoid(byte* entry, CallArgument* args) { 126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int index_x = 0; 127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int index_d = 0; 128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org std::vector<int64_t> stack_args(0); 130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; !args[i].IsEnd(); i++) { 131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument arg = args[i]; 132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (arg.IsX() && (index_x < 8)) { 133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(index_x++, arg.bits()); 134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (arg.IsD() && (index_d < 8)) { 135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg_bits(index_d++, arg.bits()); 136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(arg.IsD() || arg.IsX()); 138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_args.push_back(arg.bits()); 139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Process stack arguments, and make sure the stack is suitably aligned. 143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t original_stack = sp(); 144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t entry_stack = original_stack - 145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_args.size() * sizeof(stack_args[0]); 146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (OS::ActivationFrameAlignment() != 0) { 147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org entry_stack &= -OS::ActivationFrameAlignment(); 148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char * stack = reinterpret_cast<char*>(entry_stack); 150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org std::vector<int64_t>::const_iterator it; 151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (it = stack_args.begin(); it != stack_args.end(); it++) { 152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org memcpy(stack, &(*it), sizeof(*it)); 153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack += sizeof(*it); 154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(reinterpret_cast<uintptr_t>(stack) <= original_stack); 157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(entry_stack); 158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Call the generated code. 160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(entry); 161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_lr(kEndOfSimAddress); 162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CheckPCSComplianceAndRun(); 163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(original_stack); 165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::CallInt64(byte* entry, CallArgument* args) { 169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallVoid(entry, args); 170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return xreg(0); 171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::CallDouble(byte* entry, CallArgument* args) { 175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallVoid(entry, args); 176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return dreg(0); 177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::CallJS(byte* entry, 181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org byte* function_entry, 182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org JSFunction* func, 183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Object* revc, 184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t argc, 185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Object*** argv) { 186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument args[] = { 187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(function_entry), 188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(func), 189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(revc), 190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(argc), 191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(argv), 192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument::End() 193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return CallInt64(entry, args); 195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::CallRegExp(byte* entry, 198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org String* input, 199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t start_offset, 200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const byte* input_start, 201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const byte* input_end, 202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int* output, 203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t output_size, 204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Address stack_base, 205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t direct_call, 206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org void* return_address, 207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate) { 208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument args[] = { 209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(input), 210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(start_offset), 211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(input_start), 212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(input_end), 213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(output), 214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(output_size), 215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(stack_base), 216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(direct_call), 217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(return_address), 218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument(isolate), 219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CallArgument::End() 220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return CallInt64(entry, args); 222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckPCSComplianceAndRun() { 226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count()); 228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count()); 229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t saved_registers[kNumberOfCalleeSavedRegisters]; 231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters]; 232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList register_list = kCalleeSaved; 234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList fpregister_list = kCalleeSavedFP; 235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) { 237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // x31 is not a caller saved register, so no need to specify if we want 238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the stack or zero. 239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org saved_registers[i] = xreg(register_list.PopLowestIndex().code()); 240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) { 242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org saved_fpregisters[i] = 243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dreg_bits(fpregister_list.PopLowestIndex().code()); 244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t original_stack = sp(); 246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Start the simulation! 248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Run(); 249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(original_stack, sp()); 251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check that callee-saved registers have been preserved. 252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list = kCalleeSaved; 253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpregister_list = kCalleeSavedFP; 254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) { 255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code())); 256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) { 258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(saved_fpregisters[i] == 259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dreg_bits(fpregister_list.PopLowestIndex().code())); 260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Corrupt caller saved register minus the return regiters. 263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1 265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // for now . 266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list = kCallerSaved; 267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list.Remove(x0); 268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org register_list.Remove(x1); 269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // In theory d0 to d7 can be used for return values, but V8 only uses d0 271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // for now . 272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpregister_list = kCallerSavedFP; 273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpregister_list.Remove(d0); 274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue); 276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue); 277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The least significant byte of the curruption value holds the corresponding 283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// register's code. 284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CorruptRegisters(CPURegList* list, uint64_t value) { 285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (list->type() == CPURegister::kRegister) { 286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (!list->IsEmpty()) { 287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned code = list->PopLowestIndex().code(); 288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(code, value | code); 289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(list->type() == CPURegister::kFPRegister); 292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (!list->IsEmpty()) { 293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned code = list->PopLowestIndex().code(); 294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg_bits(code, value | code); 295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CorruptAllCallerSavedCPURegisters() { 301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Corrupt alters its parameter so copy them first. 302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList register_list = kCallerSaved; 303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CPURegList fpregister_list = kCallerSavedFP; 304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(®ister_list, kCallerSavedRegisterCorruptionValue); 306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue); 307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Extending the stack by 2 * 64 bits is required for stack alignment purposes. 312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguintptr_t Simulator::PushAddress(uintptr_t address) { 31397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ASSERT(sizeof(uintptr_t) < 2 * kXRegSize); 31497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org intptr_t new_sp = sp() - 2 * kXRegSize; 3159801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org uintptr_t* alignment_slot = 3169801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org reinterpret_cast<uintptr_t*>(new_sp + kXRegSize); 3179801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org memcpy(alignment_slot, &kSlotsZapValue, kPointerSize); 318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp); 3199801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org memcpy(stack_slot, &address, kPointerSize); 320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(new_sp); 321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return new_sp; 322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguintptr_t Simulator::PopAddress() { 326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org intptr_t current_sp = sp(); 327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uintptr_t address = *stack_slot; 32997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ASSERT(sizeof(uintptr_t) < 2 * kXRegSize); 33097b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_sp(current_sp + 2 * kXRegSize); 331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return address; 332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Returns the limit of the stack area to enable checking for stack overflows. 336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguintptr_t Simulator::StackLimit() const { 337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Leave a safety margin of 1024 bytes to prevent overrunning the stack when 338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // pushing values. 339fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org return reinterpret_cast<uintptr_t>(stack_limit_) + 1024; 340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator::Simulator(Decoder<DispatchingDecoderVisitor>* decoder, 344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate, FILE* stream) 345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : decoder_(decoder), 346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_debugger_input_(NULL), 347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org log_parameters_(NO_PARAM), 348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate_(isolate) { 349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Setup the decoder. 350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org decoder_->AppendVisitor(this); 351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Init(stream); 353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim) { 355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org decoder_->InsertVisitorBefore(print_disasm_, this); 356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org log_parameters_ = LOG_ALL; 357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_log_instruction_stats) { 360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org instrument_ = new Instrument(FLAG_log_instruction_file, 361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FLAG_log_instruction_period); 362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org decoder_->AppendVisitor(instrument_); 363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator::Simulator() 368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : decoder_(NULL), 369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_debugger_input_(NULL), 370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org log_parameters_(NO_PARAM), 371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate_(NULL) { 3728f8fe81d7a9cced7a0d30e56124c0428d1a6d229machenbach@chromium.org Init(stdout); 373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CHECK(!FLAG_trace_sim && !FLAG_log_instruction_stats); 374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Init(FILE* stream) { 378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ResetState(); 379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Allocate and setup the simulator stack. 381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_size_ = (FLAG_sim_stack_size * KB) + (2 * stack_protection_size_); 382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_ = new byte[stack_size_]; 383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack_limit_ = stack_ + stack_protection_size_; 384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org byte* tos = stack_ + stack_size_ - stack_protection_size_; 385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The stack pointer must be 16 bytes aligned. 386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sp(reinterpret_cast<int64_t>(tos) & ~0xfUL); 387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stream_ = stream; 389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org print_disasm_ = new PrintDisassembler(stream_); 390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The debugger needs to disassemble code without the simulator executing an 392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // instruction, so we create a dedicated decoder. 393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org disassembler_decoder_ = new Decoder<DispatchingDecoderVisitor>(); 394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org disassembler_decoder_->AppendVisitor(print_disasm_); 395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::ResetState() { 399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reset the system registers. 400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv_ = SimSystemRegister::DefaultValueFor(NZCV); 401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpcr_ = SimSystemRegister::DefaultValueFor(FPCR); 402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reset registers to 0. 404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_ = NULL; 405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfRegisters; i++) { 406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(i, 0xbadbeef); 407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP. 410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg_bits(i, 0x7ff000007f800001UL); 411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Returning to address 0 exits the Simulator. 413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_lr(kEndOfSimAddress); 414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Reset debug helpers. 416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.empty(); 417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break_on_next_= false; 418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgSimulator::~Simulator() { 422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete[] stack_; 423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_log_instruction_stats) { 424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete instrument_; 425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete disassembler_decoder_; 427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete print_disasm_; 428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org DeleteArray(last_debugger_input_); 429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org delete decoder_; 430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Run() { 434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_modified_ = false; 435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (pc_ != kEndOfSimAddress) { 436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExecuteInstruction(); 437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::RunFrom(Instruction* start) { 442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(start); 443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Run(); 444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// When the generated code calls an external reference we need to catch that in 448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// the simulator. The external reference will be a function compiled for the 449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// host architecture. We need to call that function instead of trying to 450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// execute it with the simulator. We do that by redirecting the external 451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// reference to a svc (Supervisor Call) instruction that is handled by 452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// the simulator. We write the original destination of the jump just at a known 453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// offset from the svc instruction so the simulator knows what to call. 454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgclass Redirection { 455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org public: 456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection(void* external_function, ExternalReference::Type type) 457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : external_function_(external_function), 458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org type_(type), 459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org next_(NULL) { 460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org redirect_call_.SetInstructionBits( 461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org HLT | Assembler::ImmException(kImmExceptionIsRedirectedCall)); 462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate = Isolate::Current(); 463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org next_ = isolate->simulator_redirection(); 464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(all): Simulator flush I cache 465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org isolate->set_simulator_redirection(this); 466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org void* address_of_redirect_call() { 469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<void*>(&redirect_call_); 470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 4727010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org template <typename T> 4737010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org T external_function() { return reinterpret_cast<T>(external_function_); } 4747010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type() { return type_; } 476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static Redirection* Get(void* external_function, 478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type) { 479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Isolate* isolate = Isolate::Current(); 480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* current = isolate->simulator_redirection(); 481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (; current != NULL; current = current->next_) { 482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (current->external_function_ == external_function) { 483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT_EQ(current->type(), type); 484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return current; 485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return new Redirection(external_function, type); 488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static Redirection* FromHltInstruction(Instruction* redirect_call) { 491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* addr_of_hlt = reinterpret_cast<char*>(redirect_call); 492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* addr_of_redirection = 493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org addr_of_hlt - OFFSET_OF(Redirection, redirect_call_); 494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<Redirection*>(addr_of_redirection); 495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static void* ReverseRedirection(int64_t reg) { 498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* redirection = 499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FromHltInstruction(reinterpret_cast<Instruction*>(reg)); 5007010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org return redirection->external_function<void*>(); 501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org private: 504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org void* external_function_; 505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instruction redirect_call_; 506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type_; 507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* next_; 508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}; 509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 5117010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Calls into the V8 runtime are based on this very simple interface. 5127010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// Note: To be able to return two values from some calls the code in runtime.cc 5137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// uses the ObjectPair structure. 5147010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// The simulator assumes all runtime calls return two 64-bits values. If they 5157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// don't, register x1 is clobbered. This is fine because x1 is caller-saved. 5167010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgstruct ObjectPair { 5177010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t res0; 5187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t res1; 5197010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org}; 5207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, 5237010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg1, 5247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg2, 5257010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg3, 5267010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg4, 5277010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg5, 5287010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg6, 5297010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t arg7); 5307010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5317010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2); 5327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2); 5337010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPCall)(double arg1); 5347010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2); 5357010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5367010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// This signature supports direct call in to API function native callback 5377010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// (refer to InvocationCallback in v8.h). 5387010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); 5397010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); 5407010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5417010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org// This signature supports direct call to accessor getter callback. 5427010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); 5437010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgtypedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1, 5447010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org void* arg2); 5457010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5467010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.orgvoid Simulator::DoRuntimeCall(Instruction* instr) { 5477010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org Redirection* redirection = Redirection::FromHltInstruction(instr); 5487010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5497010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // The called C code might itself call simulated code, so any 5507010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // caller-saved registers (including lr) could still be clobbered by a 5517010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // redirected call. 5527010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org Instruction* return_address = lr(); 5537010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5547010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t external = redirection->external_function<int64_t>(); 5557010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5567010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Call to host function at %p\n", 5577010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org redirection->external_function<void*>()); 5587010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5597010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // SP must be 16-byte-aligned at the call interface. 5607010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org bool stack_alignment_exception = ((sp() & 0xf) != 0); 5617010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org if (stack_alignment_exception) { 5627010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp()); 5637010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org FATAL("ALIGNMENT EXCEPTION"); 5647010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 5657010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5667010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org switch (redirection->type()) { 5677010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org default: 5687010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: Unknown.\n"); 5697010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org UNREACHABLE(); 5707010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 5717010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5727010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_CALL: { 573a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org // Object* f(v8::internal::Arguments). 5747010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_CALL\n"); 5757010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeCall target = 5767010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCall>(external); 5777010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 5787010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // We don't know how many arguments are being passed, but we can 5797010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // pass 8 without touching the stack. They will be ignored by the 5807010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // host function if they aren't used. 5817010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: " 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 "0x%016" PRIx64 ", 0x%016" PRIx64, 5867010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(0), xreg(1), xreg(2), xreg(3), 5877010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(4), xreg(5), xreg(6), xreg(7)); 5887010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3), 5897010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(4), xreg(5), xreg(6), xreg(7)); 5907010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n", 5917010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org result.res0, result.res1); 5927010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 5937010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 5947010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 5957010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_xreg(0, result.res0); 5967010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_xreg(1, result.res1); 5977010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 5987010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 5997010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6007010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::DIRECT_API_CALL: { 6017010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(v8::FunctionCallbackInfo&) 6027010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: DIRECT_API_CALL\n"); 6037010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeDirectApiCall target = 6047010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); 6057010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0)); 6067010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0)); 6077010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 6087010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6097010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6107010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6117010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6127010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6147010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_COMPARE_CALL: { 6157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // int f(double, double) 6167010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_COMPARE_CALL\n"); 6177010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeCompareCall target = 6187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeCompareCall>(external); 6197010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); 6207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org int64_t result = target(dreg(0), dreg(1)); 6217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %" PRId64 "\n", result); 6227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6237010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6257010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_xreg(0, result); 6267010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6277010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6287010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6297010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_FP_CALL: { 6307010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // double f(double) 6317010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_FP_CALL\n"); 6327010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeFPCall target = 6337010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPCall>(external); 6347010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Argument: %f\n", dreg(0)); 6357010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org double result = target(dreg(0)); 6367010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %f\n", result); 6377010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6387010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6397010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6407010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_dreg(0, result); 6417010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6427010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6437010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6447010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_FP_FP_CALL: { 6457010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // double f(double, double) 6467010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_FP_FP_CALL\n"); 6477010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeFPFPCall target = 6487010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPFPCall>(external); 6497010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); 6507010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org double result = target(dreg(0), dreg(1)); 6517010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %f\n", result); 6527010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6537010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6547010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6557010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_dreg(0, result); 6567010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6577010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6587010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6597010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::BUILTIN_FP_INT_CALL: { 6607010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // double f(double, int) 6617010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: BUILTIN_FP_INT_CALL\n"); 6627010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeFPIntCall target = 6637010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeFPIntCall>(external); 6647010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0)); 6657010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org double result = target(dreg(0), wreg(0)); 6667010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Returned: %f\n", result); 6677010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6687010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6697010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6707010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_dreg(0, result); 6717010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6727010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6737010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6747010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::DIRECT_GETTER_CALL: { 6757010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(Local<String> property, PropertyCallbackInfo& info) 6767010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: DIRECT_GETTER_CALL\n"); 6777010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeDirectGetterCall target = 6787010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); 6797010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n", 6807010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(0), xreg(1)); 6817010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0), xreg(1)); 6827010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 6837010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6847010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 6857010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 6867010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 6877010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 6887010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 6897010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::PROFILING_API_CALL: { 6907010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback) 6917010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: PROFILING_API_CALL\n"); 6927010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeProfilingApiCall target = 6937010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); 6947010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org void* arg1 = Redirection::ReverseRedirection(xreg(1)); 6957010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1); 6967010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0), arg1); 6977010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 6987010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 6997010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 7007010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 7017010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 7027010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 7037010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 7047010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org case ExternalReference::PROFILING_GETTER_CALL: { 7057010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // void f(Local<String> property, PropertyCallbackInfo& info, 7067010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org // AccessorGetterCallback callback) 7077010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Type: PROFILING_GETTER_CALL\n"); 7087010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org SimulatorRuntimeProfilingGetterCall target = 7097010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org reinterpret_cast<SimulatorRuntimeProfilingGetterCall>( 7107010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org external); 7117010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org void* arg2 = Redirection::ReverseRedirection(xreg(2)); 7127010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n", 7137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org xreg(0), xreg(1), arg2); 7147010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org target(xreg(0), xreg(1), arg2); 7157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org TraceSim("No return value."); 7167010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#ifdef DEBUG 7177010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 7187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org#endif 7197010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org break; 7207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 7217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org } 7227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 7237010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_lr(return_address); 7247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org set_pc(return_address); 7257010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org} 7267010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 7277010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org 728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid* Simulator::RedirectExternalReference(void* external_function, 729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExternalReference::Type type) { 730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Redirection* redirection = Redirection::Get(external_function, type); 731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return redirection->address_of_redirect_call(); 732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 735f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::xreg_names[] = { 736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", 737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", 738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"ip0", "ip1", "x18", "x19", "x20", "x21", "x22", "x23", 739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"x24", "x25", "x26", "cp", "jssp", "fp", "lr", "xzr", "csp"}; 740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::wreg_names[] = { 742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"w0", "w1", "w2", "w3", "w4", "w5", "w6", "w7", 743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"w8", "w9", "w10", "w11", "w12", "w13", "w14", "w15", 744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"w16", "w17", "w18", "w19", "w20", "w21", "w22", "w23", 745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"w24", "w25", "w26", "wcp", "wjssp", "wfp", "wlr", "wzr", "wcsp"}; 746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::sreg_names[] = { 748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", 749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", 750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", 751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31"}; 752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::dreg_names[] = { 754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", 756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", 757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"}; 758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::vreg_names[] = { 760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; 764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 766f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) { 767f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(code < kNumberOfRegisters); 768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the code represents the stack pointer, index the name after zr. 769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { 770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code = kZeroRegCode + 1; 771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return wreg_names[code]; 773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { 777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(code < kNumberOfRegisters); 778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the code represents the stack pointer, index the name after zr. 779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { 780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code = kZeroRegCode + 1; 781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return xreg_names[code]; 783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::SRegNameForCode(unsigned code) { 787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(code < kNumberOfFPRegisters); 788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sreg_names[code]; 789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::DRegNameForCode(unsigned code) { 793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(code < kNumberOfFPRegisters); 794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return dreg_names[code]; 795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgconst char* Simulator::VRegNameForCode(unsigned code) { 799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(code < kNumberOfFPRegisters); 800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return vreg_names[code]; 801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint Simulator::CodeFromName(const char* name) { 805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfRegisters; i++) { 806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp(xreg_names[i], name) == 0) || 807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(wreg_names[i], name) == 0)) { 808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return i; 809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp(vreg_names[i], name) == 0) || 813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(dreg_names[i], name) == 0) || 814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(sreg_names[i], name) == 0)) { 815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return i; 816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) { 819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kSPRegInternalCode; 820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -1; 822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Helpers --------------------------------------------------------------------- 8261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 8271845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgT Simulator::AddWithCarry(bool set_flags, 8281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T src1, 8291845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T src2, 8301845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T carry_in) { 8311845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((carry_in == 0) || (carry_in == 1)); 833f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T signed_sum = src1 + src2 + carry_in; 8351845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = signed_sum; 836f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8379801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org bool N, Z, C, V; 838f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // Compute the C flag 8401845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT u1 = static_cast<unsignedT>(src1); 8411845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT u2 = static_cast<unsignedT>(src2); 8421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT urest = std::numeric_limits<unsignedT>::max() - u1; 8431845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1)))); 844f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // Overflow iff the sign bit is the same for the two inputs and different 8461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org // for the result. 8471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); 848f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org N = CalcNFlag(result); 850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Z = CalcZFlag(result); 851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (set_flags) { 853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetN(N); 854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetZ(Z); 855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetC(C); 856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetV(V); 857f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 858f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result; 859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 8621845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 8631845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::AddSubWithCarry(Instruction* instr) { 8641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op2 = reg<T>(instr->Rm()); 8651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T new_val; 8661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) { 8681845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2 = ~op2; 8691845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 8701845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8711845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org new_val = AddWithCarry<T>(instr->FlagsUpdate(), 8721845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org reg<T>(instr->Rn()), 8731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2, 8741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org nzcv().C()); 8751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8761845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), new_val); 8771845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 8781845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 8791845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 8801845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgT Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) { 8811845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 8821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (amount == 0) { 884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return value; 885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 8861845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (shift_type) { 888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSL: 8891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return value << amount; 890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSR: 8911845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return static_cast<unsignedT>(value) >> amount; 8921845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case ASR: 8931845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return value >> amount; 8941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case ROR: 8951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return (static_cast<unsignedT>(value) >> amount) | 8961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ((value & ((1L << amount) - 1L)) << 8971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org (sizeof(unsignedT) * 8 - amount)); 898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0; 901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 9051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 9061845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgT Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) { 9071845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8; 9081845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8; 9091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8; 9101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (extend_type) { 912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTB: 913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value &= kByteMask; 914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTH: 916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value &= kHalfWordMask; 917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTW: 919f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value &= kWordMask; 920f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 921f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTB: 9221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value = (value << kSignExtendBShift) >> kSignExtendBShift; 923f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 924f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTH: 9251845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value = (value << kSignExtendHShift) >> kSignExtendHShift; 926f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 927f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTW: 9281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org value = (value << kSignExtendWShift) >> kSignExtendWShift; 929f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 930f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UXTX: 931f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SXTX: 932f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 933f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 934f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 935f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 9361845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org return value << left_shift; 9371845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 9381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 9391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 9401845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 9411845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::Extract(Instruction* instr) { 9421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned lsb = instr->ImmS(); 9431845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op2 = reg<T>(instr->Rm()); 9441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = op2; 9451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 9461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (lsb) { 9471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op1 = reg<T>(instr->Rn()); 9481845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb)); 9491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 9501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result); 951f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 952f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 953f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 9546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate<> double Simulator::FPDefaultNaN<double>() const { 9556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return kFP64DefaultNaN; 9566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 9576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 9586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 9596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate<> float Simulator::FPDefaultNaN<float>() const { 9606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return kFP32DefaultNaN; 9616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 9626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 9636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 964f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::FPCompare(double val0, double val1) { 965f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 966f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 967f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // TODO(jbramley): This assumes that the C++ implementation handles 968f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // comparisons in the way that we expect (as per AssertSupportedFPCR()). 969f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) { 970f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPUnorderedFlag); 971f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (val0 < val1) { 972f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPLessThanFlag); 973f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (val0 > val1) { 974f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPGreaterThanFlag); 975f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (val0 == val1) { 976f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetRawValue(FPEqualFlag); 977f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 978f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 979f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 980f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 981f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::SetBreakpoint(Instruction* location) { 984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < breakpoints_.size(); i++) { 985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (breakpoints_.at(i).location == location) { 9869e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 9879e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org "Existing breakpoint at %p was %s\n", 988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(location), 989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled ? "disabled" : "enabled"); 990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled; 991f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return; 992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 993f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Breakpoint new_breakpoint = {location, true}; 995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.push_back(new_breakpoint); 9969e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 9979e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org "Set a breakpoint at %p\n", reinterpret_cast<void*>(location)); 998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::ListBreakpoints() { 10029e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "Breakpoints:\n"); 1003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < breakpoints_.size(); i++) { 10049e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%p : %s\n", 1005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(breakpoints_.at(i).location), 1006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled ? "enabled" : "disabled"); 1007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1009f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckBreakpoints() { 1012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool hit_a_breakpoint = false; 1013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < breakpoints_.size(); i++) { 1014f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((breakpoints_.at(i).location == pc_) && 1015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled) { 1016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org hit_a_breakpoint = true; 1017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Disable this breakpoint. 1018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org breakpoints_.at(i).enabled = false; 1019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (hit_a_breakpoint) { 10229e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "Hit and disabled a breakpoint at %p.\n", 1023f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(pc_)); 1024f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Debug(); 1025f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1026f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1027f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckBreakNext() { 1030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the current instruction is a BL, insert a breakpoint just after it. 1031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (break_on_next_ && pc_->IsBranchAndLinkToRegister()) { 10324452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org SetBreakpoint(pc_->following()); 1033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break_on_next_ = false; 1034f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1035f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1036f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1037f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1038f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { 1039f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instruction* end = start->InstructionAtOffset(count * kInstructionSize); 10404452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org for (Instruction* pc = start; pc < end; pc = pc->following()) { 1041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org disassembler_decoder_->Decode(pc); 1042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1043f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1044f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1045f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1046f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintSystemRegisters(bool print_all) { 1047f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static bool first_run = true; 1048f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1049f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static SimSystemRegister last_nzcv; 1050f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) { 1051f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n", 1052f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_flag_name, 1053f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_flag_value, 10549801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(), 1055f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 1056f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_nzcv = nzcv(); 1058f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1059f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static SimSystemRegister last_fpcr; 1060f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (print_all || first_run || (last_fpcr.RawValue() != fpcr().RawValue())) { 1061f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const char * rmode[] = { 1062f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "0b00 (Round to Nearest)", 1063f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "0b01 (Round towards Plus Infinity)", 1064f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "0b10 (Round towards Minus Infinity)", 1065f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "0b11 (Round towards Zero)" 1066f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org }; 1067f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(fpcr().RMode() <= (sizeof(rmode) / sizeof(rmode[0]))); 1068f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", 1069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_flag_name, 1070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_flag_value, 1071f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()], 1072f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 1073f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1074f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_fpcr = fpcr(); 1075f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1076f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org first_run = false; 1077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1078f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1079f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1080f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintRegisters(bool print_all_regs) { 1081f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static bool first_run = true; 1082f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static int64_t last_regs[kNumberOfRegisters]; 1083f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1084f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfRegisters; i++) { 1085f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (print_all_regs || first_run || 1086f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (last_regs[i] != xreg(i, Reg31IsStackPointer))) { 1087f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, 1088f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "# %s%4s:%s 0x%016" PRIx64 "%s\n", 1089f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, 1090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org XRegNameForCode(i, Reg31IsStackPointer), 1091f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_value, 1092f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org xreg(i, Reg31IsStackPointer), 1093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 1094f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1095f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Cache the new register value so the next run can detect any changes. 1096f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_regs[i] = xreg(i, Reg31IsStackPointer); 1097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1098f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org first_run = false; 1099f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintFPRegisters(bool print_all_regs) { 1103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static bool first_run = true; 1104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static uint64_t last_regs[kNumberOfFPRegisters]; 1105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Print as many rows of registers as necessary, keeping each individual 1107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // register in the same column each time (to make it easy to visually scan 1108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // for changes). 1109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 1110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) { 1111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, 1112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n", 11137010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org clr_fpreg_name, 1114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org VRegNameForCode(i), 11157010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org clr_fpreg_value, 1116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dreg_bits(i), 1117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal, 11187010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org clr_fpreg_name, 1119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org DRegNameForCode(i), 11207010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org clr_fpreg_value, 1121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org dreg(i), 11227010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org clr_fpreg_name, 1123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org SRegNameForCode(i), 11247010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org clr_fpreg_value, 1125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org sreg(i), 1126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 1127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Cache the new register value so the next run can detect any changes. 1129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org last_regs[i] = dreg_bits(i); 1130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org first_run = false; 1132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintProcessorState() { 1136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintSystemRegisters(); 1137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintRegisters(); 1138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintFPRegisters(); 1139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::PrintWrite(uint8_t* address, 1143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t value, 1144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned num_bytes) { 1145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The template is "# value -> address". The template is not directly used 1146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // in the printf since compilers tend to struggle with the parametrized 1147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // width (%0*). 1148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const char* format = "# %s0x%0*" PRIx64 "%s -> %s0x%016" PRIx64 "%s\n"; 1149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, 1150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org format, 1151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_memory_value, 1152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org num_bytes * 2, // The width in hexa characters. 1153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value, 1154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal, 1155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_memory_address, 1156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org address, 1157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 1158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Visitors--------------------------------------------------------------------- 1162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnimplemented(Instruction* instr) { 1164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", 1165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(instr), instr->InstructionBits()); 1166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnallocated(Instruction* instr) { 1171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "Unallocated instruction at %p: 0x%08" PRIx32 "\n", 1172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(instr), instr->InstructionBits()); 1173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitPCRelAddressing(Instruction* instr) { 1178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(PCRelAddressingMask)) { 1179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADR: 1180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_reg(instr->Rd(), instr->ImmPCOffsetTarget()); 1181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADRP: // Not implemented in the assembler. 1183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 1187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnconditionalBranch(Instruction* instr) { 1193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(UnconditionalBranchMask)) { 1194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BL: 11954452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org set_lr(instr->following()); 1196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Fall through. 1197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case B: 1198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 1202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalBranch(Instruction* instr) { 1207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(instr->Mask(ConditionalBranchMask) == B_cond); 1208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->ConditionBranch()))) { 1209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) { 1215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instruction* target = reg<Instruction*>(instr->Rn()); 1216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(UnconditionalBranchToRegisterMask)) { 1217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BLR: { 12184452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org set_lr(instr->following()); 1219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->Rn() == 31) { 1220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // BLR XZR is used as a guard for the constant pool. We should never hit 1221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // this, but if we do trap to allow debugging. 1222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Debug(); 1223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Fall through. 1225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BR: 1227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case RET: set_pc(target); break; 1228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitTestBranch(Instruction* instr) { 1234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) | 1235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org instr->ImmTestBranchBit40(); 1236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0); 1237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(TestBranchMask)) { 1238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TBZ: break; 1239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TBNZ: take_branch = !take_branch; break; 1240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (take_branch) { 1243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitCompareBranch(Instruction* instr) { 1249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt = instr->Rt(); 1250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool take_branch = false; 1251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(CompareBranchMask)) { 1252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBZ_w: take_branch = (wreg(rt) == 0); break; 1253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBZ_x: take_branch = (xreg(rt) == 0); break; 1254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBNZ_w: take_branch = (wreg(rt) != 0); break; 1255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CBNZ_x: take_branch = (xreg(rt) != 0); break; 1256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (take_branch) { 1259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_pc(instr->ImmPCOffsetTarget()); 1260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 12641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 12651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::AddSubHelper(Instruction* instr, T op2) { 1266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool set_flags = instr->FlagsUpdate(); 12671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T new_val = 0; 1268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instr operation = instr->Mask(AddSubOpMask); 1269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (operation) { 1271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADD: 1272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ADDS: { 12731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org new_val = AddWithCarry<T>(set_flags, 12741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org reg<T>(instr->Rn(), instr->RnMode()), 12751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2); 1276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SUB: 1279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SUBS: { 12801845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org new_val = AddWithCarry<T>(set_flags, 12811845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org reg<T>(instr->Rn(), instr->RnMode()), 12821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ~op2, 12831845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 1); 1284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 1287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 12891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), new_val, instr->RdMode()); 1290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubShifted(Instruction* instr) { 12941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Shift shift_type = static_cast<Shift>(instr->ShiftDP()); 12951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned shift_amount = instr->ImmDPShift(); 12961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 12971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 12981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); 12991845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 13001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13011845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); 13021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 13031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubImmediate(Instruction* instr) { 1308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0); 13091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper<int64_t>(instr, op2); 13111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper<int32_t>(instr, op2); 13131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubExtended(Instruction* instr) { 13181845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Extend ext = static_cast<Extend>(instr->ExtendMode()); 13191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned left_shift = instr->ImmExtendShift(); 13201845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13211845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift); 13221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 13231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift); 13251845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubHelper(instr, op2); 13261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitAddSubWithCarry(Instruction* instr) { 13311845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13321845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubWithCarry<int64_t>(instr); 13331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddSubWithCarry<int32_t>(instr); 1335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLogicalShifted(Instruction* instr) { 1340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Shift shift_type = static_cast<Shift>(instr->ShiftDP()); 1341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned shift_amount = instr->ImmDPShift(); 13421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 13431845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); 13451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; 13461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int64_t>(instr, op2); 13471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13481845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); 13491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; 13501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int32_t>(instr, op2); 1351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLogicalImmediate(Instruction* instr) { 13561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13571845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int64_t>(instr, instr->ImmLogical()); 13581845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13591845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org LogicalHelper<int32_t>(instr, instr->ImmLogical()); 13601845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 13641845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 13651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::LogicalHelper(Instruction* instr, T op2) { 13661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op1 = reg<T>(instr->Rn()); 13671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = 0; 1368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool update_flags = false; 1369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Switch on the logical operation, stripping out the NOT bit, as it has a 1371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // different meaning for logical immediate instructions. 1372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(LogicalOpMask & ~NOT)) { 1373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ANDS: update_flags = true; // Fall through. 1374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case AND: result = op1 & op2; break; 1375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ORR: result = op1 | op2; break; 1376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case EOR: result = op1 ^ op2; break; 1377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 1379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (update_flags) { 13821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org nzcv().SetN(CalcNFlag(result)); 1383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetZ(CalcZFlag(result)); 1384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetC(0); 1385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetV(0); 1386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 13881845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result, instr->RdMode()); 1389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalCompareRegister(Instruction* instr) { 13931845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 13941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper(instr, xreg(instr->Rm())); 13951845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 13961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper(instr, wreg(instr->Rm())); 13971845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalCompareImmediate(Instruction* instr) { 14021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 14031845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp()); 14041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 14051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp()); 14061845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 14101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate<typename T> 14111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::ConditionalCompareHelper(Instruction* instr, T op2) { 14121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T op1 = reg<T>(instr->Rn()); 1413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 1415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition passes, set the status flags to the result of comparing 1416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the operands. 1417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->Mask(ConditionalCompareMask) == CCMP) { 14181845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddWithCarry<T>(true, op1, ~op2, 1); 1419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 1420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(instr->Mask(ConditionalCompareMask) == CCMN); 14211845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org AddWithCarry<T>(true, op1, op2, 0); 1422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 1424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition fails, set the status flags to the nzcv immediate. 1425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetFlags(instr->Nzcv()); 1426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { 1431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int offset = instr->ImmLSUnsigned() << instr->SizeLS(); 1432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, offset, Offset); 1433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStoreUnscaledOffset(Instruction* instr) { 1437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, instr->ImmLS(), Offset); 1438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePreIndex(Instruction* instr) { 1442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, instr->ImmLS(), PreIndex); 1443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePostIndex(Instruction* instr) { 1447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, instr->ImmLS(), PostIndex); 1448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) { 1452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Extend ext = static_cast<Extend>(instr->ExtendMode()); 1453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); 1454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS(); 1455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 14561845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); 1457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreHelper(instr, offset, Offset); 1458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::LoadStoreHelper(Instruction* instr, 1462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t offset, 1463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned srcdst = instr->Rt(); 1465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned addr_reg = instr->Rn(); 1466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); 1467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int num_bytes = 1 << instr->SizeLS(); 1468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t* stack = NULL; 1469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for stores before the store. On a CPU the writeback 1471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and the store are atomic, but when running on the simulator it is possible 1472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // to be interrupted in between. The simulator is not thread safe and V8 does 1473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not require it to be to run JavaScript therefore the profiler may sample 1474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the "simulated" CPU in the middle of load/store with writeback. The code 1475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // below ensures that push operations are safe even when interrupted: the 1476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack pointer will be decremented before adding an element to the stack. 1477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsStore()) { 1478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For store the address post writeback is used to check access below the 1481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 1482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack = reinterpret_cast<uint8_t*>(sp()); 1483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); 1486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (op) { 1487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRB_w: 1488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRH_w: 1489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_w: 1490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break; 1491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STRB_w: 1492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STRH_w: 1493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STR_w: 1494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break; 1495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRSB_w: { 14961845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_wreg(srcdst, ExtendValue<int32_t>(MemoryRead8(address), SXTB)); 1497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRSB_x: { 15001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead8(address), SXTB)); 1501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRSH_w: { 15041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_wreg(srcdst, ExtendValue<int32_t>(MemoryRead16(address), SXTH)); 1505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRSH_x: { 15081845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead16(address), SXTH)); 1509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDRSW_x: { 15121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead32(address), SXTW)); 1513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break; 1516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break; 1517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break; 1518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break; 1519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1522f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for loads after the load to ensure safe pop 1523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // operation even when interrupted in the middle of it. The stack pointer 1524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // is only updated after the load so pop(fp) will never break the invariant 1525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sp <= fp expected while walking the stack in the sampler. 1526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsLoad()) { 1527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For loads the address pre writeback is used to check access below the 1528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 1529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack = reinterpret_cast<uint8_t*>(sp()); 1530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Accesses below the stack pointer (but above the platform stack limit) are 1535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not allowed in the ABI. 1536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CheckMemoryAccess(address, stack); 1537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairOffset(Instruction* instr) { 1541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, Offset); 1542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairPreIndex(Instruction* instr) { 1546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, PreIndex); 1547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairPostIndex(Instruction* instr) { 1551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, PostIndex); 1552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadStorePairNonTemporal(Instruction* instr) { 1556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairHelper(instr, Offset); 1557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::LoadStorePairHelper(Instruction* instr, 1561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt = instr->Rt(); 1563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt2 = instr->Rt2(); 1564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned addr_reg = instr->Rn(); 1565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int offset = instr->ImmLSPair() << instr->SizeLSPair(); 1566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); 1567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t* stack = NULL; 1568f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1569f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for stores before the store. On a CPU the writeback 1570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // and the store are atomic, but when running on the simulator it is possible 1571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // to be interrupted in between. The simulator is not thread safe and V8 does 1572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not require it to be to run JavaScript therefore the profiler may sample 1573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the "simulated" CPU in the middle of load/store with writeback. The code 1574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // below ensures that push operations are safe even when interrupted: the 1575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack pointer will be decremented before adding an element to the stack. 1576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsStore()) { 1577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For store the address post writeback is used to check access below the 1580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 1581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack = reinterpret_cast<uint8_t*>(sp()); 1582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStorePairOp op = 1585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); 1586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 'rt' and 'rt2' can only be aliased for stores. 1588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2)); 1589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (op) { 1591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_w: { 1592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(rt, MemoryRead32(address)); 159397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_wreg(rt2, MemoryRead32(address + kWRegSize)); 1594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_s: { 1597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(rt, MemoryReadFP32(address)); 159897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_sreg(rt2, MemoryReadFP32(address + kSRegSize)); 1599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_x: { 1602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(rt, MemoryRead64(address)); 160397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_xreg(rt2, MemoryRead64(address + kXRegSize)); 1604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDP_d: { 1607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(rt, MemoryReadFP64(address)); 160897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_dreg(rt2, MemoryReadFP64(address + kDRegSize)); 1609f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDPSW_x: { 16121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(rt, ExtendValue<int64_t>(MemoryRead32(address), SXTW)); 16131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(rt2, ExtendValue<int64_t>( 161497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org MemoryRead32(address + kWRegSize), SXTW)); 1615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_w: { 1618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWrite32(address, wreg(rt)); 161997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org MemoryWrite32(address + kWRegSize, wreg(rt2)); 1620f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1622f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_s: { 1623f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWriteFP32(address, sreg(rt)); 162497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org MemoryWriteFP32(address + kSRegSize, sreg(rt2)); 1625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1626f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_x: { 1628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWrite64(address, xreg(rt)); 162997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org MemoryWrite64(address + kXRegSize, xreg(rt2)); 1630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case STP_d: { 1633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWriteFP64(address, dreg(rt)); 163497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org MemoryWriteFP64(address + kDRegSize, dreg(rt2)); 1635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1636f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 1638f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1639f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle the writeback for loads after the load to ensure safe pop 1641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // operation even when interrupted in the middle of it. The stack pointer 1642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // is only updated after the load so pop(fp) will never break the invariant 1643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sp <= fp expected while walking the stack in the sampler. 1644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->IsLoad()) { 1645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For loads the address pre writeback is used to check access below the 1646f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack. 1647f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org stack = reinterpret_cast<uint8_t*>(sp()); 1648f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1649f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LoadStoreWriteBack(addr_reg, offset, addrmode); 1650f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1651f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1652f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Accesses below the stack pointer (but above the platform stack limit) are 1653f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // not allowed in the ABI. 1654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org CheckMemoryAccess(address, stack); 1655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitLoadLiteral(Instruction* instr) { 1659f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t* address = instr->LiteralAddress(); 1660f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned rt = instr->Rt(); 1661f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1662f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(LoadLiteralMask)) { 1663f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_w_lit: set_wreg(rt, MemoryRead32(address)); break; 1664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_x_lit: set_xreg(rt, MemoryRead64(address)); break; 1665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_s_lit: set_sreg(rt, MemoryReadFP32(address)); break; 1666f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LDR_d_lit: set_dreg(rt, MemoryReadFP64(address)); break; 1667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 1668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint8_t* Simulator::LoadStoreAddress(unsigned addr_reg, 1673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t offset, 1674f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; 1676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t address = xreg(addr_reg, Reg31IsStackPointer); 1677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((addr_reg == kSPRegCode) && ((address % 16) != 0)) { 1678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // When the base register is SP the stack pointer is required to be 1679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // quadword aligned prior to the address calculation and write-backs. 1680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Misalignment will cause a stack alignment fault. 1681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FATAL("ALIGNMENT EXCEPTION"); 1682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((addrmode == Offset) || (addrmode == PreIndex)) { 1685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org address += offset; 1686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return reinterpret_cast<uint8_t*>(address); 1689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::LoadStoreWriteBack(unsigned addr_reg, 1693f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t offset, 1694f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AddrMode addrmode) { 1695f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((addrmode == PreIndex) || (addrmode == PostIndex)) { 1696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(offset != 0); 1697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t address = xreg(addr_reg, Reg31IsStackPointer); 1698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_reg(addr_reg, address + offset, Reg31IsStackPointer); 1699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1700f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::CheckMemoryAccess(uint8_t* address, uint8_t* stack) { 1704f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((address >= stack_limit_) && (address < stack)) { 1705f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "ACCESS BELOW STACK POINTER:\n"); 1706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, " sp is here: 0x%16p\n", stack); 1707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, " access was here: 0x%16p\n", address); 1708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, " stack limit is here: 0x%16p\n", stack_limit_); 1709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "\n"); 1710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FATAL("ACCESS BELOW STACK POINTER"); 1711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::MemoryRead(uint8_t* address, unsigned num_bytes) { 1716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(address != NULL); 1717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t))); 1718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t read = 0; 1719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org memcpy(&read, address, num_bytes); 1720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return read; 1721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint8_t Simulator::MemoryRead8(uint8_t* address) { 1725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return MemoryRead(address, sizeof(uint8_t)); 1726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint16_t Simulator::MemoryRead16(uint8_t* address) { 1730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return MemoryRead(address, sizeof(uint16_t)); 1731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint32_t Simulator::MemoryRead32(uint8_t* address) { 1735f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return MemoryRead(address, sizeof(uint32_t)); 1736f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::MemoryReadFP32(uint8_t* address) { 1740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_float(MemoryRead32(address)); 1741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::MemoryRead64(uint8_t* address) { 1745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return MemoryRead(address, sizeof(uint64_t)); 1746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::MemoryReadFP64(uint8_t* address) { 1750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_double(MemoryRead64(address)); 1751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::MemoryWrite(uint8_t* address, 1755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t value, 1756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned num_bytes) { 1757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(address != NULL); 1758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((num_bytes > 0) && (num_bytes <= sizeof(uint64_t))); 1759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org LogWrite(address, value, num_bytes); 1761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org memcpy(address, &value, num_bytes); 1762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::MemoryWrite32(uint8_t* address, uint32_t value) { 1766f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWrite(address, value, sizeof(uint32_t)); 1767f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::MemoryWriteFP32(uint8_t* address, float value) { 1771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWrite32(address, float_to_rawbits(value)); 1772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::MemoryWrite64(uint8_t* address, uint64_t value) { 1776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWrite(address, value, sizeof(uint64_t)); 1777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::MemoryWriteFP64(uint8_t* address, double value) { 1781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MemoryWrite64(address, double_to_rawbits(value)); 1782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitMoveWideImmediate(Instruction* instr) { 1786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org MoveWideImmediateOp mov_op = 1787f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask)); 1788f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t new_xn_val = 0; 1789f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1790f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool is_64_bits = instr->SixtyFourBits() == 1; 1791f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Shift is limited for W operations. 1792f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(is_64_bits || (instr->ShiftMoveWide() < 2)); 1793f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1794f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Get the shifted immediate. 1795f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t shift = instr->ShiftMoveWide() * 16; 1796f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t shifted_imm16 = instr->ImmMoveWide() << shift; 1797f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1798f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Compute the new value. 1799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (mov_op) { 1800f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVN_w: 1801f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVN_x: { 1802f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org new_xn_val = ~shifted_imm16; 1803f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!is_64_bits) new_xn_val &= kWRegMask; 1804f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1805f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1806f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVK_w: 1807f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVK_x: { 1808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned reg_code = instr->Rd(); 1809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t prev_xn_val = is_64_bits ? xreg(reg_code) 1810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org : wreg(reg_code); 1811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org new_xn_val = (prev_xn_val & ~(0xffffL << shift)) | shifted_imm16; 1812f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1813f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1814f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVZ_w: 1815f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MOVZ_x: { 1816f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org new_xn_val = shifted_imm16; 1817f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 1820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 1821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Update the destination register. 1824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(instr->Rd(), new_xn_val); 1825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitConditionalSelect(Instruction* instr) { 1829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionFailed(static_cast<Condition>(instr->Condition()))) { 18301845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org uint64_t new_val = xreg(instr->Rm()); 1831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(ConditionalSelectMask)) { 18321845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSEL_w: set_wreg(instr->Rd(), new_val); break; 18331845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSEL_x: set_xreg(instr->Rd(), new_val); break; 18341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINC_w: set_wreg(instr->Rd(), new_val + 1); break; 18351845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINC_x: set_xreg(instr->Rd(), new_val + 1); break; 18361845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINV_w: set_wreg(instr->Rd(), ~new_val); break; 18371845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSINV_x: set_xreg(instr->Rd(), ~new_val); break; 18381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSNEG_w: set_wreg(instr->Rd(), -new_val); break; 18391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case CSNEG_x: set_xreg(instr->Rd(), -new_val); break; 1840f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1841f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 18421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 18431845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 18441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(instr->Rd(), xreg(instr->Rn())); 18451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 18461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_wreg(instr->Rd(), wreg(instr->Rn())); 18471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 1848f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1849f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitDataProcessing1Source(Instruction* instr) { 1853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dst = instr->Rd(); 1854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned src = instr->Rn(); 1855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1856f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(DataProcessing1SourceMask)) { 185797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSizeInBits)); break; 185897b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSizeInBits)); break; 1859f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV16_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse16)); break; 1860f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV16_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse16)); break; 1861f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV_w: set_wreg(dst, ReverseBytes(wreg(src), Reverse32)); break; 1862f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV32_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse32)); break; 1863f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case REV_x: set_xreg(dst, ReverseBytes(xreg(src), Reverse64)); break; 186497b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case CLZ_w: set_wreg(dst, CountLeadingZeros(wreg(src), kWRegSizeInBits)); 186597b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org break; 186697b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org case CLZ_x: set_xreg(dst, CountLeadingZeros(xreg(src), kXRegSizeInBits)); 186797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org break; 1868f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CLS_w: { 186997b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_wreg(dst, CountLeadingSignBits(wreg(src), kWRegSizeInBits)); 1870f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1871f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1872f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case CLS_x: { 187397b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org set_xreg(dst, CountLeadingSignBits(xreg(src), kXRegSizeInBits)); 1874f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1875f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1876f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1877f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1878f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1879f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1880f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::ReverseBits(uint64_t value, unsigned num_bits) { 188297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org ASSERT((num_bits == kWRegSizeInBits) || (num_bits == kXRegSizeInBits)); 1883f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t result = 0; 1884f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (unsigned i = 0; i < num_bits; i++) { 1885f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = (result << 1) | (value & 1); 1886f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value >>= 1; 1887f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1888f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result; 1889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::ReverseBytes(uint64_t value, ReverseByteMode mode) { 1893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Split the 64-bit value into an 8-bit array, where b[0] is the least 1894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // significant byte, and b[7] is the most significant. 1895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint8_t bytes[8]; 1896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mask = 0xff00000000000000UL; 1897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 7; i >= 0; i--) { 1898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bytes[i] = (value & mask) >> (i * 8); 1899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mask >>= 8; 1900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Permutation tables for REV instructions. 1903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // permute_table[Reverse16] is used by REV16_x, REV16_w 1904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // permute_table[Reverse32] is used by REV32_x, REV_w 1905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // permute_table[Reverse64] is used by REV_x 1906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((Reverse16 == 0) && (Reverse32 == 1) && (Reverse64 == 2)); 1907f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const uint8_t permute_table[3][8] = { {6, 7, 4, 5, 2, 3, 0, 1}, 1908f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org {4, 5, 6, 7, 0, 1, 2, 3}, 1909f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org {0, 1, 2, 3, 4, 5, 6, 7} }; 1910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t result = 0; 1911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org for (int i = 0; i < 8; i++) { 1912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result <<= 8; 1913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result |= bytes[permute_table[mode][i]]; 1914f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1915f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result; 1916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 19191845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 19201845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::DataProcessing2Source(Instruction* instr) { 1921f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Shift shift_op = NO_SHIFT; 19221845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = 0; 1923f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(DataProcessing2SourceMask)) { 19241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case SDIV_w: 1925f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SDIV_x: { 19261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T rn = reg<T>(instr->Rn()); 19271845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T rm = reg<T>(instr->Rm()); 19281845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) { 19291845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result = std::numeric_limits<T>::min(); 1930f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (rm == 0) { 1931f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Division by zero can be trapped, but not on A-class processors. 1932f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = 0; 1933f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 1934f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = rn / rm; 1935f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1936f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1937f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 19381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org case UDIV_w: 1939f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UDIV_x: { 19401845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 19411845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn())); 19421845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm())); 1943f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (rm == 0) { 1944f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Division by zero can be trapped, but not on A-class processors. 1945f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = 0; 1946f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 1947f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = rn / rm; 1948f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1949f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 1950f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1951f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSLV_w: 1952f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSLV_x: shift_op = LSL; break; 1953f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSRV_w: 1954f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case LSRV_x: shift_op = LSR; break; 1955f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ASRV_w: 1956f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case ASRV_x: shift_op = ASR; break; 1957f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case RORV_w: 1958f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case RORV_x: shift_op = ROR; break; 1959f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 1960f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1961f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1962f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (shift_op != NO_SHIFT) { 1963f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Shift distance encoded in the least-significant five/six bits of the 1964f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // register. 19651845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org unsigned shift = wreg(instr->Rm()); 19661845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (sizeof(T) == kWRegSize) { 19671845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org shift &= kShiftAmountWRegMask; 19681845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 19691845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org shift &= kShiftAmountXRegMask; 19701845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 19711845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift); 19721845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 19731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result); 19741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 19751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 19761845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 19771845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::VisitDataProcessing2Source(Instruction* instr) { 19781845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 19791845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org DataProcessing2Source<int64_t>(instr); 19801845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 19811845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org DataProcessing2Source<int32_t>(instr); 1982f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 1983f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 1984f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1985f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1986f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The algorithm used is described in section 8.2 of 1987f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Hacker's Delight, by Henry S. Warren, Jr. 1988f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// It assumes that a right shift on a signed integer is an arithmetic shift. 1989f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic int64_t MultiplyHighSigned(int64_t u, int64_t v) { 1990f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t u0, v0, w0; 1991f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t u1, v1, w1, w2, t; 1992f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1993f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org u0 = u & 0xffffffffL; 1994f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org u1 = u >> 32; 1995f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org v0 = v & 0xffffffffL; 1996f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org v1 = v >> 32; 1997f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 1998f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w0 = u0 * v0; 1999f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org t = u1 * v0 + (w0 >> 32); 2000f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w1 = t & 0xffffffffL; 2001f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w2 = t >> 32; 2002f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org w1 = u0 * v1 + w1; 2003f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2004f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return u1 * v1 + w2 + (w1 >> 32); 2005f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2006f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2007f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2008f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitDataProcessing3Source(Instruction* instr) { 2009f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t result = 0; 2010f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract and sign- or zero-extend 32-bit arguments for widening operations. 2011f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t rn_u32 = reg<uint32_t>(instr->Rn()); 2012f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t rm_u32 = reg<uint32_t>(instr->Rm()); 2013f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t rn_s32 = reg<int32_t>(instr->Rn()); 2014f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t rm_s32 = reg<int32_t>(instr->Rm()); 2015f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(DataProcessing3SourceMask)) { 2016f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MADD_w: 2017f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MADD_x: 2018f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm())); 2019f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2020f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MSUB_w: 2021f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MSUB_x: 2022f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm())); 2023f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2024f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break; 2025f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break; 2026f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break; 2027f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break; 2028f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SMULH_x: 2029f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(instr->Ra() == kZeroRegCode); 2030f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm())); 2031f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2032f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2033f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 20341845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 20351845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 20361845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_xreg(instr->Rd(), result); 20371845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 20381845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_wreg(instr->Rd(), result); 20391845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 2040f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2041f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2042f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 20431845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgtemplate <typename T> 20441845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::BitfieldHelper(Instruction* instr) { 20451845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org typedef typename make_unsigned<T>::type unsignedT; 20461845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T reg_size = sizeof(T) * 8; 20471845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T R = instr->ImmR(); 20481845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T S = instr->ImmS(); 20491845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T diff = S - R; 20501845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T mask; 2051f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (diff >= 0) { 20521845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1 20531845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org : static_cast<T>(-1); 2054f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2055f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mask = ((1L << (S + 1)) - 1); 2056f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R)); 2057f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org diff += reg_size; 2058f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2059f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2060f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // inzero indicates if the extracted bitfield is inserted into the 2061f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // destination register value or in zero. 2062f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If extend is true, extend the sign of the extracted bitfield. 2063f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool inzero = false; 2064f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool extend = false; 2065f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(BitfieldMask)) { 2066f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BFM_x: 2067f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case BFM_w: 2068f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2069f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SBFM_x: 2070f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SBFM_w: 2071f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org inzero = true; 2072f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org extend = true; 2073f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2074f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UBFM_x: 2075f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UBFM_w: 2076f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org inzero = true; 2077f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2078f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 2079f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 2080f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2081f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 20821845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T dst = inzero ? 0 : reg<T>(instr->Rd()); 20831845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T src = reg<T>(instr->Rn()); 2084f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Rotate source bitfield into place. 20851845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R)); 2086f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Determine the sign extension. 20871845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1; 20881845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0) 20891845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org << (diff + 1); 2090f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2091f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Merge sign extension, dest/zero and bitfield. 2092f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org result = signbits | (result & mask) | (dst & ~mask); 2093f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 20941845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org set_reg<T>(instr->Rd(), result); 2095f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2096f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 20981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::VisitBitfield(Instruction* instr) { 20991845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 21001845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org BitfieldHelper<int64_t>(instr); 21011845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 21021845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org BitfieldHelper<int32_t>(instr); 2103011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org } 21041845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org} 21051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org 2106011a81ffd5df0e081e7c00ef430b2fec5079bf2amachenbach@chromium.org 21071845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgvoid Simulator::VisitExtract(Instruction* instr) { 21081845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org if (instr->SixtyFourBits()) { 21091845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Extract<uint64_t>(instr); 21101845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } else { 21111845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org Extract<uint32_t>(instr); 21121845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org } 2113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPImmediate(Instruction* instr) { 2117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dest = instr->Rd(); 2120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPImmediateMask)) { 2121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break; 2122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break; 2123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 2124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPIntegerConvert(Instruction* instr) { 2129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dst = instr->Rd(); 2132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned src = instr->Rn(); 2133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 21349801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org FPRounding round = fpcr().RMode(); 2135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPIntegerConvertMask)) { 2137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break; 2138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieAway)); break; 2139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieAway)); break; 2140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieAway)); break; 2141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieAway)); break; 2142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieAway)); break; 2143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieAway)); break; 2144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTAU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieAway)); break; 2145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_ws: 2146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToInt32(sreg(src), FPNegativeInfinity)); 2147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_xs: 2149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToInt64(sreg(src), FPNegativeInfinity)); 2150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_wd: 2152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToInt32(dreg(src), FPNegativeInfinity)); 2153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMS_xd: 2155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToInt64(dreg(src), FPNegativeInfinity)); 2156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_ws: 2158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToUInt32(sreg(src), FPNegativeInfinity)); 2159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_xs: 2161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToUInt64(sreg(src), FPNegativeInfinity)); 2162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_wd: 2164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_wreg(dst, FPToUInt32(dreg(src), FPNegativeInfinity)); 2165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTMU_xd: 2167f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_xreg(dst, FPToUInt64(dreg(src), FPNegativeInfinity)); 2168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieEven)); break; 2170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_xs: set_xreg(dst, FPToInt64(sreg(src), FPTieEven)); break; 2171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_wd: set_wreg(dst, FPToInt32(dreg(src), FPTieEven)); break; 2172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNS_xd: set_xreg(dst, FPToInt64(dreg(src), FPTieEven)); break; 2173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPTieEven)); break; 2174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPTieEven)); break; 2175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPTieEven)); break; 2176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTNU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPTieEven)); break; 2177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_ws: set_wreg(dst, FPToInt32(sreg(src), FPZero)); break; 2178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_xs: set_xreg(dst, FPToInt64(sreg(src), FPZero)); break; 2179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_wd: set_wreg(dst, FPToInt32(dreg(src), FPZero)); break; 2180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZS_xd: set_xreg(dst, FPToInt64(dreg(src), FPZero)); break; 2181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_ws: set_wreg(dst, FPToUInt32(sreg(src), FPZero)); break; 2182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_xs: set_xreg(dst, FPToUInt64(sreg(src), FPZero)); break; 2183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_wd: set_wreg(dst, FPToUInt32(dreg(src), FPZero)); break; 2184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVTZU_xd: set_xreg(dst, FPToUInt64(dreg(src), FPZero)); break; 2185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_ws: set_wreg(dst, sreg_bits(src)); break; 2186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_xd: set_xreg(dst, dreg_bits(src)); break; 2187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_sw: set_sreg_bits(dst, wreg(src)); break; 2188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_dx: set_dreg_bits(dst, xreg(src)); break; 2189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // A 32-bit input can be handled in the same way as a 64-bit input, since 2191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the sign- or zero-extension will not affect the conversion. 2192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dx: set_dreg(dst, FixedToDouble(xreg(src), 0, round)); break; 2193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dw: set_dreg(dst, FixedToDouble(wreg(src), 0, round)); break; 2194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dx: set_dreg(dst, UFixedToDouble(xreg(src), 0, round)); break; 2195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dw: { 2196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, UFixedToDouble(reg<uint32_t>(src), 0, round)); 2197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sx: set_sreg(dst, FixedToFloat(xreg(src), 0, round)); break; 2200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sw: set_sreg(dst, FixedToFloat(wreg(src), 0, round)); break; 2201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sx: set_sreg(dst, UFixedToFloat(xreg(src), 0, round)); break; 2202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sw: { 2203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, UFixedToFloat(reg<uint32_t>(src), 0, round)); 2204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 2208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2211f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPFixedPointConvert(Instruction* instr) { 2213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned dst = instr->Rd(); 2216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned src = instr->Rn(); 2217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int fbits = 64 - instr->FPScale(); 2218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 22199801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org FPRounding round = fpcr().RMode(); 2220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPFixedPointConvertMask)) { 2222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // A 32-bit input can be handled in the same way as a 64-bit input, since 2223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the sign- or zero-extension will not affect the conversion. 2224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dx_fixed: 2225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, FixedToDouble(xreg(src), fbits, round)); 2226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_dw_fixed: 2228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, FixedToDouble(wreg(src), fbits, round)); 2229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dx_fixed: 2231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, UFixedToDouble(xreg(src), fbits, round)); 2232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_dw_fixed: { 2234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_dreg(dst, 2235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UFixedToDouble(reg<uint32_t>(src), fbits, round)); 2236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sx_fixed: 2239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, FixedToFloat(xreg(src), fbits, round)); 2240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case SCVTF_sw_fixed: 2242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, FixedToFloat(wreg(src), fbits, round)); 2243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sx_fixed: 2245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, UFixedToFloat(xreg(src), fbits, round)); 2246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case UCVTF_sw_fixed: { 2248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_sreg(dst, 2249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UFixedToFloat(reg<uint32_t>(src), fbits, round)); 2250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNREACHABLE(); 2253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint32_t Simulator::FPToInt32(double value, FPRounding rmode) { 2258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kWMaxInt) { 2260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kWMaxInt; 2261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < kWMinInt) { 2262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kWMinInt; 2263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<int32_t>(value); 2265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgint64_t Simulator::FPToInt64(double value, FPRounding rmode) { 2269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kXMaxInt) { 2271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kXMaxInt; 2272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < kXMinInt) { 2273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kXMinInt; 2274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<int64_t>(value); 2276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint32_t Simulator::FPToUInt32(double value, FPRounding rmode) { 2280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kWMaxUInt) { 2282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kWMaxUInt; 2283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < 0.0) { 2284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0; 2285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<uint32_t>(value); 2287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orguint64_t Simulator::FPToUInt64(double value, FPRounding rmode) { 2291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org value = FPRoundInt(value, rmode); 2292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value >= kXMaxUInt) { 2293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return kXMaxUInt; 2294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (value < 0.0) { 2295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0; 2296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return std::isnan(value) ? 0 : static_cast<uint64_t>(value); 2298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPCompare(Instruction* instr) { 2302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 23046b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits 23056b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org : kSRegSizeInBits; 2306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double fn_val = fpreg(reg_size, instr->Rn()); 2307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPCompareMask)) { 2309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_s: 2310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break; 2311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_s_zero: 2312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCMP_d_zero: FPCompare(fn_val, 0.0); break; 2313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPConditionalCompare(Instruction* instr) { 2319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPConditionalCompareMask)) { 2322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCCMP_s: 2323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCCMP_d: { 2324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 2325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition passes, set the status flags to the result of 2326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // comparing the operands. 23276b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits 23286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org : kSRegSizeInBits; 2329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm())); 2330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the condition fails, set the status flags to the nzcv immediate. 2332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org nzcv().SetFlags(instr->Nzcv()); 2333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPConditionalSelect(Instruction* instr) { 2342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Instr selected; 2345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 2346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org selected = instr->Rn(); 2347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org selected = instr->Rm(); 2349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPConditionalSelectMask)) { 2352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break; 2353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break; 2354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPDataProcessing1Source(Instruction* instr) { 2360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fd = instr->Rd(); 2363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fn = instr->Rn(); 2364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPDataProcessing1SourceMask)) { 2366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_s: set_sreg(fd, sreg(fn)); break; 2367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMOV_d: set_dreg(fd, dreg(fn)); break; 2368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break; 2369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break; 2370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FNEG_s: set_sreg(fd, -sreg(fn)); break; 2371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FNEG_d: set_dreg(fd, -dreg(fn)); break; 23726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break; 23736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break; 2374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break; 2375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break; 2376255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org case FRINTM_s: 2377255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break; 2378255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org case FRINTM_d: 2379255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break; 2380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break; 2381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break; 2382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break; 2383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break; 2384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break; 2385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break; 2386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Assemble the specified IEEE-754 components into the target type and apply 2392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// appropriate rounding. 2393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// sign: 0 = positive, 1 = negative 2394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// exponent: Unbiased IEEE-754 exponent. 2395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// mantissa: The mantissa of the input. The top bit (which is not encoded for 2396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// normal IEEE-754 values) must not be omitted. This bit has the 2397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// value 'pow(2, exponent)'. 2398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// 2399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// The input value is assumed to be a normalized value. That is, the input may 2400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// not be infinity or NaN. If the source value is subnormal, it must be 2401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// normalized before calling this function such that the highest set bit in the 2402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// mantissa has the value 'pow(2, exponent)'. 2403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// 2404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than 2405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// calling a templated FPRound. 2406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <class T, int ebits, int mbits> 2407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa, 2408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPRounding round_mode) { 2409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((sign == 0) || (sign == 1)); 2410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Only the FPTieEven rounding mode is implemented. 2412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(round_mode == FPTieEven); 2413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org USE(round_mode); 2414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Rounding can promote subnormals to normals, and normals to infinities. For 2416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be 2417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // encodable as a float, but rounding based on the low-order mantissa bits 2418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // could make it overflow. With ties-to-even rounding, this value would become 2419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // an infinity. 2420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ---- Rounding Method ---- 2422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The exponent is irrelevant in the rounding operation, so we treat the 2424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // lowest-order bit that will fit into the result ('onebit') as having 2425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the value '1'. Similarly, the highest-order bit that won't fit into 2426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the result ('halfbit') has the value '0.5'. The 'point' sits between 2427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 'onebit' and 'halfbit': 2428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // These bits fit into the result. 2430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // |---------------------| 2431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 2432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // || 2433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / | 2434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / halfbit 2435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // onebit 2436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For subnormal outputs, the range of representable bits is smaller and 2438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the position of onebit and halfbit depends on the exponent of the 2439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // input, but the method is otherwise similar. 2440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // onebit(frac) 2442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | 2443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | halfbit(frac) halfbit(adjusted) 2444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | / / 2445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // | | | 2446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00 2447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.0... -> 0b00.0... -> 0b00 2448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00 2449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b00.1... -> 0b00.1... -> 0b01 2450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01 2451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.0... -> 0b01.0... -> 0b01 2452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10 2453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b01.1... -> 0b01.1... -> 0b10 2454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10 2455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.0... -> 0b10.0... -> 0b10 2456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10 2457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b10.1... -> 0b10.1... -> 0b11 2458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11 2459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // ... / | / | 2460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / | / | 2461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // / | 2462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / | 2463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // mantissa = (mantissa >> shift) + halfbit(adjusted); 2465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int mantissa_offset = 0; 2467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int exponent_offset = mantissa_offset + mbits; 2468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int sign_offset = exponent_offset + ebits; 2469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1)); 2470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Bail out early for zero inputs. 2472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (mantissa == 0) { 2473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sign << sign_offset; 2474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If all bits in the exponent are set, the value is infinite or NaN. 2477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This is true for all binary IEEE-754 formats. 2478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int infinite_exponent = (1 << ebits) - 1; 2479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org static const int max_normal_exponent = infinite_exponent - 1; 2480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Apply the exponent bias to encode it for the result. Doing this early makes 2482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // it easy to detect values that will be infinite or subnormal. 2483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent += max_normal_exponent >> 1; 2484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (exponent > max_normal_exponent) { 2486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Overflow: The input is too large for the result type to represent. The 2487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // FPTieEven rounding mode handles overflows using infinities. 2488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent = infinite_exponent; 2489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa = 0; 2490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (sign << sign_offset) | 2491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (exponent << exponent_offset) | 2492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (mantissa << mantissa_offset); 2493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the shift required to move the top mantissa bit to the proper 2496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // place in the destination type. 2497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64); 2498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int shift = highest_significant_bit - mbits; 2499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (exponent <= 0) { 2501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The output will be subnormal (before rounding). 2502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // For subnormal outputs, the shift must be adjusted by the exponent. The +1 2504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // is necessary because the exponent of a subnormal value (encoded as 0) is 2505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // the same as the exponent of the smallest normal value (encoded as 1). 2506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org shift += -exponent + 1; 2507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Handle inputs that would produce a zero output. 2509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Shifts higher than highest_significant_bit+1 will always produce a zero 2511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // result. A shift of exactly highest_significant_bit+1 might produce a 2512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // non-zero result after rounding. 2513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (shift > (highest_significant_bit + 1)) { 2514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The result will always be +/-0.0. 2515f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return sign << sign_offset; 2516f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2517f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2518f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Properly encode the exponent for a subnormal output. 2519f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent = 0; 2520f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2521f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Clear the topmost mantissa bit, since this is not encoded in IEEE-754 2522f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // normal values. 2523f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa &= ~(1UL << highest_significant_bit); 2524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (shift > 0) { 2527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We have to shift the mantissa to the right. Some precision is lost, so we 2528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // need to apply rounding. 2529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t onebit_mantissa = (mantissa >> (shift)) & 1; 2530f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1; 2531f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa); 2532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org T halfbit_adjusted = (adjusted >> (shift-1)) & 1; 2533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org T result = (sign << sign_offset) | 2535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (exponent << exponent_offset) | 2536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ((mantissa >> shift) << mantissa_offset); 2537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2538f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // A very large mantissa can overflow during rounding. If this happens, the 2539f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // exponent should be incremented and the mantissa set to 1.0 (encoded as 2540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 0). Applying halfbit_adjusted after assembling the float has the nice 2541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // side-effect that this case is handled for free. 2542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This also handles cases where a very large finite value overflows to 2544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // infinity, or where a very large subnormal value overflows to become 2545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // normal. 2546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return result + halfbit_adjusted; 2547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We have to shift the mantissa to the left (or not at all). The input 2549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // mantissa is exactly representable in the output mantissa, so apply no 2550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // rounding correction. 2551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (sign << sign_offset) | 2552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (exponent << exponent_offset) | 2553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ((mantissa << -shift) << mantissa_offset); 2554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// See FPRound for a description of this function. 2559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic inline double FPRoundToDouble(int64_t sign, int64_t exponent, 2560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mantissa, FPRounding round_mode) { 2561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t bits = 2562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign, 2563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent, 2564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa, 2565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org round_mode); 2566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_double(bits); 2567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2568f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2569f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// See FPRound for a description of this function. 2571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic inline float FPRoundToFloat(int64_t sign, int64_t exponent, 2572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mantissa, FPRounding round_mode) { 2573f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int32_t bits = 2574f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign, 2575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org exponent, 2576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa, 2577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org round_mode); 2578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_float(bits); 2579f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) { 2583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src >= 0) { 2584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return UFixedToDouble(src, fbits, round); 2585f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This works for all negative values, including INT64_MIN. 2587f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -UFixedToDouble(-src, fbits, round); 2588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) { 2593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // An input of 0 is a special case because the result is effectively 2594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit. 2595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src == 0) { 2596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0.0; 2597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the exponent. The highest significant bit will have the value 2600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2^exponent. 2601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int highest_significant_bit = 63 - CountLeadingZeros(src, 64); 2602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int64_t exponent = highest_significant_bit - fbits; 2603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return FPRoundToDouble(0, exponent, src, round); 2605f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2606f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2607f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2608f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) { 2609f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src >= 0) { 2610f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return UFixedToFloat(src, fbits, round); 2611f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2612f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // This works for all negative values, including INT64_MIN. 2613f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -UFixedToFloat(-src, fbits, round); 2614f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2615f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2616f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2617f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2618f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) { 2619f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // An input of 0 is a special case because the result is effectively 2620f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit. 2621f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (src == 0) { 2622f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0.0f; 2623f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2624f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2625f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Calculate the exponent. The highest significant bit will have the value 2626f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // 2^exponent. 2627f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int highest_significant_bit = 63 - CountLeadingZeros(src, 64); 2628f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org const int32_t exponent = highest_significant_bit - fbits; 2629f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2630f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return FPRoundToFloat(0, exponent, src, round); 2631f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2632f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2633f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2634f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::FPRoundInt(double value, FPRounding round_mode) { 2635f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((value == 0.0) || (value == kFP64PositiveInfinity) || 26366b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (value == kFP64NegativeInfinity)) { 2637f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return value; 26386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(value)) { 26396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(value); 2640f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2641f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2642f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double int_result = floor(value); 2643f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org double error = value - int_result; 2644f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (round_mode) { 2645f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPTieAway: { 2646255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // Take care of correctly handling the range ]-0.5, -0.0], which must 2647255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // yield -0.0. 2648255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org if ((-0.5 < value) && (value < 0.0)) { 2649255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org int_result = -0.0; 2650255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org 2651255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) { 2652255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // If the error is greater than 0.5, or is equal to 0.5 and the integer 2653255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // result is positive, round up. 2654f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int_result++; 2655f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2656f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2657f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2658f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPTieEven: { 2659255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // Take care of correctly handling the range [-0.5, -0.0], which must 2660255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org // yield -0.0. 2661255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org if ((-0.5 <= value) && (value < 0.0)) { 2662255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org int_result = -0.0; 2663255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org 2664f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If the error is greater than 0.5, or is equal to 0.5 and the integer 2665f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // result is odd, round up. 2666255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org } else if ((error > 0.5) || 2667f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ((error == 0.5) && (fmod(int_result, 2) != 0))) { 2668f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int_result++; 2669f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2670f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2671f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2672f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPZero: { 2673f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If value > 0 then we take floor(value) 2674f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // otherwise, ceil(value) 2675f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (value < 0) { 2676f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int_result = ceil(value); 2677f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2678f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2679f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2680f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPNegativeInfinity: { 2681f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We always use floor(value). 2682f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 2683f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2684f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2685f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2686f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return int_result; 2687f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2688f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2689f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2690f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgdouble Simulator::FPToDouble(float value) { 2691f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (std::fpclassify(value)) { 2692f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NAN: { 26939801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org if (fpcr().DN()) return kFP64DefaultNaN; 26946b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 26956b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Convert NaNs as the processor would: 2696f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The sign is propagated. 2697f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The payload (mantissa) is transferred entirely, except that the top 2698f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // bit is forced to '1', making the result a quiet NaN. The unused 2699f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (low-order) payload bits are set to 0. 2700f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t raw = float_to_rawbits(value); 2701f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2702f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t sign = raw >> 31; 2703f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t exponent = (1 << 11) - 1; 2704f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t payload = unsigned_bitextract_64(21, 0, raw); 2705f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org payload <<= (52 - 23); // The unused low-order bits should be 0. 2706f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org payload |= (1L << 51); // Force a quiet NaN. 2707f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2708f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_double((sign << 63) | (exponent << 52) | payload); 2709f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2710f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2711f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_ZERO: 2712f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NORMAL: 2713f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_SUBNORMAL: 2714f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_INFINITE: { 2715f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // All other inputs are preserved in a standard cast, because every value 2716f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // representable using an IEEE-754 float is also representable using an 2717f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // IEEE-754 double. 2718f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return static_cast<double>(value); 2719f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2720f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2721f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2722f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 2723f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return static_cast<double>(value); 2724f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2725f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2726f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2727f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgfloat Simulator::FPToFloat(double value, FPRounding round_mode) { 2728f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Only the FPTieEven rounding mode is implemented. 2729f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(round_mode == FPTieEven); 2730f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org USE(round_mode); 2731f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (std::fpclassify(value)) { 2733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NAN: { 27349801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org if (fpcr().DN()) return kFP32DefaultNaN; 27356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 27366b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Convert NaNs as the processor would: 2737f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The sign is propagated. 2738f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - The payload (mantissa) is transferred as much as possible, except 2739f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // that the top bit is forced to '1', making the result a quiet NaN. 2740f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t raw = double_to_rawbits(value); 2741f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2742f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t sign = raw >> 63; 2743f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t exponent = (1 << 8) - 1; 2744f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t payload = unsigned_bitextract_64(50, 52 - 23, raw); 2745f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org payload |= (1 << 22); // Force a quiet NaN. 2746f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2747f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return rawbits_to_float((sign << 31) | (exponent << 23) | payload); 2748f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2749f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2750f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_ZERO: 2751f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_INFINITE: { 2752f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // In a C++ cast, any value representable in the target type will be 2753f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // unchanged. This is always the case for +/-0.0 and infinities. 2754f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return static_cast<float>(value); 2755f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2756f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2757f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_NORMAL: 2758f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FP_SUBNORMAL: { 2759f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Convert double-to-float as the processor would, assuming that FPCR.FZ 2760f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // (flush-to-zero) is not set. 2761f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t raw = double_to_rawbits(value); 2762f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract the IEEE-754 double components. 2763f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t sign = raw >> 63; 2764f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract the exponent and remove the IEEE-754 encoding bias. 2765f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int32_t exponent = unsigned_bitextract_64(62, 52, raw) - 1023; 2766f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Extract the mantissa and add the implicit '1' bit. 2767f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint64_t mantissa = unsigned_bitextract_64(51, 0, raw); 2768f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (std::fpclassify(value) == FP_NORMAL) { 2769f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org mantissa |= (1UL << 52); 2770f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2771f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return FPRoundToFloat(sign, exponent, mantissa, round_mode); 2772f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2773f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2774f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2775f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 2776f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return value; 2777f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2778f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2779f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2780f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPDataProcessing2Source(Instruction* instr) { 2781f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2782f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2783f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fd = instr->Rd(); 2784f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fn = instr->Rn(); 2785f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fm = instr->Rm(); 2786f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 27876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Fmaxnm and Fminnm have special NaN handling. 27886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org switch (instr->Mask(FPDataProcessing2SourceMask)) { 27896b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return; 27906b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return; 27916b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return; 27926b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return; 27936b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org default: 27946b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; // Fall through. 27956b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 27966b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 27976b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (FPProcessNaNs(instr)) return; 27986b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2799f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPDataProcessing2SourceMask)) { 28006b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break; 28016b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break; 28026b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break; 28036b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break; 28046b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break; 28056b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break; 28066b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break; 28076b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break; 2808f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break; 2809f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break; 2810f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break; 2811f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break; 28126b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_s: 28136b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMAXNM_d: 28146b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_s: 28156b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMINNM_d: 28166b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // These were handled before the standard FPProcessNaNs() stage. 28176b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org UNREACHABLE(); 2818f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2819f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2820f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2821f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2822f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2823f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitFPDataProcessing3Source(Instruction* instr) { 2824f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org AssertSupportedFPCR(); 2825f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2826f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fd = instr->Rd(); 2827f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fn = instr->Rn(); 2828f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fm = instr->Rm(); 2829f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned fa = instr->Ra(); 2830f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2831f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(FPDataProcessing3SourceMask)) { 2832f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // fd = fa +/- (fn * fm) 28336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMADD_s: set_sreg(fd, FPMulAdd(sreg(fa), sreg(fn), sreg(fm))); break; 28346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMSUB_s: set_sreg(fd, FPMulAdd(sreg(fa), -sreg(fn), sreg(fm))); break; 28356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMADD_d: set_dreg(fd, FPMulAdd(dreg(fa), dreg(fn), dreg(fm))); break; 28366b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FMSUB_d: set_dreg(fd, FPMulAdd(dreg(fa), -dreg(fn), dreg(fm))); break; 28376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Negated variants of the above. 28386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMADD_s: 28396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_sreg(fd, FPMulAdd(-sreg(fa), -sreg(fn), sreg(fm))); 28406b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 28416b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMSUB_s: 28426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_sreg(fd, FPMulAdd(-sreg(fa), sreg(fn), sreg(fm))); 28436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 28446b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMADD_d: 28456b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm))); 28466b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 28476b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org case FNMSUB_d: 28486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm))); 28496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org break; 2850f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 2851f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2852f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2853f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2854f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2855f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 28566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPAdd(T op1, T op2) { 28576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 28586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!std::isnan(op1) && !std::isnan(op2)); 28596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2860a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) { 28616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf + -inf returns the default NaN. 28626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 28636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 28646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 28656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 + op2; 28666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 28676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 28686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 28696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 28706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 28716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPDiv(T op1, T op2) { 28726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 28736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!std::isnan(op1) && !std::isnan(op2)); 28746b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2875a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) { 28766b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf / inf and 0.0 / 0.0 return the default NaN. 28776b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 28786b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 28796b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 28806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 / op2; 2881f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 28826b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 28836b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 28846b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 28856b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 28866b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPMax(T a, T b) { 28876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 28886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!std::isnan(a) && !std::isnan(b)); 2889f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2890f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((a == 0.0) && (b == 0.0) && 2891f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (copysign(1.0, a) != copysign(1.0, b))) { 2892f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // a and b are zero, and the sign differs: return +0.0. 2893f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return 0.0; 2894f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2895f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (a > b) ? a : b; 2896f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2897f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2898f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2899f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2900f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 2901f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgT Simulator::FPMaxNM(T a, T b) { 2902f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (IsQuietNaN(a) && !IsQuietNaN(b)) { 2903f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org a = kFP64NegativeInfinity; 2904f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { 2905f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org b = kFP64NegativeInfinity; 2906f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 29076b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29086b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T result = FPProcessNaNs(a, b); 29096b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return std::isnan(result) ? result : FPMax(a, b); 2910f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2911f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2912f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 2913f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgT Simulator::FPMin(T a, T b) { 29146b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 29156b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!isnan(a) && !isnan(b)); 2916f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2917f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((a == 0.0) && (b == 0.0) && 2918f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (copysign(1.0, a) != copysign(1.0, b))) { 2919f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // a and b are zero, and the sign differs: return -0.0. 2920f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return -0.0; 2921f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 2922f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return (a < b) ? a : b; 2923f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 2924f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 2925f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2926f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 2927f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgtemplate <typename T> 2928f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgT Simulator::FPMinNM(T a, T b) { 2929f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (IsQuietNaN(a) && !IsQuietNaN(b)) { 2930f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org a = kFP64PositiveInfinity; 2931f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (!IsQuietNaN(a) && IsQuietNaN(b)) { 2932f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org b = kFP64PositiveInfinity; 2933f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 29346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T result = FPProcessNaNs(a, b); 2936a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org return std::isnan(result) ? result : FPMin(a, b); 29376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 29386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29406b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 29416b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPMul(T op1, T op2) { 29426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 29436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!std::isnan(op1) && !std::isnan(op2)); 29446b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 2945a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) { 29466b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf * 0.0 returns the default NaN. 29476b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 29486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 29496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 29506b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 * op2; 29516b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29526b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 29536b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate<typename T> 29566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPMulAdd(T a, T op1, T op2) { 29576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T result = FPProcessNaNs3(a, op1, op2); 29586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T sign_a = copysign(1.0, a); 29606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org T sign_prod = copysign(1.0, op1) * copysign(1.0, op2); 29616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org bool isinf_prod = std::isinf(op1) || std::isinf(op2); 29626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org bool operation_generates_nan = 29636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0 29646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf 29656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf 29666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(result)) { 29686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Generated NaNs override quiet NaNs propagated from a. 29696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (operation_generates_nan && IsQuietNaN(a)) { 29706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 29716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 29726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return result; 29736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29746b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29756b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29766b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // If the operation would produce a NaN, return the default NaN. 29776b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (operation_generates_nan) { 29786b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 29796b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29816b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Work around broken fma implementations for exact zero results: The sign of 29826b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // exact 0.0 results is positive unless both a and op1 * op2 are negative. 29836b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) { 29846b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0; 29856b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29866b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org result = FusedMultiplyAdd(op1, op2, a); 29886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!std::isnan(result)); 29896b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29906b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Work around broken fma implementations for rounded zero results: If a is 29916b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // 0.0, the sign of the result is the sign of op1 * op2 before rounding. 29926b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if ((a == 0.0) && (result == 0.0)) { 29936b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return copysign(0.0, sign_prod); 29946b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 29956b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29966b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return result; 29976b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 29986b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 29996b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30006b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30016b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPSqrt(T op) { 30026b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(op)) { 30036b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op); 30046b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (op < 0.0) { 30056b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 30066b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30076b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return std::sqrt(op); 30086b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30096b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30106b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30116b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30126b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30136b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPSub(T op1, T op2) { 30146b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // NaNs should be handled elsewhere. 30156b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(!std::isnan(op1) && !std::isnan(op2)); 30166b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 3017a221880197f38ff22d942851060daffa5d036bdfmachenbach@chromium.org if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) { 30186b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // inf - inf returns the default NaN. 30196b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPDefaultNaN<T>(); 30206b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org // Other cases should be handled by standard arithmetic. 30226b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return op1 - op2; 30236b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30246b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30256b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30266b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30276b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30286b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPProcessNaN(T op) { 30296b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(std::isnan(op)); 30309801e3c558f3df82f01ac626b6171032afa33819machenbach@chromium.org return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op); 30316b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30356b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPProcessNaNs(T op1, T op2) { 30366b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (IsSignallingNaN(op1)) { 30376b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 30386b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (IsSignallingNaN(op2)) { 30396b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 30406b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op1)) { 30416b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(IsQuietNaN(op1)); 30426b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 30436b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op2)) { 30446b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(IsQuietNaN(op2)); 30456b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 30466b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30476b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return 0.0; 30486b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30496b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30506b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30516b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30526b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgtemplate <typename T> 30536b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgT Simulator::FPProcessNaNs3(T op1, T op2, T op3) { 30546b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (IsSignallingNaN(op1)) { 30556b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 30566b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (IsSignallingNaN(op2)) { 30576b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 30586b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (IsSignallingNaN(op3)) { 30596b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op3); 30606b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op1)) { 30616b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(IsQuietNaN(op1)); 30626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op1); 30636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op2)) { 30646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(IsQuietNaN(op2)); 30656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op2); 30666b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else if (std::isnan(op3)) { 30676b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org ASSERT(IsQuietNaN(op3)); 30686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return FPProcessNaN(op3); 30696b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30706b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return 0.0; 30716b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org} 30736b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30746b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30756b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgbool Simulator::FPProcessNaNs(Instruction* instr) { 30766b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned fd = instr->Rd(); 30776b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned fn = instr->Rn(); 30786b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org unsigned fm = instr->Rm(); 30796b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org bool done = false; 30806b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30816b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (instr->Mask(FP64) == FP64) { 30826b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org double result = FPProcessNaNs(dreg(fn), dreg(fm)); 30836b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(result)) { 30846b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_dreg(fd, result); 30856b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org done = true; 30866b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30876b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } else { 30886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org float result = FPProcessNaNs(sreg(fn), sreg(fm)); 30896b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org if (std::isnan(result)) { 30906b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org set_sreg(fd, result); 30916b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org done = true; 30926b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30936b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org } 30946b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org 30956b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org return done; 3096f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3097f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3098f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3099f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitSystem(Instruction* instr) { 3100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Some system instructions hijack their Op and Cp fields to represent a 3101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // range of immediates instead of indicating a different instruction. This 3102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // makes the decoding tricky. 3103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) { 3104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(SystemSysRegMask)) { 3105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MRS: { 3106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->ImmSystemRegister()) { 3107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NZCV: set_xreg(instr->Rt(), nzcv().RawValue()); break; 3108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPCR: set_xreg(instr->Rt(), fpcr().RawValue()); break; 3109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 3110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case MSR: { 3114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->ImmSystemRegister()) { 3115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NZCV: nzcv().SetRawValue(xreg(instr->Rt())); break; 3116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case FPCR: fpcr().SetRawValue(xreg(instr->Rt())); break; 3117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 3118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3121f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { 3123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(instr->Mask(SystemHintMask) == HINT); 3124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->ImmHint()) { 3125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case NOP: break; 3126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: UNIMPLEMENTED(); 3127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { 3129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org __sync_synchronize(); 3130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 3132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3136f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool Simulator::GetValue(const char* desc, int64_t* value) { 3137f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int regnum = CodeFromName(desc); 3138f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (regnum >= 0) { 3139f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org unsigned code = regnum; 3140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (code == kZeroRegCode) { 3141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Catch the zero register and return 0. 3142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org *value = 0; 3143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (code == kSPRegInternalCode) { 3145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Translate the stack pointer code to 31, for Reg31IsStackPointer. 3146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code = 31; 3147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (desc[0] == 'w') { 3149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org *value = wreg(code, Reg31IsStackPointer); 3150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org *value = xreg(code, Reg31IsStackPointer); 3152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3153f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3154f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strncmp(desc, "0x", 2) == 0) { 3155f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SScanF(desc + 2, "%" SCNx64, 3156f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<uint64_t*>(value)) == 1; 3157f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3158f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return SScanF(desc, "%" SCNu64, 3159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<uint64_t*>(value)) == 1; 3160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3162f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool Simulator::PrintValue(const char* desc) { 3165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(desc, "csp") == 0) { 3166f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode)); 31679e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s csp:%s 0x%016" PRIx64 "%s\n", 3168f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal); 3169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(desc, "wcsp") == 0) { 3171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode)); 31729e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n", 3173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal); 3174f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3175f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int i = CodeFromName(desc); 3178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters); 3179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false; 3180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (desc[0] == 'v') { 31829e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n", 3183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, VRegNameForCode(i), 3184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, double_to_rawbits(dreg(i)), 3185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal, 3186f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, DRegNameForCode(i), 3187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, dreg(i), 3188f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, SRegNameForCode(i), 3189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, sreg(i), 3190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (desc[0] == 'd') { 31939e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s %g%s\n", 3194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, DRegNameForCode(i), 3195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, dreg(i), 3196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3197f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (desc[0] == 's') { 31999e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s %g%s\n", 3200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_name, SRegNameForCode(i), 3201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_fpreg_value, sreg(i), 3202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (desc[0] == 'w') { 32059e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n", 3206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal); 3207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // X register names have a wide variety of starting characters, but anything 3210f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // else will be an X register. 32119e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n", 3212f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal); 3213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org return true; 3214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::Debug() { 3219f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define COMMAND_SIZE 63 3220f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define ARG_SIZE 255 3221f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define STR(a) #a 3223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define XSTR(a) STR(a) 3224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char cmd[COMMAND_SIZE + 1]; 3226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char arg1[ARG_SIZE + 1]; 3227f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char arg2[ARG_SIZE + 1]; 3228f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* argv[3] = { cmd, arg1, arg2 }; 3229f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3230f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Make sure to have a proper terminating character if reaching the limit. 3231f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cmd[COMMAND_SIZE] = 0; 3232f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org arg1[ARG_SIZE] = 0; 3233f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org arg2[ARG_SIZE] = 0; 3234f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3235f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool done = false; 3236f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org bool cleared_log_disasm_bit = false; 3237f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (!done) { 3239f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Disassemble the next instruction to execute before doing anything else. 3240f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintInstructionsAt(pc_, 1); 3241f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Read the command line. 3242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* line = ReadLine("sim> "); 3243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (line == NULL) { 3244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3245f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3246f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Repeat last command by default. 3247f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org char* last_input = last_debugger_input(); 3248f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(line, "\n") == 0 && (last_input != NULL)) { 3249f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org DeleteArray(line); 3250f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org line = last_input; 3251f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Update the latest command ran 3253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_last_debugger_input(line); 3254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3255f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3256f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Use sscanf to parse the individual parts of the command line. At the 3257f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // moment no command expects more than two parameters. 3258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int argc = SScanF(line, 3259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "%" XSTR(COMMAND_SIZE) "s " 3260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "%" XSTR(ARG_SIZE) "s " 3261f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "%" XSTR(ARG_SIZE) "s", 3262f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cmd, arg1, arg2); 3263f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3264f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stepi / si ------------------------------------------------------------ 3265f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 3266f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We are about to execute instructions, after which by default we 3267f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // should increment the pc_. If it was set when reaching this debug 3268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // instruction, it has not been cleared because this instruction has not 3269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // completed yet. So clear it manually. 3270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_modified_ = false; 3271f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 1) { 3273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExecuteInstruction(); 3274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t number_of_instructions_to_execute = 1; 3276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GetValue(arg1, &number_of_instructions_to_execute); 3277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() | LOG_DISASM); 3279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (number_of_instructions_to_execute-- > 0) { 3280f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ExecuteInstruction(); 3281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() & ~LOG_DISASM); 3283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // If it was necessary, the pc has already been updated or incremented 3287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // when executing the instruction. So we do not want it to be updated 3288f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // again. It will be cleared when exiting. 3289f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org pc_modified_ = true; 3290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // next / n -------------------------------------------------------------- 3292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "next") == 0) || (strcmp(cmd, "n") == 0)) { 3293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Tell the simulator to break after the next executed BL. 3294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break_on_next_ = true; 3295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Continue. 3296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org done = true; 3297f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3298f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // continue / cont / c --------------------------------------------------- 3299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "continue") == 0) || 3300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(cmd, "cont") == 0) || 3301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(cmd, "c") == 0)) { 3302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Leave the debugger shell. 3303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org done = true; 3304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // disassemble / disasm / di --------------------------------------------- 3306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "disassemble") == 0 || 3307f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org strcmp(cmd, "disasm") == 0 || 3308f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org strcmp(cmd, "di") == 0) { 3309f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t n_of_instrs_to_disasm = 10; // default value. 3310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t address = reinterpret_cast<int64_t>(pc_); // default value. 3311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc >= 2) { // disasm <n of instrs> 3312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GetValue(arg1, &n_of_instrs_to_disasm); 3313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc >= 3) { // disasm <n of instrs> <address> 3315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org GetValue(arg2, &address); 3316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Disassemble. 3319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintInstructionsAt(reinterpret_cast<Instruction*>(address), 3320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org n_of_instrs_to_disasm); 3321f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // print / p ------------------------------------------------------------- 3324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { 3325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 2) { 3326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(arg1, "all") == 0) { 3327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintRegisters(true); 3328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintFPRegisters(true); 3329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!PrintValue(arg1)) { 3331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3333f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF( 3336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "print <register>\n" 3337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print the content of a register. (alias 'p')\n" 3338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " 'print all' will print all registers.\n" 3339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Use 'printobject' to get more details about the value.\n"); 3340f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3341f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // printobject / po ------------------------------------------------------ 3343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if ((strcmp(cmd, "printobject") == 0) || 3344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (strcmp(cmd, "po") == 0)) { 3345f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 2) { 3346f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value; 3347f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (GetValue(arg1, &value)) { 3348f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Object* obj = reinterpret_cast<Object*>(value); 3349f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s: \n", arg1); 3350f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG 3351f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org obj->PrintLn(); 3352f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#else 3353f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org obj->ShortPrint(); 3354f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3355f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif 3356f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3357f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3358f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3359f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3360f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("printobject <value>\n" 3361f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "printobject <register>\n" 3362f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print details about the value. (alias 'po')\n"); 3363f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3364f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3365f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // stack / mem ---------------------------------------------------------- 3366f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) { 3367f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t* cur = NULL; 3368f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t* end = NULL; 3369f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int next_arg = 1; 3370f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (strcmp(cmd, "stack") == 0) { 3372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cur = reinterpret_cast<int64_t*>(jssp()); 3373f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3374f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { // "mem" 3375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value; 3376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!GetValue(arg1, &value)) { 3377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3378f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org continue; 3379f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3380f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cur = reinterpret_cast<int64_t*>(value); 3381f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org next_arg++; 3382f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3383f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3384f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t words = 0; 3385f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == next_arg) { 3386f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org words = 10; 3387f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (argc == next_arg + 1) { 3388f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (!GetValue(argv[next_arg], &words)) { 3389f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", argv[next_arg]); 3390f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Printing 10 double words by default"); 3391f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org words = 10; 3392f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3393f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3394f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNREACHABLE(); 3395f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3396f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org end = cur + words; 3397f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3398f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org while (cur < end) { 3399f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF(" 0x%016" PRIx64 ": 0x%016" PRIx64 " %10" PRId64, 3400f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<uint64_t>(cur), *cur, *cur); 3401f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); 3402f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value = *cur; 3403f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org Heap* current_heap = v8::internal::Isolate::Current()->heap(); 3404f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (((value & 1) == 0) || current_heap->Contains(obj)) { 3405f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF(" ("); 3406f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((value & kSmiTagMask) == 0) { 3407f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org STATIC_ASSERT(kSmiValueSize == 32); 3408f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int32_t untagged = (value >> kSmiShift) & 0xffffffff; 3409f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("smi %" PRId32, untagged); 3410f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3411f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org obj->ShortPrint(); 3412f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3413f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF(")"); 3414f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3415f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("\n"); 3416f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org cur++; 3417f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3418f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3419f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // trace / t ------------------------------------------------------------- 3420f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "trace") == 0 || strcmp(cmd, "t") == 0) { 3421f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if ((log_parameters() & (LOG_DISASM | LOG_REGS)) != 3422f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org (LOG_DISASM | LOG_REGS)) { 3423f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Enabling disassembly and registers tracing\n"); 3424f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() | LOG_DISASM | LOG_REGS); 3425f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3426f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Disabling disassembly and registers tracing\n"); 3427f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() & ~(LOG_DISASM | LOG_REGS)); 3428f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3429f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3430f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // break / b ------------------------------------------------------------- 3431f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "break") == 0 || strcmp(cmd, "b") == 0) { 3432f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (argc == 2) { 3433f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org int64_t value; 3434f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (GetValue(arg1, &value)) { 3435f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org SetBreakpoint(reinterpret_cast<Instruction*>(value)); 3436f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3437f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("%s unrecognized\n", arg1); 3438f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3439f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3440f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ListBreakpoints(); 3441f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Use `break <address>` to set or disable a breakpoint\n"); 3442f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3443f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3444f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // gdb ------------------------------------------------------------------- 3445f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "gdb") == 0) { 3446f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Relinquishing control to gdb.\n"); 3447f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org OS::DebugBreak(); 3448f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Regaining control from gdb.\n"); 3449f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3450f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // sysregs --------------------------------------------------------------- 3451f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "sysregs") == 0) { 3452f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintSystemRegisters(); 3453f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3454f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // help / h -------------------------------------------------------------- 3455f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (strcmp(cmd, "help") == 0 || strcmp(cmd, "h") == 0) { 3456f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF( 3457f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "stepi / si\n" 3458f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " stepi <n>\n" 3459f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Step <n> instructions.\n" 3460f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "next / n\n" 3461f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Continue execution until a BL instruction is reached.\n" 3462f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " At this point a breakpoint is set just after this BL.\n" 3463f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Then execution is resumed. It will probably later hit the\n" 3464f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " breakpoint just set.\n" 3465f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "continue / cont / c\n" 3466f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Continue execution from here.\n" 3467f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "disassemble / disasm / di\n" 3468f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " disassemble <n> <address>\n" 3469f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Disassemble <n> instructions from current <address>.\n" 3470f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " By default <n> is 20 and <address> is the current pc.\n" 3471f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "print / p\n" 3472f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " print <register>\n" 3473f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print the content of a register.\n" 3474f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " 'print all' will print all registers.\n" 3475f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Use 'printobject' to get more details about the value.\n" 3476f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "printobject / po\n" 3477f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " printobject <value>\n" 3478f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " printobject <register>\n" 3479f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print details about the value.\n" 3480f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "stack\n" 3481f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " stack [<words>]\n" 3482f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Dump stack content, default dump 10 words\n" 3483f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "mem\n" 3484f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " mem <address> [<words>]\n" 3485f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Dump memory content, default dump 10 words\n" 3486f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "trace / t\n" 3487f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Toggle disassembly and register tracing\n" 3488f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "break / b\n" 3489f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " break : list all breakpoints\n" 3490f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " break <address> : set / enable / disable a breakpoint.\n" 3491f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "gdb\n" 3492f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Enter gdb.\n" 3493f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org "sysregs\n" 3494f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org " Print all system registers (including NZCV).\n"); 3495f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3496f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Unknown command: %s\n", cmd); 3497f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org PrintF("Use 'help' for more information.\n"); 3498f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3499f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3500f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (cleared_log_disasm_bit == true) { 3501f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters_ | LOG_DISASM); 3502f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3503f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3504f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3505f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3506f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3507f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid Simulator::VisitException(Instruction* instr) { 3508f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (instr->Mask(ExceptionMask)) { 3509f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case HLT: { 3510f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (instr->ImmException() == kImmExceptionIsDebug) { 3511f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Read the arguments encoded inline in the instruction stream. 3512f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t code; 3513f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org uint32_t parameters; 3514f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 35154452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org memcpy(&code, 35164452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_->InstructionAtOffset(kDebugCodeOffset), 35174452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org sizeof(code)); 35184452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org memcpy(¶meters, 35194452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_->InstructionAtOffset(kDebugParamsOffset), 35204452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org sizeof(parameters)); 35214452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org char const *message = 35224452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org reinterpret_cast<char const*>( 35234452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_->InstructionAtOffset(kDebugMessageOffset)); 3524f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3525f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Always print something when we hit a debug point that breaks. 3526f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We are going to break, so printing something is not an issue in 3527f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // terms of speed. 3528f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (FLAG_trace_sim_messages || FLAG_trace_sim || (parameters & BREAK)) { 3529f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (message != NULL) { 35309e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 35319e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org "%sDebugger hit %d: %s%s%s\n", 3532f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_debug_number, 3533f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code, 3534f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_debug_message, 3535f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org message, 3536f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3537f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 35389e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org PrintF(stream_, 35399e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org "%sDebugger hit %d.%s\n", 3540f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_debug_number, 3541f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org code, 3542f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org clr_normal); 3543f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3544f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3545f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3546f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Other options. 3547f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org switch (parameters & kDebuggerTracingDirectivesMask) { 3548f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TRACE_ENABLE: 3549f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() | parameters); 3550f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } 3551f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_REGS) { PrintRegisters(); } 3552f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } 3553f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3554f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TRACE_DISABLE: 3555f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(log_parameters() & ~parameters); 3556f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3557f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org case TRACE_OVERRIDE: 3558f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org set_log_parameters(parameters); 3559f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3560f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 3561f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // We don't support a one-shot LOG_DISASM. 3562f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT((parameters & LOG_DISASM) == 0); 3563f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Don't print information that is already being traced. 3564f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org parameters &= ~log_parameters(); 3565f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Print the requested information. 3566f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_SYS_REGS) PrintSystemRegisters(true); 3567f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_REGS) PrintRegisters(true); 3568f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & LOG_FP_REGS) PrintFPRegisters(true); 3569f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3570f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3571f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // The stop parameters are inlined in the code. Skip them: 3572f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Skip to the end of the message string. 35734452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org size_t size = kDebugMessageOffset + strlen(message) + 1; 35744452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); 3575f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Verify that the unreachable marker is present. 3576f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(pc_->Mask(ExceptionMask) == HLT); 3577f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable); 3578f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // - Skip past the unreachable marker. 35794452a490cca1fd780af6b2a4ca946c5d0fd108bamachenbach@chromium.org set_pc(pc_->following()); 3580f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3581f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org // Check if the debugger should break. 3582f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org if (parameters & BREAK) Debug(); 3583f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3584f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) { 35857010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org DoRuntimeCall(instr); 3586f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->ImmException() == kImmExceptionIsPrintf) { 3587a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org DoPrintf(instr); 3588f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3589f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else if (instr->ImmException() == kImmExceptionIsUnreachable) { 3590f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org fprintf(stream_, "Hit UNREACHABLE marker at PC=%p.\n", 3591f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org reinterpret_cast<void*>(pc_)); 3592f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org abort(); 3593f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3594f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } else { 3595f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org OS::DebugBreak(); 3596f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3597f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org break; 3598f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3599f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3600f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org default: 3601f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org UNIMPLEMENTED(); 3602f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org } 3603f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} 3604f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3605a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3606a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.orgvoid Simulator::DoPrintf(Instruction* instr) { 3607a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org ASSERT((instr->Mask(ExceptionMask) == HLT) && 3608a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org (instr->ImmException() == kImmExceptionIsPrintf)); 3609a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3610a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Read the arguments encoded inline in the instruction stream. 3611a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t arg_count; 3612a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t arg_pattern_list; 3613a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org STATIC_ASSERT(sizeof(*instr) == 1); 3614a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org memcpy(&arg_count, 3615a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org instr + kPrintfArgCountOffset, 3616a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org sizeof(arg_count)); 3617a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org memcpy(&arg_pattern_list, 3618a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org instr + kPrintfArgPatternListOffset, 3619a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org sizeof(arg_pattern_list)); 3620a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3621a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org ASSERT(arg_count <= kPrintfMaxArgCount); 3622a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0); 3623a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3624a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // We need to call the host printf function with a set of arguments defined by 3625a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // arg_pattern_list. Because we don't know the types and sizes of the 3626a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // arguments, this is very difficult to do in a robust and portable way. To 3627a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // work around the problem, we pick apart the format string, and print one 3628a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // format placeholder at a time. 3629a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3630a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Allocate space for the format string. We take a copy, so we can modify it. 3631a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Leave enough space for one extra character per expected argument (plus the 3632a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // '\0' termination). 3633a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org const char * format_base = reg<const char *>(0); 3634a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org ASSERT(format_base != NULL); 3635a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org size_t length = strlen(format_base) + 1; 3636a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org char * const format = new char[length + arg_count]; 3637a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3638a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // A list of chunks, each with exactly one format placeholder. 3639a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org const char * chunks[kPrintfMaxArgCount]; 3640a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3641a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Copy the format string and search for format placeholders. 3642a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t placeholder_count = 0; 3643a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org char * format_scratch = format; 3644a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org for (size_t i = 0; i < length; i++) { 3645a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (format_base[i] != '%') { 3646a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[i]; 3647a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } else { 3648a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (format_base[i + 1] == '%') { 3649a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Ignore explicit "%%" sequences. 3650a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[i]; 3651a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3652a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (placeholder_count == 0) { 3653a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // The first chunk is passed to printf using "%s", so we need to 3654a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // unescape "%%" sequences in this chunk. (Just skip the next '%'.) 3655a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org i++; 3656a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } else { 3657a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Otherwise, pass through "%%" unchanged. 3658a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[++i]; 3659a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3660a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } else { 3661a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org CHECK(placeholder_count < arg_count); 3662a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Insert '\0' before placeholders, and store their locations. 3663a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = '\0'; 3664a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org chunks[placeholder_count++] = format_scratch; 3665a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org *format_scratch++ = format_base[i]; 3666a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3667a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3668a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3669a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org ASSERT(format_scratch <= (format + length + arg_count)); 3670a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org CHECK(placeholder_count == arg_count); 3671a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3672a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Finally, call printf with each chunk, passing the appropriate register 3673a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // argument. Normally, printf returns the number of bytes transmitted, so we 3674a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // can emulate a single printf call by adding the result from each chunk. If 3675a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // any call returns a negative (error) value, though, just return that value. 3676a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3677a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org fprintf(stream_, "%s", clr_printf); 3678a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3679a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Because '\0' is inserted before each placeholder, the first string in 3680a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // 'format' contains no format placeholders and should be printed literally. 3681a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int result = fprintf(stream_, "%s", format); 3682a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int pcs_r = 1; // Start at x1. x0 holds the format string. 3683a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int pcs_f = 0; // Start at d0. 3684a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (result >= 0) { 3685a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org for (uint32_t i = 0; i < placeholder_count; i++) { 3686a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org int part_result = -1; 3687a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3688a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits); 3689a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org arg_pattern &= (1 << kPrintfArgPatternBits) - 1; 3690a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org switch (arg_pattern) { 3691a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org case kPrintfArgW: 3692a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org part_result = fprintf(stream_, chunks[i], wreg(pcs_r++)); 3693a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3694a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org case kPrintfArgX: 3695a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org part_result = fprintf(stream_, chunks[i], xreg(pcs_r++)); 3696a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3697a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org case kPrintfArgD: 3698a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org part_result = fprintf(stream_, chunks[i], dreg(pcs_f++)); 3699a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3700a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org default: UNREACHABLE(); 3701a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3702a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3703a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org if (part_result < 0) { 3704a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Handle error values. 3705a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org result = part_result; 3706a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org break; 3707a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3708a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3709a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org result += part_result; 3710a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3711a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org } 3712a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3713a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org fprintf(stream_, "%s", clr_normal); 3714a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3715a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org#ifdef DEBUG 3716a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org CorruptAllCallerSavedCPURegisters(); 3717a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org#endif 3718a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3719a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Printf returns its result in x0 (just like the C library's printf). 3720a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org set_xreg(0, result); 3721a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3722a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // The printf parameters are inlined in the code, so skip them. 3723a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org set_pc(instr->InstructionAtOffset(kPrintfLength)); 3724a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3725a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org // Set LR as if we'd just called a native printf function. 3726a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org set_lr(pc()); 3727a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3728a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org delete[] format; 3729a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org} 3730a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3731a3b66334e4dd35d9d4874d275ef9c4a756f0225cmachenbach@chromium.org 3732f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif // USE_SIMULATOR 3733f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3734f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} } // namespace v8::internal 3735f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org 3736fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#endif // V8_TARGET_ARCH_ARM64 3737