Home | History | Annotate | Download | only in arm
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <stdarg.h>
      6 #include <stdlib.h>
      7 #include <cmath>
      8 
      9 #if V8_TARGET_ARCH_ARM
     10 
     11 #include "src/arm/constants-arm.h"
     12 #include "src/arm/simulator-arm.h"
     13 #include "src/assembler.h"
     14 #include "src/base/bits.h"
     15 #include "src/codegen.h"
     16 #include "src/disasm.h"
     17 #include "src/runtime/runtime-utils.h"
     18 
     19 #if defined(USE_SIMULATOR)
     20 
     21 // Only build the simulator if not compiling for real ARM hardware.
     22 namespace v8 {
     23 namespace internal {
     24 
     25 // static
     26 base::LazyInstance<Simulator::GlobalMonitor>::type Simulator::global_monitor_ =
     27     LAZY_INSTANCE_INITIALIZER;
     28 
     29 // This macro provides a platform independent use of sscanf. The reason for
     30 // SScanF not being implemented in a platform independent way through
     31 // ::v8::internal::OS in the same way as SNPrintF is that the
     32 // Windows C Run-Time Library does not provide vsscanf.
     33 #define SScanF sscanf  // NOLINT
     34 
     35 // The ArmDebugger class is used by the simulator while debugging simulated ARM
     36 // code.
     37 class ArmDebugger {
     38  public:
     39   explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
     40 
     41   void Stop(Instruction* instr);
     42   void Debug();
     43 
     44  private:
     45   static const Instr kBreakpointInstr =
     46       (al | (7*B25) | (1*B24) | kBreakpoint);
     47   static const Instr kNopInstr = (al | (13*B21));
     48 
     49   Simulator* sim_;
     50 
     51   int32_t GetRegisterValue(int regnum);
     52   double GetRegisterPairDoubleValue(int regnum);
     53   double GetVFPDoubleRegisterValue(int regnum);
     54   bool GetValue(const char* desc, int32_t* value);
     55   bool GetVFPSingleValue(const char* desc, float* value);
     56   bool GetVFPDoubleValue(const char* desc, double* value);
     57 
     58   // Set or delete a breakpoint. Returns true if successful.
     59   bool SetBreakpoint(Instruction* breakpc);
     60   bool DeleteBreakpoint(Instruction* breakpc);
     61 
     62   // Undo and redo all breakpoints. This is needed to bracket disassembly and
     63   // execution to skip past breakpoints when run from the debugger.
     64   void UndoBreakpoints();
     65   void RedoBreakpoints();
     66 };
     67 
     68 void ArmDebugger::Stop(Instruction* instr) {
     69   // Get the stop code.
     70   uint32_t code = instr->SvcValue() & kStopCodeMask;
     71   // Print the stop message and code if it is not the default code.
     72   if (code != kMaxStopCode) {
     73     PrintF("Simulator hit stop %u\n", code);
     74   } else {
     75     PrintF("Simulator hit\n");
     76   }
     77   sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
     78   Debug();
     79 }
     80 
     81 int32_t ArmDebugger::GetRegisterValue(int regnum) {
     82   if (regnum == kPCRegister) {
     83     return sim_->get_pc();
     84   } else {
     85     return sim_->get_register(regnum);
     86   }
     87 }
     88 
     89 double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
     90   return sim_->get_double_from_register_pair(regnum);
     91 }
     92 
     93 
     94 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
     95   return sim_->get_double_from_d_register(regnum);
     96 }
     97 
     98 
     99 bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
    100   int regnum = Registers::Number(desc);
    101   if (regnum != kNoRegister) {
    102     *value = GetRegisterValue(regnum);
    103     return true;
    104   } else {
    105     if (strncmp(desc, "0x", 2) == 0) {
    106       return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
    107     } else {
    108       return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
    109     }
    110   }
    111   return false;
    112 }
    113 
    114 
    115 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
    116   bool is_double;
    117   int regnum = VFPRegisters::Number(desc, &is_double);
    118   if (regnum != kNoRegister && !is_double) {
    119     *value = sim_->get_float_from_s_register(regnum);
    120     return true;
    121   }
    122   return false;
    123 }
    124 
    125 
    126 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
    127   bool is_double;
    128   int regnum = VFPRegisters::Number(desc, &is_double);
    129   if (regnum != kNoRegister && is_double) {
    130     *value = sim_->get_double_from_d_register(regnum);
    131     return true;
    132   }
    133   return false;
    134 }
    135 
    136 
    137 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
    138   // Check if a breakpoint can be set. If not return without any side-effects.
    139   if (sim_->break_pc_ != NULL) {
    140     return false;
    141   }
    142 
    143   // Set the breakpoint.
    144   sim_->break_pc_ = breakpc;
    145   sim_->break_instr_ = breakpc->InstructionBits();
    146   // Not setting the breakpoint instruction in the code itself. It will be set
    147   // when the debugger shell continues.
    148   return true;
    149 }
    150 
    151 
    152 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
    153   if (sim_->break_pc_ != NULL) {
    154     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    155   }
    156 
    157   sim_->break_pc_ = NULL;
    158   sim_->break_instr_ = 0;
    159   return true;
    160 }
    161 
    162 
    163 void ArmDebugger::UndoBreakpoints() {
    164   if (sim_->break_pc_ != NULL) {
    165     sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
    166   }
    167 }
    168 
    169 
    170 void ArmDebugger::RedoBreakpoints() {
    171   if (sim_->break_pc_ != NULL) {
    172     sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
    173   }
    174 }
    175 
    176 
    177 void ArmDebugger::Debug() {
    178   intptr_t last_pc = -1;
    179   bool done = false;
    180 
    181 #define COMMAND_SIZE 63
    182 #define ARG_SIZE 255
    183 
    184 #define STR(a) #a
    185 #define XSTR(a) STR(a)
    186 
    187   char cmd[COMMAND_SIZE + 1];
    188   char arg1[ARG_SIZE + 1];
    189   char arg2[ARG_SIZE + 1];
    190   char* argv[3] = { cmd, arg1, arg2 };
    191 
    192   // make sure to have a proper terminating character if reaching the limit
    193   cmd[COMMAND_SIZE] = 0;
    194   arg1[ARG_SIZE] = 0;
    195   arg2[ARG_SIZE] = 0;
    196 
    197   // Undo all set breakpoints while running in the debugger shell. This will
    198   // make them invisible to all commands.
    199   UndoBreakpoints();
    200 
    201   while (!done && !sim_->has_bad_pc()) {
    202     if (last_pc != sim_->get_pc()) {
    203       disasm::NameConverter converter;
    204       disasm::Disassembler dasm(converter);
    205       // use a reasonably large buffer
    206       v8::internal::EmbeddedVector<char, 256> buffer;
    207       dasm.InstructionDecode(buffer,
    208                              reinterpret_cast<byte*>(sim_->get_pc()));
    209       PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
    210       last_pc = sim_->get_pc();
    211     }
    212     char* line = ReadLine("sim> ");
    213     if (line == NULL) {
    214       break;
    215     } else {
    216       char* last_input = sim_->last_debugger_input();
    217       if (strcmp(line, "\n") == 0 && last_input != NULL) {
    218         line = last_input;
    219       } else {
    220         // Ownership is transferred to sim_;
    221         sim_->set_last_debugger_input(line);
    222       }
    223       // Use sscanf to parse the individual parts of the command line. At the
    224       // moment no command expects more than two parameters.
    225       int argc = SScanF(line,
    226                         "%" XSTR(COMMAND_SIZE) "s "
    227                         "%" XSTR(ARG_SIZE) "s "
    228                         "%" XSTR(ARG_SIZE) "s",
    229                         cmd, arg1, arg2);
    230       if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
    231         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
    232       } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
    233         // Execute the one instruction we broke at with breakpoints disabled.
    234         sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
    235         // Leave the debugger shell.
    236         done = true;
    237       } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
    238         if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
    239           int32_t value;
    240           float svalue;
    241           double dvalue;
    242           if (strcmp(arg1, "all") == 0) {
    243             for (int i = 0; i < kNumRegisters; i++) {
    244               value = GetRegisterValue(i);
    245               PrintF(
    246                   "%3s: 0x%08x %10d",
    247                   RegisterConfiguration::Crankshaft()->GetGeneralRegisterName(
    248                       i),
    249                   value, value);
    250               if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
    251                   i < 8 &&
    252                   (i % 2) == 0) {
    253                 dvalue = GetRegisterPairDoubleValue(i);
    254                 PrintF(" (%f)\n", dvalue);
    255               } else {
    256                 PrintF("\n");
    257               }
    258             }
    259             for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
    260               dvalue = GetVFPDoubleRegisterValue(i);
    261               uint64_t as_words = bit_cast<uint64_t>(dvalue);
    262               PrintF("%3s: %f 0x%08x %08x\n",
    263                      VFPRegisters::Name(i, true),
    264                      dvalue,
    265                      static_cast<uint32_t>(as_words >> 32),
    266                      static_cast<uint32_t>(as_words & 0xffffffff));
    267             }
    268           } else {
    269             if (GetValue(arg1, &value)) {
    270               PrintF("%s: 0x%08x %d \n", arg1, value, value);
    271             } else if (GetVFPSingleValue(arg1, &svalue)) {
    272               uint32_t as_word = bit_cast<uint32_t>(svalue);
    273               PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
    274             } else if (GetVFPDoubleValue(arg1, &dvalue)) {
    275               uint64_t as_words = bit_cast<uint64_t>(dvalue);
    276               PrintF("%s: %f 0x%08x %08x\n",
    277                      arg1,
    278                      dvalue,
    279                      static_cast<uint32_t>(as_words >> 32),
    280                      static_cast<uint32_t>(as_words & 0xffffffff));
    281             } else {
    282               PrintF("%s unrecognized\n", arg1);
    283             }
    284           }
    285         } else {
    286           PrintF("print <register>\n");
    287         }
    288       } else if ((strcmp(cmd, "po") == 0)
    289                  || (strcmp(cmd, "printobject") == 0)) {
    290         if (argc == 2) {
    291           int32_t value;
    292           OFStream os(stdout);
    293           if (GetValue(arg1, &value)) {
    294             Object* obj = reinterpret_cast<Object*>(value);
    295             os << arg1 << ": \n";
    296 #ifdef DEBUG
    297             obj->Print(os);
    298             os << "\n";
    299 #else
    300             os << Brief(obj) << "\n";
    301 #endif
    302           } else {
    303             os << arg1 << " unrecognized\n";
    304           }
    305         } else {
    306           PrintF("printobject <value>\n");
    307         }
    308       } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
    309         int32_t* cur = NULL;
    310         int32_t* end = NULL;
    311         int next_arg = 1;
    312 
    313         if (strcmp(cmd, "stack") == 0) {
    314           cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
    315         } else {  // "mem"
    316           int32_t value;
    317           if (!GetValue(arg1, &value)) {
    318             PrintF("%s unrecognized\n", arg1);
    319             continue;
    320           }
    321           cur = reinterpret_cast<int32_t*>(value);
    322           next_arg++;
    323         }
    324 
    325         int32_t words;
    326         if (argc == next_arg) {
    327           words = 10;
    328         } else {
    329           if (!GetValue(argv[next_arg], &words)) {
    330             words = 10;
    331           }
    332         }
    333         end = cur + words;
    334 
    335         while (cur < end) {
    336           PrintF("  0x%08" V8PRIxPTR ":  0x%08x %10d",
    337                  reinterpret_cast<intptr_t>(cur), *cur, *cur);
    338           HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
    339           int value = *cur;
    340           Heap* current_heap = sim_->isolate_->heap();
    341           if (((value & 1) == 0) ||
    342               current_heap->ContainsSlow(obj->address())) {
    343             PrintF(" (");
    344             if ((value & 1) == 0) {
    345               PrintF("smi %d", value / 2);
    346             } else {
    347               obj->ShortPrint();
    348             }
    349             PrintF(")");
    350           }
    351           PrintF("\n");
    352           cur++;
    353         }
    354       } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
    355         disasm::NameConverter converter;
    356         disasm::Disassembler dasm(converter);
    357         // use a reasonably large buffer
    358         v8::internal::EmbeddedVector<char, 256> buffer;
    359 
    360         byte* prev = NULL;
    361         byte* cur = NULL;
    362         byte* end = NULL;
    363 
    364         if (argc == 1) {
    365           cur = reinterpret_cast<byte*>(sim_->get_pc());
    366           end = cur + (10 * Instruction::kInstrSize);
    367         } else if (argc == 2) {
    368           int regnum = Registers::Number(arg1);
    369           if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
    370             // The argument is an address or a register name.
    371             int32_t value;
    372             if (GetValue(arg1, &value)) {
    373               cur = reinterpret_cast<byte*>(value);
    374               // Disassemble 10 instructions at <arg1>.
    375               end = cur + (10 * Instruction::kInstrSize);
    376             }
    377           } else {
    378             // The argument is the number of instructions.
    379             int32_t value;
    380             if (GetValue(arg1, &value)) {
    381               cur = reinterpret_cast<byte*>(sim_->get_pc());
    382               // Disassemble <arg1> instructions.
    383               end = cur + (value * Instruction::kInstrSize);
    384             }
    385           }
    386         } else {
    387           int32_t value1;
    388           int32_t value2;
    389           if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
    390             cur = reinterpret_cast<byte*>(value1);
    391             end = cur + (value2 * Instruction::kInstrSize);
    392           }
    393         }
    394 
    395         while (cur < end) {
    396           prev = cur;
    397           cur += dasm.InstructionDecode(buffer, cur);
    398           PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(prev),
    399                  buffer.start());
    400         }
    401       } else if (strcmp(cmd, "gdb") == 0) {
    402         PrintF("relinquishing control to gdb\n");
    403         v8::base::OS::DebugBreak();
    404         PrintF("regaining control from gdb\n");
    405       } else if (strcmp(cmd, "break") == 0) {
    406         if (argc == 2) {
    407           int32_t value;
    408           if (GetValue(arg1, &value)) {
    409             if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
    410               PrintF("setting breakpoint failed\n");
    411             }
    412           } else {
    413             PrintF("%s unrecognized\n", arg1);
    414           }
    415         } else {
    416           PrintF("break <address>\n");
    417         }
    418       } else if (strcmp(cmd, "del") == 0) {
    419         if (!DeleteBreakpoint(NULL)) {
    420           PrintF("deleting breakpoint failed\n");
    421         }
    422       } else if (strcmp(cmd, "flags") == 0) {
    423         PrintF("N flag: %d; ", sim_->n_flag_);
    424         PrintF("Z flag: %d; ", sim_->z_flag_);
    425         PrintF("C flag: %d; ", sim_->c_flag_);
    426         PrintF("V flag: %d\n", sim_->v_flag_);
    427         PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
    428         PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
    429         PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
    430         PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
    431         PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
    432       } else if (strcmp(cmd, "stop") == 0) {
    433         int32_t value;
    434         intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
    435         Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
    436         Instruction* msg_address =
    437           reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
    438         if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
    439           // Remove the current stop.
    440           if (sim_->isStopInstruction(stop_instr)) {
    441             stop_instr->SetInstructionBits(kNopInstr);
    442             msg_address->SetInstructionBits(kNopInstr);
    443           } else {
    444             PrintF("Not at debugger stop.\n");
    445           }
    446         } else if (argc == 3) {
    447           // Print information about all/the specified breakpoint(s).
    448           if (strcmp(arg1, "info") == 0) {
    449             if (strcmp(arg2, "all") == 0) {
    450               PrintF("Stop information:\n");
    451               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
    452                 sim_->PrintStopInfo(i);
    453               }
    454             } else if (GetValue(arg2, &value)) {
    455               sim_->PrintStopInfo(value);
    456             } else {
    457               PrintF("Unrecognized argument.\n");
    458             }
    459           } else if (strcmp(arg1, "enable") == 0) {
    460             // Enable all/the specified breakpoint(s).
    461             if (strcmp(arg2, "all") == 0) {
    462               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
    463                 sim_->EnableStop(i);
    464               }
    465             } else if (GetValue(arg2, &value)) {
    466               sim_->EnableStop(value);
    467             } else {
    468               PrintF("Unrecognized argument.\n");
    469             }
    470           } else if (strcmp(arg1, "disable") == 0) {
    471             // Disable all/the specified breakpoint(s).
    472             if (strcmp(arg2, "all") == 0) {
    473               for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
    474                 sim_->DisableStop(i);
    475               }
    476             } else if (GetValue(arg2, &value)) {
    477               sim_->DisableStop(value);
    478             } else {
    479               PrintF("Unrecognized argument.\n");
    480             }
    481           }
    482         } else {
    483           PrintF("Wrong usage. Use help command for more information.\n");
    484         }
    485       } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
    486         ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
    487         PrintF("Trace of executed instructions is %s\n",
    488                ::v8::internal::FLAG_trace_sim ? "on" : "off");
    489       } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
    490         PrintF("cont\n");
    491         PrintF("  continue execution (alias 'c')\n");
    492         PrintF("stepi\n");
    493         PrintF("  step one instruction (alias 'si')\n");
    494         PrintF("print <register>\n");
    495         PrintF("  print register content (alias 'p')\n");
    496         PrintF("  use register name 'all' to print all registers\n");
    497         PrintF("  add argument 'fp' to print register pair double values\n");
    498         PrintF("printobject <register>\n");
    499         PrintF("  print an object from a register (alias 'po')\n");
    500         PrintF("flags\n");
    501         PrintF("  print flags\n");
    502         PrintF("stack [<words>]\n");
    503         PrintF("  dump stack content, default dump 10 words)\n");
    504         PrintF("mem <address> [<words>]\n");
    505         PrintF("  dump memory content, default dump 10 words)\n");
    506         PrintF("disasm [<instructions>]\n");
    507         PrintF("disasm [<address/register>]\n");
    508         PrintF("disasm [[<address/register>] <instructions>]\n");
    509         PrintF("  disassemble code, default is 10 instructions\n");
    510         PrintF("  from pc (alias 'di')\n");
    511         PrintF("gdb\n");
    512         PrintF("  enter gdb\n");
    513         PrintF("break <address>\n");
    514         PrintF("  set a break point on the address\n");
    515         PrintF("del\n");
    516         PrintF("  delete the breakpoint\n");
    517         PrintF("trace (alias 't')\n");
    518         PrintF("  toogle the tracing of all executed statements\n");
    519         PrintF("stop feature:\n");
    520         PrintF("  Description:\n");
    521         PrintF("    Stops are debug instructions inserted by\n");
    522         PrintF("    the Assembler::stop() function.\n");
    523         PrintF("    When hitting a stop, the Simulator will\n");
    524         PrintF("    stop and and give control to the ArmDebugger.\n");
    525         PrintF("    The first %d stop codes are watched:\n",
    526                Simulator::kNumOfWatchedStops);
    527         PrintF("    - They can be enabled / disabled: the Simulator\n");
    528         PrintF("      will / won't stop when hitting them.\n");
    529         PrintF("    - The Simulator keeps track of how many times they \n");
    530         PrintF("      are met. (See the info command.) Going over a\n");
    531         PrintF("      disabled stop still increases its counter. \n");
    532         PrintF("  Commands:\n");
    533         PrintF("    stop info all/<code> : print infos about number <code>\n");
    534         PrintF("      or all stop(s).\n");
    535         PrintF("    stop enable/disable all/<code> : enables / disables\n");
    536         PrintF("      all or number <code> stop(s)\n");
    537         PrintF("    stop unstop\n");
    538         PrintF("      ignore the stop instruction at the current location\n");
    539         PrintF("      from now on\n");
    540       } else {
    541         PrintF("Unknown command: %s\n", cmd);
    542       }
    543     }
    544   }
    545 
    546   // Add all the breakpoints back to stop execution and enter the debugger
    547   // shell when hit.
    548   RedoBreakpoints();
    549 
    550 #undef COMMAND_SIZE
    551 #undef ARG_SIZE
    552 
    553 #undef STR
    554 #undef XSTR
    555 }
    556 
    557 
    558 static bool ICacheMatch(void* one, void* two) {
    559   DCHECK((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
    560   DCHECK((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
    561   return one == two;
    562 }
    563 
    564 
    565 static uint32_t ICacheHash(void* key) {
    566   return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
    567 }
    568 
    569 
    570 static bool AllOnOnePage(uintptr_t start, int size) {
    571   intptr_t start_page = (start & ~CachePage::kPageMask);
    572   intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
    573   return start_page == end_page;
    574 }
    575 
    576 void Simulator::set_last_debugger_input(char* input) {
    577   DeleteArray(last_debugger_input_);
    578   last_debugger_input_ = input;
    579 }
    580 
    581 void Simulator::FlushICache(base::CustomMatcherHashMap* i_cache,
    582                             void* start_addr, size_t size) {
    583   intptr_t start = reinterpret_cast<intptr_t>(start_addr);
    584   int intra_line = (start & CachePage::kLineMask);
    585   start -= intra_line;
    586   size += intra_line;
    587   size = ((size - 1) | CachePage::kLineMask) + 1;
    588   int offset = (start & CachePage::kPageMask);
    589   while (!AllOnOnePage(start, size - 1)) {
    590     int bytes_to_flush = CachePage::kPageSize - offset;
    591     FlushOnePage(i_cache, start, bytes_to_flush);
    592     start += bytes_to_flush;
    593     size -= bytes_to_flush;
    594     DCHECK_EQ(0, start & CachePage::kPageMask);
    595     offset = 0;
    596   }
    597   if (size != 0) {
    598     FlushOnePage(i_cache, start, size);
    599   }
    600 }
    601 
    602 CachePage* Simulator::GetCachePage(base::CustomMatcherHashMap* i_cache,
    603                                    void* page) {
    604   base::HashMap::Entry* entry = i_cache->LookupOrInsert(page, ICacheHash(page));
    605   if (entry->value == NULL) {
    606     CachePage* new_page = new CachePage();
    607     entry->value = new_page;
    608   }
    609   return reinterpret_cast<CachePage*>(entry->value);
    610 }
    611 
    612 
    613 // Flush from start up to and not including start + size.
    614 void Simulator::FlushOnePage(base::CustomMatcherHashMap* i_cache,
    615                              intptr_t start, int size) {
    616   DCHECK(size <= CachePage::kPageSize);
    617   DCHECK(AllOnOnePage(start, size - 1));
    618   DCHECK((start & CachePage::kLineMask) == 0);
    619   DCHECK((size & CachePage::kLineMask) == 0);
    620   void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
    621   int offset = (start & CachePage::kPageMask);
    622   CachePage* cache_page = GetCachePage(i_cache, page);
    623   char* valid_bytemap = cache_page->ValidityByte(offset);
    624   memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
    625 }
    626 
    627 void Simulator::CheckICache(base::CustomMatcherHashMap* i_cache,
    628                             Instruction* instr) {
    629   intptr_t address = reinterpret_cast<intptr_t>(instr);
    630   void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
    631   void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
    632   int offset = (address & CachePage::kPageMask);
    633   CachePage* cache_page = GetCachePage(i_cache, page);
    634   char* cache_valid_byte = cache_page->ValidityByte(offset);
    635   bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
    636   char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
    637   if (cache_hit) {
    638     // Check that the data in memory matches the contents of the I-cache.
    639     CHECK_EQ(0,
    640              memcmp(reinterpret_cast<void*>(instr),
    641                     cache_page->CachedData(offset), Instruction::kInstrSize));
    642   } else {
    643     // Cache miss.  Load memory into the cache.
    644     memcpy(cached_line, line, CachePage::kLineLength);
    645     *cache_valid_byte = CachePage::LINE_VALID;
    646   }
    647 }
    648 
    649 
    650 void Simulator::Initialize(Isolate* isolate) {
    651   if (isolate->simulator_initialized()) return;
    652   isolate->set_simulator_initialized(true);
    653   ::v8::internal::ExternalReference::set_redirector(isolate,
    654                                                     &RedirectExternalReference);
    655 }
    656 
    657 
    658 Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
    659   i_cache_ = isolate_->simulator_i_cache();
    660   if (i_cache_ == NULL) {
    661     i_cache_ = new base::CustomMatcherHashMap(&ICacheMatch);
    662     isolate_->set_simulator_i_cache(i_cache_);
    663   }
    664   Initialize(isolate);
    665   // Set up simulator support first. Some of this information is needed to
    666   // setup the architecture state.
    667   size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
    668   stack_ = reinterpret_cast<char*>(malloc(stack_size));
    669   pc_modified_ = false;
    670   icount_ = 0;
    671   break_pc_ = NULL;
    672   break_instr_ = 0;
    673 
    674   // Set up architecture state.
    675   // All registers are initialized to zero to start with.
    676   for (int i = 0; i < num_registers; i++) {
    677     registers_[i] = 0;
    678   }
    679   n_flag_ = false;
    680   z_flag_ = false;
    681   c_flag_ = false;
    682   v_flag_ = false;
    683 
    684   // Initializing VFP registers.
    685   // All registers are initialized to zero to start with
    686   // even though s_registers_ & d_registers_ share the same
    687   // physical registers in the target.
    688   for (int i = 0; i < num_d_registers * 2; i++) {
    689     vfp_registers_[i] = 0;
    690   }
    691   n_flag_FPSCR_ = false;
    692   z_flag_FPSCR_ = false;
    693   c_flag_FPSCR_ = false;
    694   v_flag_FPSCR_ = false;
    695   FPSCR_rounding_mode_ = RN;
    696   FPSCR_default_NaN_mode_ = false;
    697 
    698   inv_op_vfp_flag_ = false;
    699   div_zero_vfp_flag_ = false;
    700   overflow_vfp_flag_ = false;
    701   underflow_vfp_flag_ = false;
    702   inexact_vfp_flag_ = false;
    703 
    704   // The sp is initialized to point to the bottom (high address) of the
    705   // allocated stack area. To be safe in potential stack underflows we leave
    706   // some buffer below.
    707   registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
    708   // The lr and pc are initialized to a known bad value that will cause an
    709   // access violation if the simulator ever tries to execute it.
    710   registers_[pc] = bad_lr;
    711   registers_[lr] = bad_lr;
    712 
    713   last_debugger_input_ = NULL;
    714 }
    715 
    716 Simulator::~Simulator() {
    717   global_monitor_.Pointer()->RemoveProcessor(&global_monitor_processor_);
    718   free(stack_);
    719 }
    720 
    721 // When the generated code calls an external reference we need to catch that in
    722 // the simulator.  The external reference will be a function compiled for the
    723 // host architecture.  We need to call that function instead of trying to
    724 // execute it with the simulator.  We do that by redirecting the external
    725 // reference to a svc (Supervisor Call) instruction that is handled by
    726 // the simulator.  We write the original destination of the jump just at a known
    727 // offset from the svc instruction so the simulator knows what to call.
    728 class Redirection {
    729  public:
    730   Redirection(Isolate* isolate, void* external_function,
    731               ExternalReference::Type type)
    732       : external_function_(external_function),
    733         swi_instruction_(al | (0xf * B24) | kCallRtRedirected),
    734         type_(type),
    735         next_(NULL) {
    736     next_ = isolate->simulator_redirection();
    737     Simulator::current(isolate)->
    738         FlushICache(isolate->simulator_i_cache(),
    739                     reinterpret_cast<void*>(&swi_instruction_),
    740                     Instruction::kInstrSize);
    741     isolate->set_simulator_redirection(this);
    742   }
    743 
    744   void* address_of_swi_instruction() {
    745     return reinterpret_cast<void*>(&swi_instruction_);
    746   }
    747 
    748   void* external_function() { return external_function_; }
    749   ExternalReference::Type type() { return type_; }
    750 
    751   static Redirection* Get(Isolate* isolate, void* external_function,
    752                           ExternalReference::Type type) {
    753     Redirection* current = isolate->simulator_redirection();
    754     for (; current != NULL; current = current->next_) {
    755       if (current->external_function_ == external_function) {
    756         DCHECK_EQ(current->type(), type);
    757         return current;
    758       }
    759     }
    760     return new Redirection(isolate, external_function, type);
    761   }
    762 
    763   static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
    764     char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
    765     char* addr_of_redirection =
    766         addr_of_swi - offsetof(Redirection, swi_instruction_);
    767     return reinterpret_cast<Redirection*>(addr_of_redirection);
    768   }
    769 
    770   static void* ReverseRedirection(int32_t reg) {
    771     Redirection* redirection = FromSwiInstruction(
    772         reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
    773     return redirection->external_function();
    774   }
    775 
    776   static void DeleteChain(Redirection* redirection) {
    777     while (redirection != nullptr) {
    778       Redirection* next = redirection->next_;
    779       delete redirection;
    780       redirection = next;
    781     }
    782   }
    783 
    784  private:
    785   void* external_function_;
    786   uint32_t swi_instruction_;
    787   ExternalReference::Type type_;
    788   Redirection* next_;
    789 };
    790 
    791 
    792 // static
    793 void Simulator::TearDown(base::CustomMatcherHashMap* i_cache,
    794                          Redirection* first) {
    795   Redirection::DeleteChain(first);
    796   if (i_cache != nullptr) {
    797     for (base::HashMap::Entry* entry = i_cache->Start(); entry != nullptr;
    798          entry = i_cache->Next(entry)) {
    799       delete static_cast<CachePage*>(entry->value);
    800     }
    801     delete i_cache;
    802   }
    803 }
    804 
    805 
    806 void* Simulator::RedirectExternalReference(Isolate* isolate,
    807                                            void* external_function,
    808                                            ExternalReference::Type type) {
    809   Redirection* redirection = Redirection::Get(isolate, external_function, type);
    810   return redirection->address_of_swi_instruction();
    811 }
    812 
    813 
    814 // Get the active Simulator for the current thread.
    815 Simulator* Simulator::current(Isolate* isolate) {
    816   v8::internal::Isolate::PerIsolateThreadData* isolate_data =
    817       isolate->FindOrAllocatePerThreadDataForThisThread();
    818   DCHECK(isolate_data != NULL);
    819 
    820   Simulator* sim = isolate_data->simulator();
    821   if (sim == NULL) {
    822     // TODO(146): delete the simulator object when a thread/isolate goes away.
    823     sim = new Simulator(isolate);
    824     isolate_data->set_simulator(sim);
    825   }
    826   return sim;
    827 }
    828 
    829 
    830 // Sets the register in the architecture state. It will also deal with updating
    831 // Simulator internal state for special registers such as PC.
    832 void Simulator::set_register(int reg, int32_t value) {
    833   DCHECK((reg >= 0) && (reg < num_registers));
    834   if (reg == pc) {
    835     pc_modified_ = true;
    836   }
    837   registers_[reg] = value;
    838 }
    839 
    840 
    841 // Get the register from the architecture state. This function does handle
    842 // the special case of accessing the PC register.
    843 int32_t Simulator::get_register(int reg) const {
    844   DCHECK((reg >= 0) && (reg < num_registers));
    845   // Stupid code added to avoid bug in GCC.
    846   // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
    847   if (reg >= num_registers) return 0;
    848   // End stupid code.
    849   return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
    850 }
    851 
    852 
    853 double Simulator::get_double_from_register_pair(int reg) {
    854   DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
    855 
    856   double dm_val = 0.0;
    857   // Read the bits from the unsigned integer register_[] array
    858   // into the double precision floating point value and return it.
    859   char buffer[2 * sizeof(vfp_registers_[0])];
    860   memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
    861   memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
    862   return(dm_val);
    863 }
    864 
    865 
    866 void Simulator::set_register_pair_from_double(int reg, double* value) {
    867   DCHECK((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
    868   memcpy(registers_ + reg, value, sizeof(*value));
    869 }
    870 
    871 
    872 void Simulator::set_dw_register(int dreg, const int* dbl) {
    873   DCHECK((dreg >= 0) && (dreg < num_d_registers));
    874   registers_[dreg] = dbl[0];
    875   registers_[dreg + 1] = dbl[1];
    876 }
    877 
    878 
    879 void Simulator::get_d_register(int dreg, uint64_t* value) {
    880   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
    881   memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
    882 }
    883 
    884 
    885 void Simulator::set_d_register(int dreg, const uint64_t* value) {
    886   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
    887   memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
    888 }
    889 
    890 
    891 void Simulator::get_d_register(int dreg, uint32_t* value) {
    892   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
    893   memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
    894 }
    895 
    896 
    897 void Simulator::set_d_register(int dreg, const uint32_t* value) {
    898   DCHECK((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
    899   memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
    900 }
    901 
    902 template <typename T>
    903 void Simulator::get_q_register(int qreg, T* value) {
    904   DCHECK((qreg >= 0) && (qreg < num_q_registers));
    905   memcpy(value, vfp_registers_ + qreg * 4, kSimd128Size);
    906 }
    907 
    908 template <typename T>
    909 void Simulator::set_q_register(int qreg, const T* value) {
    910   DCHECK((qreg >= 0) && (qreg < num_q_registers));
    911   memcpy(vfp_registers_ + qreg * 4, value, kSimd128Size);
    912 }
    913 
    914 
    915 // Raw access to the PC register.
    916 void Simulator::set_pc(int32_t value) {
    917   pc_modified_ = true;
    918   registers_[pc] = value;
    919 }
    920 
    921 
    922 bool Simulator::has_bad_pc() const {
    923   return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
    924 }
    925 
    926 
    927 // Raw access to the PC register without the special adjustment when reading.
    928 int32_t Simulator::get_pc() const {
    929   return registers_[pc];
    930 }
    931 
    932 
    933 // Getting from and setting into VFP registers.
    934 void Simulator::set_s_register(int sreg, unsigned int value) {
    935   DCHECK((sreg >= 0) && (sreg < num_s_registers));
    936   vfp_registers_[sreg] = value;
    937 }
    938 
    939 
    940 unsigned int Simulator::get_s_register(int sreg) const {
    941   DCHECK((sreg >= 0) && (sreg < num_s_registers));
    942   return vfp_registers_[sreg];
    943 }
    944 
    945 
    946 template<class InputType, int register_size>
    947 void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
    948   DCHECK(reg_index >= 0);
    949   if (register_size == 1) DCHECK(reg_index < num_s_registers);
    950   if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
    951 
    952   char buffer[register_size * sizeof(vfp_registers_[0])];
    953   memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
    954   memcpy(&vfp_registers_[reg_index * register_size], buffer,
    955          register_size * sizeof(vfp_registers_[0]));
    956 }
    957 
    958 
    959 template<class ReturnType, int register_size>
    960 ReturnType Simulator::GetFromVFPRegister(int reg_index) {
    961   DCHECK(reg_index >= 0);
    962   if (register_size == 1) DCHECK(reg_index < num_s_registers);
    963   if (register_size == 2) DCHECK(reg_index < DwVfpRegister::NumRegisters());
    964 
    965   ReturnType value = 0;
    966   char buffer[register_size * sizeof(vfp_registers_[0])];
    967   memcpy(buffer, &vfp_registers_[register_size * reg_index],
    968          register_size * sizeof(vfp_registers_[0]));
    969   memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
    970   return value;
    971 }
    972 
    973 void Simulator::SetSpecialRegister(SRegisterFieldMask reg_and_mask,
    974                                    uint32_t value) {
    975   // Only CPSR_f is implemented. Of that, only N, Z, C and V are implemented.
    976   if ((reg_and_mask == CPSR_f) && ((value & ~kSpecialCondition) == 0)) {
    977     n_flag_ = ((value & (1 << 31)) != 0);
    978     z_flag_ = ((value & (1 << 30)) != 0);
    979     c_flag_ = ((value & (1 << 29)) != 0);
    980     v_flag_ = ((value & (1 << 28)) != 0);
    981   } else {
    982     UNIMPLEMENTED();
    983   }
    984 }
    985 
    986 uint32_t Simulator::GetFromSpecialRegister(SRegister reg) {
    987   uint32_t result = 0;
    988   // Only CPSR_f is implemented.
    989   if (reg == CPSR) {
    990     if (n_flag_) result |= (1 << 31);
    991     if (z_flag_) result |= (1 << 30);
    992     if (c_flag_) result |= (1 << 29);
    993     if (v_flag_) result |= (1 << 28);
    994   } else {
    995     UNIMPLEMENTED();
    996   }
    997   return result;
    998 }
    999 
   1000 // Runtime FP routines take:
   1001 // - two double arguments
   1002 // - one double argument and zero or one integer arguments.
   1003 // All are consructed here from r0-r3 or d0, d1 and r0.
   1004 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
   1005   if (use_eabi_hardfloat()) {
   1006     *x = get_double_from_d_register(0);
   1007     *y = get_double_from_d_register(1);
   1008     *z = get_register(0);
   1009   } else {
   1010     // Registers 0 and 1 -> x.
   1011     *x = get_double_from_register_pair(0);
   1012     // Register 2 and 3 -> y.
   1013     *y = get_double_from_register_pair(2);
   1014     // Register 2 -> z
   1015     *z = get_register(2);
   1016   }
   1017 }
   1018 
   1019 
   1020 // The return value is either in r0/r1 or d0.
   1021 void Simulator::SetFpResult(const double& result) {
   1022   if (use_eabi_hardfloat()) {
   1023     char buffer[2 * sizeof(vfp_registers_[0])];
   1024     memcpy(buffer, &result, sizeof(buffer));
   1025     // Copy result to d0.
   1026     memcpy(vfp_registers_, buffer, sizeof(buffer));
   1027   } else {
   1028     char buffer[2 * sizeof(registers_[0])];
   1029     memcpy(buffer, &result, sizeof(buffer));
   1030     // Copy result to r0 and r1.
   1031     memcpy(registers_, buffer, sizeof(buffer));
   1032   }
   1033 }
   1034 
   1035 
   1036 void Simulator::TrashCallerSaveRegisters() {
   1037   // We don't trash the registers with the return value.
   1038   registers_[2] = 0x50Bad4U;
   1039   registers_[3] = 0x50Bad4U;
   1040   registers_[12] = 0x50Bad4U;
   1041 }
   1042 
   1043 
   1044 int Simulator::ReadW(int32_t addr, Instruction* instr) {
   1045   // All supported ARM targets allow unaligned accesses, so we don't need to
   1046   // check the alignment here.
   1047   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1048   local_monitor_.NotifyLoad(addr);
   1049   intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1050   return *ptr;
   1051 }
   1052 
   1053 int Simulator::ReadExW(int32_t addr, Instruction* instr) {
   1054   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1055   local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
   1056   global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
   1057                                                    &global_monitor_processor_);
   1058   intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1059   return *ptr;
   1060 }
   1061 
   1062 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
   1063   // All supported ARM targets allow unaligned accesses, so we don't need to
   1064   // check the alignment here.
   1065   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1066   local_monitor_.NotifyStore(addr);
   1067   global_monitor_.Pointer()->NotifyStore_Locked(addr,
   1068                                                 &global_monitor_processor_);
   1069   intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1070   *ptr = value;
   1071 }
   1072 
   1073 int Simulator::WriteExW(int32_t addr, int value, Instruction* instr) {
   1074   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1075   if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
   1076       global_monitor_.Pointer()->NotifyStoreExcl_Locked(
   1077           addr, &global_monitor_processor_)) {
   1078     intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
   1079     *ptr = value;
   1080     return 0;
   1081   } else {
   1082     return 1;
   1083   }
   1084 }
   1085 
   1086 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
   1087   // All supported ARM targets allow unaligned accesses, so we don't need to
   1088   // check the alignment here.
   1089   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1090   local_monitor_.NotifyLoad(addr);
   1091   uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   1092   return *ptr;
   1093 }
   1094 
   1095 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
   1096   // All supported ARM targets allow unaligned accesses, so we don't need to
   1097   // check the alignment here.
   1098   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1099   local_monitor_.NotifyLoad(addr);
   1100   int16_t* ptr = reinterpret_cast<int16_t*>(addr);
   1101   return *ptr;
   1102 }
   1103 
   1104 uint16_t Simulator::ReadExHU(int32_t addr, Instruction* instr) {
   1105   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1106   local_monitor_.NotifyLoadExcl(addr, TransactionSize::HalfWord);
   1107   global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
   1108                                                    &global_monitor_processor_);
   1109   uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   1110   return *ptr;
   1111 }
   1112 
   1113 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
   1114   // All supported ARM targets allow unaligned accesses, so we don't need to
   1115   // check the alignment here.
   1116   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1117   local_monitor_.NotifyStore(addr);
   1118   global_monitor_.Pointer()->NotifyStore_Locked(addr,
   1119                                                 &global_monitor_processor_);
   1120   uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   1121   *ptr = value;
   1122 }
   1123 
   1124 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
   1125   // All supported ARM targets allow unaligned accesses, so we don't need to
   1126   // check the alignment here.
   1127   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1128   local_monitor_.NotifyStore(addr);
   1129   global_monitor_.Pointer()->NotifyStore_Locked(addr,
   1130                                                 &global_monitor_processor_);
   1131   int16_t* ptr = reinterpret_cast<int16_t*>(addr);
   1132   *ptr = value;
   1133 }
   1134 
   1135 int Simulator::WriteExH(int32_t addr, uint16_t value, Instruction* instr) {
   1136   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1137   if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::HalfWord) &&
   1138       global_monitor_.Pointer()->NotifyStoreExcl_Locked(
   1139           addr, &global_monitor_processor_)) {
   1140     uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
   1141     *ptr = value;
   1142     return 0;
   1143   } else {
   1144     return 1;
   1145   }
   1146 }
   1147 
   1148 uint8_t Simulator::ReadBU(int32_t addr) {
   1149   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1150   local_monitor_.NotifyLoad(addr);
   1151   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   1152   return *ptr;
   1153 }
   1154 
   1155 int8_t Simulator::ReadB(int32_t addr) {
   1156   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1157   local_monitor_.NotifyLoad(addr);
   1158   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   1159   return *ptr;
   1160 }
   1161 
   1162 uint8_t Simulator::ReadExBU(int32_t addr) {
   1163   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1164   local_monitor_.NotifyLoadExcl(addr, TransactionSize::Byte);
   1165   global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
   1166                                                    &global_monitor_processor_);
   1167   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   1168   return *ptr;
   1169 }
   1170 
   1171 void Simulator::WriteB(int32_t addr, uint8_t value) {
   1172   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1173   local_monitor_.NotifyStore(addr);
   1174   global_monitor_.Pointer()->NotifyStore_Locked(addr,
   1175                                                 &global_monitor_processor_);
   1176   uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   1177   *ptr = value;
   1178 }
   1179 
   1180 void Simulator::WriteB(int32_t addr, int8_t value) {
   1181   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1182   local_monitor_.NotifyStore(addr);
   1183   global_monitor_.Pointer()->NotifyStore_Locked(addr,
   1184                                                 &global_monitor_processor_);
   1185   int8_t* ptr = reinterpret_cast<int8_t*>(addr);
   1186   *ptr = value;
   1187 }
   1188 
   1189 int Simulator::WriteExB(int32_t addr, uint8_t value) {
   1190   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1191   if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Byte) &&
   1192       global_monitor_.Pointer()->NotifyStoreExcl_Locked(
   1193           addr, &global_monitor_processor_)) {
   1194     uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
   1195     *ptr = value;
   1196     return 0;
   1197   } else {
   1198     return 1;
   1199   }
   1200 }
   1201 
   1202 int32_t* Simulator::ReadDW(int32_t addr) {
   1203   // All supported ARM targets allow unaligned accesses, so we don't need to
   1204   // check the alignment here.
   1205   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1206   local_monitor_.NotifyLoad(addr);
   1207   int32_t* ptr = reinterpret_cast<int32_t*>(addr);
   1208   return ptr;
   1209 }
   1210 
   1211 
   1212 void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
   1213   // All supported ARM targets allow unaligned accesses, so we don't need to
   1214   // check the alignment here.
   1215   base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
   1216   local_monitor_.NotifyStore(addr);
   1217   global_monitor_.Pointer()->NotifyStore_Locked(addr,
   1218                                                 &global_monitor_processor_);
   1219   int32_t* ptr = reinterpret_cast<int32_t*>(addr);
   1220   *ptr++ = value1;
   1221   *ptr = value2;
   1222 }
   1223 
   1224 
   1225 // Returns the limit of the stack area to enable checking for stack overflows.
   1226 uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
   1227   // The simulator uses a separate JS stack. If we have exhausted the C stack,
   1228   // we also drop down the JS limit to reflect the exhaustion on the JS stack.
   1229   if (GetCurrentStackPosition() < c_limit) {
   1230     return reinterpret_cast<uintptr_t>(get_sp());
   1231   }
   1232 
   1233   // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
   1234   // to prevent overrunning the stack when pushing values.
   1235   return reinterpret_cast<uintptr_t>(stack_) + 1024;
   1236 }
   1237 
   1238 
   1239 // Unsupported instructions use Format to print an error and stop execution.
   1240 void Simulator::Format(Instruction* instr, const char* format) {
   1241   PrintF("Simulator found unsupported instruction:\n 0x%08" V8PRIxPTR ": %s\n",
   1242          reinterpret_cast<intptr_t>(instr), format);
   1243   UNIMPLEMENTED();
   1244 }
   1245 
   1246 
   1247 // Checks if the current instruction should be executed based on its
   1248 // condition bits.
   1249 bool Simulator::ConditionallyExecute(Instruction* instr) {
   1250   switch (instr->ConditionField()) {
   1251     case eq: return z_flag_;
   1252     case ne: return !z_flag_;
   1253     case cs: return c_flag_;
   1254     case cc: return !c_flag_;
   1255     case mi: return n_flag_;
   1256     case pl: return !n_flag_;
   1257     case vs: return v_flag_;
   1258     case vc: return !v_flag_;
   1259     case hi: return c_flag_ && !z_flag_;
   1260     case ls: return !c_flag_ || z_flag_;
   1261     case ge: return n_flag_ == v_flag_;
   1262     case lt: return n_flag_ != v_flag_;
   1263     case gt: return !z_flag_ && (n_flag_ == v_flag_);
   1264     case le: return z_flag_ || (n_flag_ != v_flag_);
   1265     case al: return true;
   1266     default: UNREACHABLE();
   1267   }
   1268   return false;
   1269 }
   1270 
   1271 
   1272 // Calculate and set the Negative and Zero flags.
   1273 void Simulator::SetNZFlags(int32_t val) {
   1274   n_flag_ = (val < 0);
   1275   z_flag_ = (val == 0);
   1276 }
   1277 
   1278 
   1279 // Set the Carry flag.
   1280 void Simulator::SetCFlag(bool val) {
   1281   c_flag_ = val;
   1282 }
   1283 
   1284 
   1285 // Set the oVerflow flag.
   1286 void Simulator::SetVFlag(bool val) {
   1287   v_flag_ = val;
   1288 }
   1289 
   1290 
   1291 // Calculate C flag value for additions.
   1292 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
   1293   uint32_t uleft = static_cast<uint32_t>(left);
   1294   uint32_t uright = static_cast<uint32_t>(right);
   1295   uint32_t urest  = 0xffffffffU - uleft;
   1296 
   1297   return (uright > urest) ||
   1298          (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
   1299 }
   1300 
   1301 
   1302 // Calculate C flag value for subtractions.
   1303 bool Simulator::BorrowFrom(int32_t left, int32_t right, int32_t carry) {
   1304   uint32_t uleft = static_cast<uint32_t>(left);
   1305   uint32_t uright = static_cast<uint32_t>(right);
   1306 
   1307   return (uright > uleft) ||
   1308          (!carry && (((uright + 1) > uleft) || (uright > (uleft - 1))));
   1309 }
   1310 
   1311 
   1312 // Calculate V flag value for additions and subtractions.
   1313 bool Simulator::OverflowFrom(int32_t alu_out,
   1314                              int32_t left, int32_t right, bool addition) {
   1315   bool overflow;
   1316   if (addition) {
   1317                // operands have the same sign
   1318     overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
   1319                // and operands and result have different sign
   1320                && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
   1321   } else {
   1322                // operands have different signs
   1323     overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
   1324                // and first operand and result have different signs
   1325                && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
   1326   }
   1327   return overflow;
   1328 }
   1329 
   1330 
   1331 // Support for VFP comparisons.
   1332 void Simulator::Compute_FPSCR_Flags(float val1, float val2) {
   1333   if (std::isnan(val1) || std::isnan(val2)) {
   1334     n_flag_FPSCR_ = false;
   1335     z_flag_FPSCR_ = false;
   1336     c_flag_FPSCR_ = true;
   1337     v_flag_FPSCR_ = true;
   1338     // All non-NaN cases.
   1339   } else if (val1 == val2) {
   1340     n_flag_FPSCR_ = false;
   1341     z_flag_FPSCR_ = true;
   1342     c_flag_FPSCR_ = true;
   1343     v_flag_FPSCR_ = false;
   1344   } else if (val1 < val2) {
   1345     n_flag_FPSCR_ = true;
   1346     z_flag_FPSCR_ = false;
   1347     c_flag_FPSCR_ = false;
   1348     v_flag_FPSCR_ = false;
   1349   } else {
   1350     // Case when (val1 > val2).
   1351     n_flag_FPSCR_ = false;
   1352     z_flag_FPSCR_ = false;
   1353     c_flag_FPSCR_ = true;
   1354     v_flag_FPSCR_ = false;
   1355   }
   1356 }
   1357 
   1358 
   1359 void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
   1360   if (std::isnan(val1) || std::isnan(val2)) {
   1361     n_flag_FPSCR_ = false;
   1362     z_flag_FPSCR_ = false;
   1363     c_flag_FPSCR_ = true;
   1364     v_flag_FPSCR_ = true;
   1365   // All non-NaN cases.
   1366   } else if (val1 == val2) {
   1367     n_flag_FPSCR_ = false;
   1368     z_flag_FPSCR_ = true;
   1369     c_flag_FPSCR_ = true;
   1370     v_flag_FPSCR_ = false;
   1371   } else if (val1 < val2) {
   1372     n_flag_FPSCR_ = true;
   1373     z_flag_FPSCR_ = false;
   1374     c_flag_FPSCR_ = false;
   1375     v_flag_FPSCR_ = false;
   1376   } else {
   1377     // Case when (val1 > val2).
   1378     n_flag_FPSCR_ = false;
   1379     z_flag_FPSCR_ = false;
   1380     c_flag_FPSCR_ = true;
   1381     v_flag_FPSCR_ = false;
   1382   }
   1383 }
   1384 
   1385 
   1386 void Simulator::Copy_FPSCR_to_APSR() {
   1387   n_flag_ = n_flag_FPSCR_;
   1388   z_flag_ = z_flag_FPSCR_;
   1389   c_flag_ = c_flag_FPSCR_;
   1390   v_flag_ = v_flag_FPSCR_;
   1391 }
   1392 
   1393 
   1394 // Addressing Mode 1 - Data-processing operands:
   1395 // Get the value based on the shifter_operand with register.
   1396 int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
   1397   ShiftOp shift = instr->ShiftField();
   1398   int shift_amount = instr->ShiftAmountValue();
   1399   int32_t result = get_register(instr->RmValue());
   1400   if (instr->Bit(4) == 0) {
   1401     // by immediate
   1402     if ((shift == ROR) && (shift_amount == 0)) {
   1403       UNIMPLEMENTED();
   1404       return result;
   1405     } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
   1406       shift_amount = 32;
   1407     }
   1408     switch (shift) {
   1409       case ASR: {
   1410         if (shift_amount == 0) {
   1411           if (result < 0) {
   1412             result = 0xffffffff;
   1413             *carry_out = true;
   1414           } else {
   1415             result = 0;
   1416             *carry_out = false;
   1417           }
   1418         } else {
   1419           result >>= (shift_amount - 1);
   1420           *carry_out = (result & 1) == 1;
   1421           result >>= 1;
   1422         }
   1423         break;
   1424       }
   1425 
   1426       case LSL: {
   1427         if (shift_amount == 0) {
   1428           *carry_out = c_flag_;
   1429         } else {
   1430           result <<= (shift_amount - 1);
   1431           *carry_out = (result < 0);
   1432           result <<= 1;
   1433         }
   1434         break;
   1435       }
   1436 
   1437       case LSR: {
   1438         if (shift_amount == 0) {
   1439           result = 0;
   1440           *carry_out = c_flag_;
   1441         } else {
   1442           uint32_t uresult = static_cast<uint32_t>(result);
   1443           uresult >>= (shift_amount - 1);
   1444           *carry_out = (uresult & 1) == 1;
   1445           uresult >>= 1;
   1446           result = static_cast<int32_t>(uresult);
   1447         }
   1448         break;
   1449       }
   1450 
   1451       case ROR: {
   1452         if (shift_amount == 0) {
   1453           *carry_out = c_flag_;
   1454         } else {
   1455           uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
   1456           uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
   1457           result = right | left;
   1458           *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
   1459         }
   1460         break;
   1461       }
   1462 
   1463       default: {
   1464         UNREACHABLE();
   1465         break;
   1466       }
   1467     }
   1468   } else {
   1469     // by register
   1470     int rs = instr->RsValue();
   1471     shift_amount = get_register(rs) &0xff;
   1472     switch (shift) {
   1473       case ASR: {
   1474         if (shift_amount == 0) {
   1475           *carry_out = c_flag_;
   1476         } else if (shift_amount < 32) {
   1477           result >>= (shift_amount - 1);
   1478           *carry_out = (result & 1) == 1;
   1479           result >>= 1;
   1480         } else {
   1481           DCHECK(shift_amount >= 32);
   1482           if (result < 0) {
   1483             *carry_out = true;
   1484             result = 0xffffffff;
   1485           } else {
   1486             *carry_out = false;
   1487             result = 0;
   1488           }
   1489         }
   1490         break;
   1491       }
   1492 
   1493       case LSL: {
   1494         if (shift_amount == 0) {
   1495           *carry_out = c_flag_;
   1496         } else if (shift_amount < 32) {
   1497           result <<= (shift_amount - 1);
   1498           *carry_out = (result < 0);
   1499           result <<= 1;
   1500         } else if (shift_amount == 32) {
   1501           *carry_out = (result & 1) == 1;
   1502           result = 0;
   1503         } else {
   1504           DCHECK(shift_amount > 32);
   1505           *carry_out = false;
   1506           result = 0;
   1507         }
   1508         break;
   1509       }
   1510 
   1511       case LSR: {
   1512         if (shift_amount == 0) {
   1513           *carry_out = c_flag_;
   1514         } else if (shift_amount < 32) {
   1515           uint32_t uresult = static_cast<uint32_t>(result);
   1516           uresult >>= (shift_amount - 1);
   1517           *carry_out = (uresult & 1) == 1;
   1518           uresult >>= 1;
   1519           result = static_cast<int32_t>(uresult);
   1520         } else if (shift_amount == 32) {
   1521           *carry_out = (result < 0);
   1522           result = 0;
   1523         } else {
   1524           *carry_out = false;
   1525           result = 0;
   1526         }
   1527         break;
   1528       }
   1529 
   1530       case ROR: {
   1531         if (shift_amount == 0) {
   1532           *carry_out = c_flag_;
   1533         } else {
   1534           uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
   1535           uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
   1536           result = right | left;
   1537           *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
   1538         }
   1539         break;
   1540       }
   1541 
   1542       default: {
   1543         UNREACHABLE();
   1544         break;
   1545       }
   1546     }
   1547   }
   1548   return result;
   1549 }
   1550 
   1551 
   1552 // Addressing Mode 1 - Data-processing operands:
   1553 // Get the value based on the shifter_operand with immediate.
   1554 int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
   1555   int rotate = instr->RotateValue() * 2;
   1556   int immed8 = instr->Immed8Value();
   1557   int imm = base::bits::RotateRight32(immed8, rotate);
   1558   *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
   1559   return imm;
   1560 }
   1561 
   1562 
   1563 static int count_bits(int bit_vector) {
   1564   int count = 0;
   1565   while (bit_vector != 0) {
   1566     if ((bit_vector & 1) != 0) {
   1567       count++;
   1568     }
   1569     bit_vector >>= 1;
   1570   }
   1571   return count;
   1572 }
   1573 
   1574 
   1575 int32_t Simulator::ProcessPU(Instruction* instr,
   1576                              int num_regs,
   1577                              int reg_size,
   1578                              intptr_t* start_address,
   1579                              intptr_t* end_address) {
   1580   int rn = instr->RnValue();
   1581   int32_t rn_val = get_register(rn);
   1582   switch (instr->PUField()) {
   1583     case da_x: {
   1584       UNIMPLEMENTED();
   1585       break;
   1586     }
   1587     case ia_x: {
   1588       *start_address = rn_val;
   1589       *end_address = rn_val + (num_regs * reg_size) - reg_size;
   1590       rn_val = rn_val + (num_regs * reg_size);
   1591       break;
   1592     }
   1593     case db_x: {
   1594       *start_address = rn_val - (num_regs * reg_size);
   1595       *end_address = rn_val - reg_size;
   1596       rn_val = *start_address;
   1597       break;
   1598     }
   1599     case ib_x: {
   1600       *start_address = rn_val + reg_size;
   1601       *end_address = rn_val + (num_regs * reg_size);
   1602       rn_val = *end_address;
   1603       break;
   1604     }
   1605     default: {
   1606       UNREACHABLE();
   1607       break;
   1608     }
   1609   }
   1610   return rn_val;
   1611 }
   1612 
   1613 
   1614 // Addressing Mode 4 - Load and Store Multiple
   1615 void Simulator::HandleRList(Instruction* instr, bool load) {
   1616   int rlist = instr->RlistValue();
   1617   int num_regs = count_bits(rlist);
   1618 
   1619   intptr_t start_address = 0;
   1620   intptr_t end_address = 0;
   1621   int32_t rn_val =
   1622       ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
   1623 
   1624   intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
   1625   // Catch null pointers a little earlier.
   1626   DCHECK(start_address > 8191 || start_address < 0);
   1627   int reg = 0;
   1628   while (rlist != 0) {
   1629     if ((rlist & 1) != 0) {
   1630       if (load) {
   1631         set_register(reg, *address);
   1632       } else {
   1633         *address = get_register(reg);
   1634       }
   1635       address += 1;
   1636     }
   1637     reg++;
   1638     rlist >>= 1;
   1639   }
   1640   DCHECK(end_address == ((intptr_t)address) - 4);
   1641   if (instr->HasW()) {
   1642     set_register(instr->RnValue(), rn_val);
   1643   }
   1644 }
   1645 
   1646 
   1647 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
   1648 void Simulator::HandleVList(Instruction* instr) {
   1649   VFPRegPrecision precision =
   1650       (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
   1651   int operand_size = (precision == kSinglePrecision) ? 4 : 8;
   1652 
   1653   bool load = (instr->VLValue() == 0x1);
   1654 
   1655   int vd;
   1656   int num_regs;
   1657   vd = instr->VFPDRegValue(precision);
   1658   if (precision == kSinglePrecision) {
   1659     num_regs = instr->Immed8Value();
   1660   } else {
   1661     num_regs = instr->Immed8Value() / 2;
   1662   }
   1663 
   1664   intptr_t start_address = 0;
   1665   intptr_t end_address = 0;
   1666   int32_t rn_val =
   1667       ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
   1668 
   1669   intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
   1670   for (int reg = vd; reg < vd + num_regs; reg++) {
   1671     if (precision == kSinglePrecision) {
   1672       if (load) {
   1673         set_s_register_from_sinteger(
   1674             reg, ReadW(reinterpret_cast<int32_t>(address), instr));
   1675       } else {
   1676         WriteW(reinterpret_cast<int32_t>(address),
   1677                get_sinteger_from_s_register(reg), instr);
   1678       }
   1679       address += 1;
   1680     } else {
   1681       if (load) {
   1682         int32_t data[] = {
   1683           ReadW(reinterpret_cast<int32_t>(address), instr),
   1684           ReadW(reinterpret_cast<int32_t>(address + 1), instr)
   1685         };
   1686         set_d_register(reg, reinterpret_cast<uint32_t*>(data));
   1687       } else {
   1688         uint32_t data[2];
   1689         get_d_register(reg, data);
   1690         WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
   1691         WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
   1692       }
   1693       address += 2;
   1694     }
   1695   }
   1696   DCHECK(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
   1697   if (instr->HasW()) {
   1698     set_register(instr->RnValue(), rn_val);
   1699   }
   1700 }
   1701 
   1702 
   1703 // Calls into the V8 runtime are based on this very simple interface.
   1704 // Note: To be able to return two values from some calls the code in runtime.cc
   1705 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
   1706 // 64-bit value. With the code below we assume that all runtime calls return
   1707 // 64 bits of result. If they don't, the r1 result register contains a bogus
   1708 // value, which is fine because it is caller-saved.
   1709 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
   1710                                         int32_t arg1,
   1711                                         int32_t arg2,
   1712                                         int32_t arg3,
   1713                                         int32_t arg4,
   1714                                         int32_t arg5);
   1715 
   1716 typedef ObjectTriple (*SimulatorRuntimeTripleCall)(int32_t arg0, int32_t arg1,
   1717                                                    int32_t arg2, int32_t arg3,
   1718                                                    int32_t arg4);
   1719 
   1720 // These prototypes handle the four types of FP calls.
   1721 typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
   1722 typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
   1723 typedef double (*SimulatorRuntimeFPCall)(double darg0);
   1724 typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
   1725 
   1726 // This signature supports direct call in to API function native callback
   1727 // (refer to InvocationCallback in v8.h).
   1728 typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
   1729 typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
   1730 
   1731 // This signature supports direct call to accessor getter callback.
   1732 typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
   1733 typedef void (*SimulatorRuntimeProfilingGetterCall)(
   1734     int32_t arg0, int32_t arg1, void* arg2);
   1735 
   1736 // Software interrupt instructions are used by the simulator to call into the
   1737 // C-based V8 runtime.
   1738 void Simulator::SoftwareInterrupt(Instruction* instr) {
   1739   int svc = instr->SvcValue();
   1740   switch (svc) {
   1741     case kCallRtRedirected: {
   1742       // Check if stack is aligned. Error if not aligned is reported below to
   1743       // include information on the function called.
   1744       bool stack_aligned =
   1745           (get_register(sp)
   1746            & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
   1747       Redirection* redirection = Redirection::FromSwiInstruction(instr);
   1748       int32_t arg0 = get_register(r0);
   1749       int32_t arg1 = get_register(r1);
   1750       int32_t arg2 = get_register(r2);
   1751       int32_t arg3 = get_register(r3);
   1752       int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
   1753       int32_t arg4 = stack_pointer[0];
   1754       int32_t arg5 = stack_pointer[1];
   1755       bool fp_call =
   1756          (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
   1757          (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
   1758          (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
   1759          (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
   1760       // This is dodgy but it works because the C entry stubs are never moved.
   1761       // See comment in codegen-arm.cc and bug 1242173.
   1762       int32_t saved_lr = get_register(lr);
   1763       intptr_t external =
   1764           reinterpret_cast<intptr_t>(redirection->external_function());
   1765       if (fp_call) {
   1766         double dval0, dval1;  // one or two double parameters
   1767         int32_t ival;         // zero or one integer parameters
   1768         int64_t iresult = 0;  // integer return value
   1769         double dresult = 0;   // double return value
   1770         GetFpArgs(&dval0, &dval1, &ival);
   1771         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1772           SimulatorRuntimeCall generic_target =
   1773             reinterpret_cast<SimulatorRuntimeCall>(external);
   1774           switch (redirection->type()) {
   1775           case ExternalReference::BUILTIN_FP_FP_CALL:
   1776           case ExternalReference::BUILTIN_COMPARE_CALL:
   1777             PrintF("Call to host function at %p with args %f, %f",
   1778                    static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
   1779                    dval1);
   1780             break;
   1781           case ExternalReference::BUILTIN_FP_CALL:
   1782             PrintF("Call to host function at %p with arg %f",
   1783                    static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0);
   1784             break;
   1785           case ExternalReference::BUILTIN_FP_INT_CALL:
   1786             PrintF("Call to host function at %p with args %f, %d",
   1787                    static_cast<void*>(FUNCTION_ADDR(generic_target)), dval0,
   1788                    ival);
   1789             break;
   1790           default:
   1791             UNREACHABLE();
   1792             break;
   1793           }
   1794           if (!stack_aligned) {
   1795             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1796           }
   1797           PrintF("\n");
   1798         }
   1799         CHECK(stack_aligned);
   1800         switch (redirection->type()) {
   1801         case ExternalReference::BUILTIN_COMPARE_CALL: {
   1802           SimulatorRuntimeCompareCall target =
   1803             reinterpret_cast<SimulatorRuntimeCompareCall>(external);
   1804           iresult = target(dval0, dval1);
   1805           set_register(r0, static_cast<int32_t>(iresult));
   1806           set_register(r1, static_cast<int32_t>(iresult >> 32));
   1807           break;
   1808         }
   1809         case ExternalReference::BUILTIN_FP_FP_CALL: {
   1810           SimulatorRuntimeFPFPCall target =
   1811             reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
   1812           dresult = target(dval0, dval1);
   1813           SetFpResult(dresult);
   1814           break;
   1815         }
   1816         case ExternalReference::BUILTIN_FP_CALL: {
   1817           SimulatorRuntimeFPCall target =
   1818             reinterpret_cast<SimulatorRuntimeFPCall>(external);
   1819           dresult = target(dval0);
   1820           SetFpResult(dresult);
   1821           break;
   1822         }
   1823         case ExternalReference::BUILTIN_FP_INT_CALL: {
   1824           SimulatorRuntimeFPIntCall target =
   1825             reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
   1826           dresult = target(dval0, ival);
   1827           SetFpResult(dresult);
   1828           break;
   1829         }
   1830         default:
   1831           UNREACHABLE();
   1832           break;
   1833         }
   1834         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1835           switch (redirection->type()) {
   1836           case ExternalReference::BUILTIN_COMPARE_CALL:
   1837             PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
   1838             break;
   1839           case ExternalReference::BUILTIN_FP_FP_CALL:
   1840           case ExternalReference::BUILTIN_FP_CALL:
   1841           case ExternalReference::BUILTIN_FP_INT_CALL:
   1842             PrintF("Returned %f\n", dresult);
   1843             break;
   1844           default:
   1845             UNREACHABLE();
   1846             break;
   1847           }
   1848         }
   1849       } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
   1850         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1851           PrintF("Call to host function at %p args %08x",
   1852               reinterpret_cast<void*>(external), arg0);
   1853           if (!stack_aligned) {
   1854             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1855           }
   1856           PrintF("\n");
   1857         }
   1858         CHECK(stack_aligned);
   1859         SimulatorRuntimeDirectApiCall target =
   1860             reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
   1861         target(arg0);
   1862       } else if (
   1863           redirection->type() == ExternalReference::PROFILING_API_CALL) {
   1864         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1865           PrintF("Call to host function at %p args %08x %08x",
   1866               reinterpret_cast<void*>(external), arg0, arg1);
   1867           if (!stack_aligned) {
   1868             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1869           }
   1870           PrintF("\n");
   1871         }
   1872         CHECK(stack_aligned);
   1873         SimulatorRuntimeProfilingApiCall target =
   1874             reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
   1875         target(arg0, Redirection::ReverseRedirection(arg1));
   1876       } else if (
   1877           redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
   1878         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1879           PrintF("Call to host function at %p args %08x %08x",
   1880               reinterpret_cast<void*>(external), arg0, arg1);
   1881           if (!stack_aligned) {
   1882             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1883           }
   1884           PrintF("\n");
   1885         }
   1886         CHECK(stack_aligned);
   1887         SimulatorRuntimeDirectGetterCall target =
   1888             reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
   1889         target(arg0, arg1);
   1890       } else if (
   1891           redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
   1892         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1893           PrintF("Call to host function at %p args %08x %08x %08x",
   1894               reinterpret_cast<void*>(external), arg0, arg1, arg2);
   1895           if (!stack_aligned) {
   1896             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1897           }
   1898           PrintF("\n");
   1899         }
   1900         CHECK(stack_aligned);
   1901         SimulatorRuntimeProfilingGetterCall target =
   1902             reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
   1903                 external);
   1904         target(arg0, arg1, Redirection::ReverseRedirection(arg2));
   1905       } else if (redirection->type() ==
   1906                  ExternalReference::BUILTIN_CALL_TRIPLE) {
   1907         // builtin call returning ObjectTriple.
   1908         SimulatorRuntimeTripleCall target =
   1909             reinterpret_cast<SimulatorRuntimeTripleCall>(external);
   1910         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1911           PrintF(
   1912               "Call to host triple returning runtime function %p "
   1913               "args %08x, %08x, %08x, %08x, %08x",
   1914               static_cast<void*>(FUNCTION_ADDR(target)), arg1, arg2, arg3, arg4,
   1915               arg5);
   1916           if (!stack_aligned) {
   1917             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1918           }
   1919           PrintF("\n");
   1920         }
   1921         CHECK(stack_aligned);
   1922         // arg0 is a hidden argument pointing to the return location, so don't
   1923         // pass it to the target function.
   1924         ObjectTriple result = target(arg1, arg2, arg3, arg4, arg5);
   1925         if (::v8::internal::FLAG_trace_sim) {
   1926           PrintF("Returned { %p, %p, %p }\n", static_cast<void*>(result.x),
   1927                  static_cast<void*>(result.y), static_cast<void*>(result.z));
   1928         }
   1929         // Return is passed back in address pointed to by hidden first argument.
   1930         ObjectTriple* sim_result = reinterpret_cast<ObjectTriple*>(arg0);
   1931         *sim_result = result;
   1932         set_register(r0, arg0);
   1933       } else {
   1934         // builtin call.
   1935         DCHECK(redirection->type() == ExternalReference::BUILTIN_CALL ||
   1936                redirection->type() == ExternalReference::BUILTIN_CALL_PAIR);
   1937         SimulatorRuntimeCall target =
   1938             reinterpret_cast<SimulatorRuntimeCall>(external);
   1939         if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
   1940           PrintF(
   1941               "Call to host function at %p "
   1942               "args %08x, %08x, %08x, %08x, %08x, %08x",
   1943               static_cast<void*>(FUNCTION_ADDR(target)), arg0, arg1, arg2, arg3,
   1944               arg4, arg5);
   1945           if (!stack_aligned) {
   1946             PrintF(" with unaligned stack %08x\n", get_register(sp));
   1947           }
   1948           PrintF("\n");
   1949         }
   1950         CHECK(stack_aligned);
   1951         int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
   1952         int32_t lo_res = static_cast<int32_t>(result);
   1953         int32_t hi_res = static_cast<int32_t>(result >> 32);
   1954         if (::v8::internal::FLAG_trace_sim) {
   1955           PrintF("Returned %08x\n", lo_res);
   1956         }
   1957         set_register(r0, lo_res);
   1958         set_register(r1, hi_res);
   1959       }
   1960       set_register(lr, saved_lr);
   1961       set_pc(get_register(lr));
   1962       break;
   1963     }
   1964     case kBreakpoint: {
   1965       ArmDebugger dbg(this);
   1966       dbg.Debug();
   1967       break;
   1968     }
   1969     // stop uses all codes greater than 1 << 23.
   1970     default: {
   1971       if (svc >= (1 << 23)) {
   1972         uint32_t code = svc & kStopCodeMask;
   1973         if (isWatchedStop(code)) {
   1974           IncreaseStopCounter(code);
   1975         }
   1976         // Stop if it is enabled, otherwise go on jumping over the stop
   1977         // and the message address.
   1978         if (isEnabledStop(code)) {
   1979           ArmDebugger dbg(this);
   1980           dbg.Stop(instr);
   1981         } else {
   1982           set_pc(get_pc() + 2 * Instruction::kInstrSize);
   1983         }
   1984       } else {
   1985         // This is not a valid svc code.
   1986         UNREACHABLE();
   1987         break;
   1988       }
   1989     }
   1990   }
   1991 }
   1992 
   1993 
   1994 float Simulator::canonicalizeNaN(float value) {
   1995   // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
   1996   // choices" of the ARM Reference Manual.
   1997   const uint32_t kDefaultNaN = 0x7FC00000u;
   1998   if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
   1999     value = bit_cast<float>(kDefaultNaN);
   2000   }
   2001   return value;
   2002 }
   2003 
   2004 
   2005 double Simulator::canonicalizeNaN(double value) {
   2006   // Default NaN value, see "NaN handling" in "IEEE 754 standard implementation
   2007   // choices" of the ARM Reference Manual.
   2008   const uint64_t kDefaultNaN = V8_UINT64_C(0x7FF8000000000000);
   2009   if (FPSCR_default_NaN_mode_ && std::isnan(value)) {
   2010     value = bit_cast<double>(kDefaultNaN);
   2011   }
   2012   return value;
   2013 }
   2014 
   2015 
   2016 // Stop helper functions.
   2017 bool Simulator::isStopInstruction(Instruction* instr) {
   2018   return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
   2019 }
   2020 
   2021 
   2022 bool Simulator::isWatchedStop(uint32_t code) {
   2023   DCHECK(code <= kMaxStopCode);
   2024   return code < kNumOfWatchedStops;
   2025 }
   2026 
   2027 
   2028 bool Simulator::isEnabledStop(uint32_t code) {
   2029   DCHECK(code <= kMaxStopCode);
   2030   // Unwatched stops are always enabled.
   2031   return !isWatchedStop(code) ||
   2032     !(watched_stops_[code].count & kStopDisabledBit);
   2033 }
   2034 
   2035 
   2036 void Simulator::EnableStop(uint32_t code) {
   2037   DCHECK(isWatchedStop(code));
   2038   if (!isEnabledStop(code)) {
   2039     watched_stops_[code].count &= ~kStopDisabledBit;
   2040   }
   2041 }
   2042 
   2043 
   2044 void Simulator::DisableStop(uint32_t code) {
   2045   DCHECK(isWatchedStop(code));
   2046   if (isEnabledStop(code)) {
   2047     watched_stops_[code].count |= kStopDisabledBit;
   2048   }
   2049 }
   2050 
   2051 
   2052 void Simulator::IncreaseStopCounter(uint32_t code) {
   2053   DCHECK(code <= kMaxStopCode);
   2054   DCHECK(isWatchedStop(code));
   2055   if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
   2056     PrintF("Stop counter for code %i has overflowed.\n"
   2057            "Enabling this code and reseting the counter to 0.\n", code);
   2058     watched_stops_[code].count = 0;
   2059     EnableStop(code);
   2060   } else {
   2061     watched_stops_[code].count++;
   2062   }
   2063 }
   2064 
   2065 
   2066 // Print a stop status.
   2067 void Simulator::PrintStopInfo(uint32_t code) {
   2068   DCHECK(code <= kMaxStopCode);
   2069   if (!isWatchedStop(code)) {
   2070     PrintF("Stop not watched.");
   2071   } else {
   2072     const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
   2073     int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
   2074     // Don't print the state of unused breakpoints.
   2075     if (count != 0) {
   2076       if (watched_stops_[code].desc) {
   2077         PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
   2078                code, code, state, count, watched_stops_[code].desc);
   2079       } else {
   2080         PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
   2081                code, code, state, count);
   2082       }
   2083     }
   2084   }
   2085 }
   2086 
   2087 
   2088 // Handle execution based on instruction types.
   2089 
   2090 // Instruction types 0 and 1 are both rolled into one function because they
   2091 // only differ in the handling of the shifter_operand.
   2092 void Simulator::DecodeType01(Instruction* instr) {
   2093   int type = instr->TypeValue();
   2094   if ((type == 0) && instr->IsSpecialType0()) {
   2095     // multiply instruction or extra loads and stores
   2096     if (instr->Bits(7, 4) == 9) {
   2097       if (instr->Bit(24) == 0) {
   2098         // Raw field decoding here. Multiply instructions have their Rd in
   2099         // funny places.
   2100         int rn = instr->RnValue();
   2101         int rm = instr->RmValue();
   2102         int rs = instr->RsValue();
   2103         int32_t rs_val = get_register(rs);
   2104         int32_t rm_val = get_register(rm);
   2105         if (instr->Bit(23) == 0) {
   2106           if (instr->Bit(21) == 0) {
   2107             // The MUL instruction description (A 4.1.33) refers to Rd as being
   2108             // the destination for the operation, but it confusingly uses the
   2109             // Rn field to encode it.
   2110             // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
   2111             int rd = rn;  // Remap the rn field to the Rd register.
   2112             int32_t alu_out = rm_val * rs_val;
   2113             set_register(rd, alu_out);
   2114             if (instr->HasS()) {
   2115               SetNZFlags(alu_out);
   2116             }
   2117           } else {
   2118             int rd = instr->RdValue();
   2119             int32_t acc_value = get_register(rd);
   2120             if (instr->Bit(22) == 0) {
   2121               // The MLA instruction description (A 4.1.28) refers to the order
   2122               // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
   2123               // Rn field to encode the Rd register and the Rd field to encode
   2124               // the Rn register.
   2125               // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
   2126               int32_t mul_out = rm_val * rs_val;
   2127               int32_t result = acc_value + mul_out;
   2128               set_register(rn, result);
   2129             } else {
   2130               // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
   2131               int32_t mul_out = rm_val * rs_val;
   2132               int32_t result = acc_value - mul_out;
   2133               set_register(rn, result);
   2134             }
   2135           }
   2136         } else {
   2137           // The signed/long multiply instructions use the terms RdHi and RdLo
   2138           // when referring to the target registers. They are mapped to the Rn
   2139           // and Rd fields as follows:
   2140           // RdLo == Rd
   2141           // RdHi == Rn (This is confusingly stored in variable rd here
   2142           //             because the mul instruction from above uses the
   2143           //             Rn field to encode the Rd register. Good luck figuring
   2144           //             this out without reading the ARM instruction manual
   2145           //             at a very detailed level.)
   2146           // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
   2147           int rd_hi = rn;  // Remap the rn field to the RdHi register.
   2148           int rd_lo = instr->RdValue();
   2149           int32_t hi_res = 0;
   2150           int32_t lo_res = 0;
   2151           if (instr->Bit(22) == 1) {
   2152             int64_t left_op  = static_cast<int32_t>(rm_val);
   2153             int64_t right_op = static_cast<int32_t>(rs_val);
   2154             uint64_t result = left_op * right_op;
   2155             hi_res = static_cast<int32_t>(result >> 32);
   2156             lo_res = static_cast<int32_t>(result & 0xffffffff);
   2157           } else {
   2158             // unsigned multiply
   2159             uint64_t left_op  = static_cast<uint32_t>(rm_val);
   2160             uint64_t right_op = static_cast<uint32_t>(rs_val);
   2161             uint64_t result = left_op * right_op;
   2162             hi_res = static_cast<int32_t>(result >> 32);
   2163             lo_res = static_cast<int32_t>(result & 0xffffffff);
   2164           }
   2165           set_register(rd_lo, lo_res);
   2166           set_register(rd_hi, hi_res);
   2167           if (instr->HasS()) {
   2168             UNIMPLEMENTED();
   2169           }
   2170         }
   2171       } else {
   2172         if (instr->Bits(24, 23) == 3) {
   2173           if (instr->Bit(20) == 1) {
   2174             // ldrex
   2175             int rt = instr->RtValue();
   2176             int rn = instr->RnValue();
   2177             int32_t addr = get_register(rn);
   2178             switch (instr->Bits(22, 21)) {
   2179               case 0: {
   2180                 // Format(instr, "ldrex'cond 'rt, ['rn]");
   2181                 int value = ReadExW(addr, instr);
   2182                 set_register(rt, value);
   2183                 break;
   2184               }
   2185               case 2: {
   2186                 // Format(instr, "ldrexb'cond 'rt, ['rn]");
   2187                 uint8_t value = ReadExBU(addr);
   2188                 set_register(rt, value);
   2189                 break;
   2190               }
   2191               case 3: {
   2192                 // Format(instr, "ldrexh'cond 'rt, ['rn]");
   2193                 uint16_t value = ReadExHU(addr, instr);
   2194                 set_register(rt, value);
   2195                 break;
   2196               }
   2197               default:
   2198                 UNREACHABLE();
   2199                 break;
   2200             }
   2201           } else {
   2202             // The instruction is documented as strex rd, rt, [rn], but the
   2203             // "rt" register is using the rm bits.
   2204             int rd = instr->RdValue();
   2205             int rt = instr->RmValue();
   2206             int rn = instr->RnValue();
   2207             int32_t addr = get_register(rn);
   2208             switch (instr->Bits(22, 21)) {
   2209               case 0: {
   2210                 // Format(instr, "strex'cond 'rd, 'rm, ['rn]");
   2211                 int value = get_register(rt);
   2212                 int status = WriteExW(addr, value, instr);
   2213                 set_register(rd, status);
   2214                 break;
   2215               }
   2216               case 2: {
   2217                 // Format(instr, "strexb'cond 'rd, 'rm, ['rn]");
   2218                 uint8_t value = get_register(rt);
   2219                 int status = WriteExB(addr, value);
   2220                 set_register(rd, status);
   2221                 break;
   2222               }
   2223               case 3: {
   2224                 // Format(instr, "strexh'cond 'rd, 'rm, ['rn]");
   2225                 uint16_t value = get_register(rt);
   2226                 int status = WriteExH(addr, value, instr);
   2227                 set_register(rd, status);
   2228                 break;
   2229               }
   2230               default:
   2231                 UNREACHABLE();
   2232                 break;
   2233             }
   2234           }
   2235         } else {
   2236           UNIMPLEMENTED();  // Not used by V8.
   2237         }
   2238       }
   2239     } else {
   2240       // extra load/store instructions
   2241       int rd = instr->RdValue();
   2242       int rn = instr->RnValue();
   2243       int32_t rn_val = get_register(rn);
   2244       int32_t addr = 0;
   2245       if (instr->Bit(22) == 0) {
   2246         int rm = instr->RmValue();
   2247         int32_t rm_val = get_register(rm);
   2248         switch (instr->PUField()) {
   2249           case da_x: {
   2250             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
   2251             DCHECK(!instr->HasW());
   2252             addr = rn_val;
   2253             rn_val -= rm_val;
   2254             set_register(rn, rn_val);
   2255             break;
   2256           }
   2257           case ia_x: {
   2258             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
   2259             DCHECK(!instr->HasW());
   2260             addr = rn_val;
   2261             rn_val += rm_val;
   2262             set_register(rn, rn_val);
   2263             break;
   2264           }
   2265           case db_x: {
   2266             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
   2267             rn_val -= rm_val;
   2268             addr = rn_val;
   2269             if (instr->HasW()) {
   2270               set_register(rn, rn_val);
   2271             }
   2272             break;
   2273           }
   2274           case ib_x: {
   2275             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
   2276             rn_val += rm_val;
   2277             addr = rn_val;
   2278             if (instr->HasW()) {
   2279               set_register(rn, rn_val);
   2280             }
   2281             break;
   2282           }
   2283           default: {
   2284             // The PU field is a 2-bit field.
   2285             UNREACHABLE();
   2286             break;
   2287           }
   2288         }
   2289       } else {
   2290         int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
   2291         switch (instr->PUField()) {
   2292           case da_x: {
   2293             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
   2294             DCHECK(!instr->HasW());
   2295             addr = rn_val;
   2296             rn_val -= imm_val;
   2297             set_register(rn, rn_val);
   2298             break;
   2299           }
   2300           case ia_x: {
   2301             // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
   2302             DCHECK(!instr->HasW());
   2303             addr = rn_val;
   2304             rn_val += imm_val;
   2305             set_register(rn, rn_val);
   2306             break;
   2307           }
   2308           case db_x: {
   2309             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
   2310             rn_val -= imm_val;
   2311             addr = rn_val;
   2312             if (instr->HasW()) {
   2313               set_register(rn, rn_val);
   2314             }
   2315             break;
   2316           }
   2317           case ib_x: {
   2318             // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
   2319             rn_val += imm_val;
   2320             addr = rn_val;
   2321             if (instr->HasW()) {
   2322               set_register(rn, rn_val);
   2323             }
   2324             break;
   2325           }
   2326           default: {
   2327             // The PU field is a 2-bit field.
   2328             UNREACHABLE();
   2329             break;
   2330           }
   2331         }
   2332       }
   2333       if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
   2334         DCHECK((rd % 2) == 0);
   2335         if (instr->HasH()) {
   2336           // The strd instruction.
   2337           int32_t value1 = get_register(rd);
   2338           int32_t value2 = get_register(rd+1);
   2339           WriteDW(addr, value1, value2);
   2340         } else {
   2341           // The ldrd instruction.
   2342           int* rn_data = ReadDW(addr);
   2343           set_dw_register(rd, rn_data);
   2344         }
   2345       } else if (instr->HasH()) {
   2346         if (instr->HasSign()) {
   2347           if (instr->HasL()) {
   2348             int16_t val = ReadH(addr, instr);
   2349             set_register(rd, val);
   2350           } else {
   2351             int16_t val = get_register(rd);
   2352             WriteH(addr, val, instr);
   2353           }
   2354         } else {
   2355           if (instr->HasL()) {
   2356             uint16_t val = ReadHU(addr, instr);
   2357             set_register(rd, val);
   2358           } else {
   2359             uint16_t val = get_register(rd);
   2360             WriteH(addr, val, instr);
   2361           }
   2362         }
   2363       } else {
   2364         // signed byte loads
   2365         DCHECK(instr->HasSign());
   2366         DCHECK(instr->HasL());
   2367         int8_t val = ReadB(addr);
   2368         set_register(rd, val);
   2369       }
   2370       return;
   2371     }
   2372   } else if ((type == 0) && instr->IsMiscType0()) {
   2373     if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 2) &&
   2374         (instr->Bits(15, 4) == 0xf00)) {
   2375       // MSR
   2376       int rm = instr->RmValue();
   2377       DCHECK_NE(pc, rm);  // UNPREDICTABLE
   2378       SRegisterFieldMask sreg_and_mask =
   2379           instr->BitField(22, 22) | instr->BitField(19, 16);
   2380       SetSpecialRegister(sreg_and_mask, get_register(rm));
   2381     } else if ((instr->Bits(27, 23) == 2) && (instr->Bits(21, 20) == 0) &&
   2382                (instr->Bits(11, 0) == 0)) {
   2383       // MRS
   2384       int rd = instr->RdValue();
   2385       DCHECK_NE(pc, rd);  // UNPREDICTABLE
   2386       SRegister sreg = static_cast<SRegister>(instr->BitField(22, 22));
   2387       set_register(rd, GetFromSpecialRegister(sreg));
   2388     } else if (instr->Bits(22, 21) == 1) {
   2389       int rm = instr->RmValue();
   2390       switch (instr->BitField(7, 4)) {
   2391         case BX:
   2392           set_pc(get_register(rm));
   2393           break;
   2394         case BLX: {
   2395           uint32_t old_pc = get_pc();
   2396           set_pc(get_register(rm));
   2397           set_register(lr, old_pc + Instruction::kInstrSize);
   2398           break;
   2399         }
   2400         case BKPT: {
   2401           ArmDebugger dbg(this);
   2402           PrintF("Simulator hit BKPT.\n");
   2403           dbg.Debug();
   2404           break;
   2405         }
   2406         default:
   2407           UNIMPLEMENTED();
   2408       }
   2409     } else if (instr->Bits(22, 21) == 3) {
   2410       int rm = instr->RmValue();
   2411       int rd = instr->RdValue();
   2412       switch (instr->BitField(7, 4)) {
   2413         case CLZ: {
   2414           uint32_t bits = get_register(rm);
   2415           int leading_zeros = 0;
   2416           if (bits == 0) {
   2417             leading_zeros = 32;
   2418           } else {
   2419             while ((bits & 0x80000000u) == 0) {
   2420               bits <<= 1;
   2421               leading_zeros++;
   2422             }
   2423           }
   2424           set_register(rd, leading_zeros);
   2425           break;
   2426         }
   2427         default:
   2428           UNIMPLEMENTED();
   2429       }
   2430     } else {
   2431       PrintF("%08x\n", instr->InstructionBits());
   2432       UNIMPLEMENTED();
   2433     }
   2434   } else if ((type == 1) && instr->IsNopType1()) {
   2435     // NOP.
   2436   } else {
   2437     int rd = instr->RdValue();
   2438     int rn = instr->RnValue();
   2439     int32_t rn_val = get_register(rn);
   2440     int32_t shifter_operand = 0;
   2441     bool shifter_carry_out = 0;
   2442     if (type == 0) {
   2443       shifter_operand = GetShiftRm(instr, &shifter_carry_out);
   2444     } else {
   2445       DCHECK(instr->TypeValue() == 1);
   2446       shifter_operand = GetImm(instr, &shifter_carry_out);
   2447     }
   2448     int32_t alu_out;
   2449 
   2450     switch (instr->OpcodeField()) {
   2451       case AND: {
   2452         // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
   2453         // Format(instr, "and'cond's 'rd, 'rn, 'imm");
   2454         alu_out = rn_val & shifter_operand;
   2455         set_register(rd, alu_out);
   2456         if (instr->HasS()) {
   2457           SetNZFlags(alu_out);
   2458           SetCFlag(shifter_carry_out);
   2459         }
   2460         break;
   2461       }
   2462 
   2463       case EOR: {
   2464         // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
   2465         // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
   2466         alu_out = rn_val ^ shifter_operand;
   2467         set_register(rd, alu_out);
   2468         if (instr->HasS()) {
   2469           SetNZFlags(alu_out);
   2470           SetCFlag(shifter_carry_out);
   2471         }
   2472         break;
   2473       }
   2474 
   2475       case SUB: {
   2476         // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
   2477         // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
   2478         alu_out = rn_val - shifter_operand;
   2479         set_register(rd, alu_out);
   2480         if (instr->HasS()) {
   2481           SetNZFlags(alu_out);
   2482           SetCFlag(!BorrowFrom(rn_val, shifter_operand));
   2483           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
   2484         }
   2485         break;
   2486       }
   2487 
   2488       case RSB: {
   2489         // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
   2490         // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
   2491         alu_out = shifter_operand - rn_val;
   2492         set_register(rd, alu_out);
   2493         if (instr->HasS()) {
   2494           SetNZFlags(alu_out);
   2495           SetCFlag(!BorrowFrom(shifter_operand, rn_val));
   2496           SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
   2497         }
   2498         break;
   2499       }
   2500 
   2501       case ADD: {
   2502         // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
   2503         // Format(instr, "add'cond's 'rd, 'rn, 'imm");
   2504         alu_out = rn_val + shifter_operand;
   2505         set_register(rd, alu_out);
   2506         if (instr->HasS()) {
   2507           SetNZFlags(alu_out);
   2508           SetCFlag(CarryFrom(rn_val, shifter_operand));
   2509           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
   2510         }
   2511         break;
   2512       }
   2513 
   2514       case ADC: {
   2515         // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
   2516         // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
   2517         alu_out = rn_val + shifter_operand + GetCarry();
   2518         set_register(rd, alu_out);
   2519         if (instr->HasS()) {
   2520           SetNZFlags(alu_out);
   2521           SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
   2522           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
   2523         }
   2524         break;
   2525       }
   2526 
   2527       case SBC: {
   2528         //        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
   2529         //        Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
   2530         alu_out = (rn_val - shifter_operand) - (GetCarry() ? 0 : 1);
   2531         set_register(rd, alu_out);
   2532         if (instr->HasS()) {
   2533           SetNZFlags(alu_out);
   2534           SetCFlag(!BorrowFrom(rn_val, shifter_operand, GetCarry()));
   2535           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
   2536         }
   2537         break;
   2538       }
   2539 
   2540       case RSC: {
   2541         Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
   2542         Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
   2543         break;
   2544       }
   2545 
   2546       case TST: {
   2547         if (instr->HasS()) {
   2548           // Format(instr, "tst'cond 'rn, 'shift_rm");
   2549           // Format(instr, "tst'cond 'rn, 'imm");
   2550           alu_out = rn_val & shifter_operand;
   2551           SetNZFlags(alu_out);
   2552           SetCFlag(shifter_carry_out);
   2553         } else {
   2554           // Format(instr, "movw'cond 'rd, 'imm").
   2555           alu_out = instr->ImmedMovwMovtValue();
   2556           set_register(rd, alu_out);
   2557         }
   2558         break;
   2559       }
   2560 
   2561       case TEQ: {
   2562         if (instr->HasS()) {
   2563           // Format(instr, "teq'cond 'rn, 'shift_rm");
   2564           // Format(instr, "teq'cond 'rn, 'imm");
   2565           alu_out = rn_val ^ shifter_operand;
   2566           SetNZFlags(alu_out);
   2567           SetCFlag(shifter_carry_out);
   2568         } else {
   2569           // Other instructions matching this pattern are handled in the
   2570           // miscellaneous instructions part above.
   2571           UNREACHABLE();
   2572         }
   2573         break;
   2574       }
   2575 
   2576       case CMP: {
   2577         if (instr->HasS()) {
   2578           // Format(instr, "cmp'cond 'rn, 'shift_rm");
   2579           // Format(instr, "cmp'cond 'rn, 'imm");
   2580           alu_out = rn_val - shifter_operand;
   2581           SetNZFlags(alu_out);
   2582           SetCFlag(!BorrowFrom(rn_val, shifter_operand));
   2583           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
   2584         } else {
   2585           // Format(instr, "movt'cond 'rd, 'imm").
   2586           alu_out = (get_register(rd) & 0xffff) |
   2587               (instr->ImmedMovwMovtValue() << 16);
   2588           set_register(rd, alu_out);
   2589         }
   2590         break;
   2591       }
   2592 
   2593       case CMN: {
   2594         if (instr->HasS()) {
   2595           // Format(instr, "cmn'cond 'rn, 'shift_rm");
   2596           // Format(instr, "cmn'cond 'rn, 'imm");
   2597           alu_out = rn_val + shifter_operand;
   2598           SetNZFlags(alu_out);
   2599           SetCFlag(CarryFrom(rn_val, shifter_operand));
   2600           SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
   2601         } else {
   2602           // Other instructions matching this pattern are handled in the
   2603           // miscellaneous instructions part above.
   2604           UNREACHABLE();
   2605         }
   2606         break;
   2607       }
   2608 
   2609       case ORR: {
   2610         // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
   2611         // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
   2612         alu_out = rn_val | shifter_operand;
   2613         set_register(rd, alu_out);
   2614         if (instr->HasS()) {
   2615           SetNZFlags(alu_out);
   2616           SetCFlag(shifter_carry_out);
   2617         }
   2618         break;
   2619       }
   2620 
   2621       case MOV: {
   2622         // Format(instr, "mov'cond's 'rd, 'shift_rm");
   2623         // Format(instr, "mov'cond's 'rd, 'imm");
   2624         alu_out = shifter_operand;
   2625         set_register(rd, alu_out);
   2626         if (instr->HasS()) {
   2627           SetNZFlags(alu_out);
   2628           SetCFlag(shifter_carry_out);
   2629         }
   2630         break;
   2631       }
   2632 
   2633       case BIC: {
   2634         // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
   2635         // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
   2636         alu_out = rn_val & ~shifter_operand;
   2637         set_register(rd, alu_out);
   2638         if (instr->HasS()) {
   2639           SetNZFlags(alu_out);
   2640           SetCFlag(shifter_carry_out);
   2641         }
   2642         break;
   2643       }
   2644 
   2645       case MVN: {
   2646         // Format(instr, "mvn'cond's 'rd, 'shift_rm");
   2647         // Format(instr, "mvn'cond's 'rd, 'imm");
   2648         alu_out = ~shifter_operand;
   2649         set_register(rd, alu_out);
   2650         if (instr->HasS()) {
   2651           SetNZFlags(alu_out);
   2652           SetCFlag(shifter_carry_out);
   2653         }
   2654         break;
   2655       }
   2656 
   2657       default: {
   2658         UNREACHABLE();
   2659         break;
   2660       }
   2661     }
   2662   }
   2663 }
   2664 
   2665 
   2666 void Simulator::DecodeType2(Instruction* instr) {
   2667   int rd = instr->RdValue();
   2668   int rn = instr->RnValue();
   2669   int32_t rn_val = get_register(rn);
   2670   int32_t im_val = instr->Offset12Value();
   2671   int32_t addr = 0;
   2672   switch (instr->PUField()) {
   2673     case da_x: {
   2674       // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
   2675       DCHECK(!instr->HasW());
   2676       addr = rn_val;
   2677       rn_val -= im_val;
   2678       set_register(rn, rn_val);
   2679       break;
   2680     }
   2681     case ia_x: {
   2682       // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
   2683       DCHECK(!instr->HasW());
   2684       addr = rn_val;
   2685       rn_val += im_val;
   2686       set_register(rn, rn_val);
   2687       break;
   2688     }
   2689     case db_x: {
   2690       // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
   2691       rn_val -= im_val;
   2692       addr = rn_val;
   2693       if (instr->HasW()) {
   2694         set_register(rn, rn_val);
   2695       }
   2696       break;
   2697     }
   2698     case ib_x: {
   2699       // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
   2700       rn_val += im_val;
   2701       addr = rn_val;
   2702       if (instr->HasW()) {
   2703         set_register(rn, rn_val);
   2704       }
   2705       break;
   2706     }
   2707     default: {
   2708       UNREACHABLE();
   2709       break;
   2710     }
   2711   }
   2712   if (instr->HasB()) {
   2713     if (instr->HasL()) {
   2714       byte val = ReadBU(addr);
   2715       set_register(rd, val);
   2716     } else {
   2717       byte val = get_register(rd);
   2718       WriteB(addr, val);
   2719     }
   2720   } else {
   2721     if (instr->HasL()) {
   2722       set_register(rd, ReadW(addr, instr));
   2723     } else {
   2724       WriteW(addr, get_register(rd), instr);
   2725     }
   2726   }
   2727 }
   2728 
   2729 
   2730 void Simulator::DecodeType3(Instruction* instr) {
   2731   int rd = instr->RdValue();
   2732   int rn = instr->RnValue();
   2733   int32_t rn_val = get_register(rn);
   2734   bool shifter_carry_out = 0;
   2735   int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
   2736   int32_t addr = 0;
   2737   switch (instr->PUField()) {
   2738     case da_x: {
   2739       DCHECK(!instr->HasW());
   2740       Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
   2741       UNIMPLEMENTED();
   2742       break;
   2743     }
   2744     case ia_x: {
   2745       if (instr->Bit(4) == 0) {
   2746         // Memop.
   2747       } else {
   2748         if (instr->Bit(5) == 0) {
   2749           switch (instr->Bits(22, 21)) {
   2750             case 0:
   2751               if (instr->Bit(20) == 0) {
   2752                 if (instr->Bit(6) == 0) {
   2753                   // Pkhbt.
   2754                   uint32_t rn_val = get_register(rn);
   2755                   uint32_t rm_val = get_register(instr->RmValue());
   2756                   int32_t shift = instr->Bits(11, 7);
   2757                   rm_val <<= shift;
   2758                   set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
   2759                 } else {
   2760                   // Pkhtb.
   2761                   uint32_t rn_val = get_register(rn);
   2762                   int32_t rm_val = get_register(instr->RmValue());
   2763                   int32_t shift = instr->Bits(11, 7);
   2764                   if (shift == 0) {
   2765                     shift = 32;
   2766                   }
   2767                   rm_val >>= shift;
   2768                   set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
   2769                 }
   2770               } else {
   2771                 UNIMPLEMENTED();
   2772               }
   2773               break;
   2774             case 1:
   2775               UNIMPLEMENTED();
   2776               break;
   2777             case 2:
   2778               UNIMPLEMENTED();
   2779               break;
   2780             case 3: {
   2781               // Usat.
   2782               int32_t sat_pos = instr->Bits(20, 16);
   2783               int32_t sat_val = (1 << sat_pos) - 1;
   2784               int32_t shift = instr->Bits(11, 7);
   2785               int32_t shift_type = instr->Bit(6);
   2786               int32_t rm_val = get_register(instr->RmValue());
   2787               if (shift_type == 0) {  // LSL
   2788                 rm_val <<= shift;
   2789               } else {  // ASR
   2790                 rm_val >>= shift;
   2791               }
   2792               // If saturation occurs, the Q flag should be set in the CPSR.
   2793               // There is no Q flag yet, and no instruction (MRS) to read the
   2794               // CPSR directly.
   2795               if (rm_val > sat_val) {
   2796                 rm_val = sat_val;
   2797               } else if (rm_val < 0) {
   2798                 rm_val = 0;
   2799               }
   2800               set_register(rd, rm_val);
   2801               break;
   2802             }
   2803           }
   2804         } else {
   2805           switch (instr->Bits(22, 21)) {
   2806             case 0:
   2807               UNIMPLEMENTED();
   2808               break;
   2809             case 1:
   2810               if (instr->Bits(9, 6) == 1) {
   2811                 if (instr->Bit(20) == 0) {
   2812                   if (instr->Bits(19, 16) == 0xF) {
   2813                     // Sxtb.
   2814                     int32_t rm_val = get_register(instr->RmValue());
   2815                     int32_t rotate = instr->Bits(11, 10);
   2816                     switch (rotate) {
   2817                       case 0:
   2818                         break;
   2819                       case 1:
   2820                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2821                         break;
   2822                       case 2:
   2823                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2824                         break;
   2825                       case 3:
   2826                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2827                         break;
   2828                     }
   2829                     set_register(rd, static_cast<int8_t>(rm_val));
   2830                   } else {
   2831                     // Sxtab.
   2832                     int32_t rn_val = get_register(rn);
   2833                     int32_t rm_val = get_register(instr->RmValue());
   2834                     int32_t rotate = instr->Bits(11, 10);
   2835                     switch (rotate) {
   2836                       case 0:
   2837                         break;
   2838                       case 1:
   2839                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2840                         break;
   2841                       case 2:
   2842                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2843                         break;
   2844                       case 3:
   2845                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2846                         break;
   2847                     }
   2848                     set_register(rd, rn_val + static_cast<int8_t>(rm_val));
   2849                   }
   2850                 } else {
   2851                   if (instr->Bits(19, 16) == 0xF) {
   2852                     // Sxth.
   2853                     int32_t rm_val = get_register(instr->RmValue());
   2854                     int32_t rotate = instr->Bits(11, 10);
   2855                     switch (rotate) {
   2856                       case 0:
   2857                         break;
   2858                       case 1:
   2859                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2860                         break;
   2861                       case 2:
   2862                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2863                         break;
   2864                       case 3:
   2865                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2866                         break;
   2867                     }
   2868                     set_register(rd, static_cast<int16_t>(rm_val));
   2869                   } else {
   2870                     // Sxtah.
   2871                     int32_t rn_val = get_register(rn);
   2872                     int32_t rm_val = get_register(instr->RmValue());
   2873                     int32_t rotate = instr->Bits(11, 10);
   2874                     switch (rotate) {
   2875                       case 0:
   2876                         break;
   2877                       case 1:
   2878                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2879                         break;
   2880                       case 2:
   2881                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2882                         break;
   2883                       case 3:
   2884                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2885                         break;
   2886                     }
   2887                     set_register(rd, rn_val + static_cast<int16_t>(rm_val));
   2888                   }
   2889                 }
   2890               } else {
   2891                 UNREACHABLE();
   2892               }
   2893               break;
   2894             case 2:
   2895               if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
   2896                 if (instr->Bits(19, 16) == 0xF) {
   2897                   // Uxtb16.
   2898                   uint32_t rm_val = get_register(instr->RmValue());
   2899                   int32_t rotate = instr->Bits(11, 10);
   2900                   switch (rotate) {
   2901                     case 0:
   2902                       break;
   2903                     case 1:
   2904                       rm_val = (rm_val >> 8) | (rm_val << 24);
   2905                       break;
   2906                     case 2:
   2907                       rm_val = (rm_val >> 16) | (rm_val << 16);
   2908                       break;
   2909                     case 3:
   2910                       rm_val = (rm_val >> 24) | (rm_val << 8);
   2911                       break;
   2912                   }
   2913                   set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
   2914                 } else {
   2915                   UNIMPLEMENTED();
   2916                 }
   2917               } else {
   2918                 UNIMPLEMENTED();
   2919               }
   2920               break;
   2921             case 3:
   2922               if ((instr->Bits(9, 6) == 1)) {
   2923                 if (instr->Bit(20) == 0) {
   2924                   if (instr->Bits(19, 16) == 0xF) {
   2925                     // Uxtb.
   2926                     uint32_t rm_val = get_register(instr->RmValue());
   2927                     int32_t rotate = instr->Bits(11, 10);
   2928                     switch (rotate) {
   2929                       case 0:
   2930                         break;
   2931                       case 1:
   2932                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2933                         break;
   2934                       case 2:
   2935                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2936                         break;
   2937                       case 3:
   2938                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2939                         break;
   2940                     }
   2941                     set_register(rd, (rm_val & 0xFF));
   2942                   } else {
   2943                     // Uxtab.
   2944                     uint32_t rn_val = get_register(rn);
   2945                     uint32_t rm_val = get_register(instr->RmValue());
   2946                     int32_t rotate = instr->Bits(11, 10);
   2947                     switch (rotate) {
   2948                       case 0:
   2949                         break;
   2950                       case 1:
   2951                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2952                         break;
   2953                       case 2:
   2954                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2955                         break;
   2956                       case 3:
   2957                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2958                         break;
   2959                     }
   2960                     set_register(rd, rn_val + (rm_val & 0xFF));
   2961                   }
   2962                 } else {
   2963                   if (instr->Bits(19, 16) == 0xF) {
   2964                     // Uxth.
   2965                     uint32_t rm_val = get_register(instr->RmValue());
   2966                     int32_t rotate = instr->Bits(11, 10);
   2967                     switch (rotate) {
   2968                       case 0:
   2969                         break;
   2970                       case 1:
   2971                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2972                         break;
   2973                       case 2:
   2974                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2975                         break;
   2976                       case 3:
   2977                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2978                         break;
   2979                     }
   2980                     set_register(rd, (rm_val & 0xFFFF));
   2981                   } else {
   2982                     // Uxtah.
   2983                     uint32_t rn_val = get_register(rn);
   2984                     uint32_t rm_val = get_register(instr->RmValue());
   2985                     int32_t rotate = instr->Bits(11, 10);
   2986                     switch (rotate) {
   2987                       case 0:
   2988                         break;
   2989                       case 1:
   2990                         rm_val = (rm_val >> 8) | (rm_val << 24);
   2991                         break;
   2992                       case 2:
   2993                         rm_val = (rm_val >> 16) | (rm_val << 16);
   2994                         break;
   2995                       case 3:
   2996                         rm_val = (rm_val >> 24) | (rm_val << 8);
   2997                         break;
   2998                     }
   2999                     set_register(rd, rn_val + (rm_val & 0xFFFF));
   3000                   }
   3001                 }
   3002               } else {
   3003                 // PU == 0b01, BW == 0b11, Bits(9, 6) != 0b0001
   3004                 if ((instr->Bits(20, 16) == 0x1f) &&
   3005                     (instr->Bits(11, 4) == 0xf3)) {
   3006                   // Rbit.
   3007                   uint32_t rm_val = get_register(instr->RmValue());
   3008                   set_register(rd, base::bits::ReverseBits(rm_val));
   3009                 } else {
   3010                   UNIMPLEMENTED();
   3011                 }
   3012               }
   3013               break;
   3014           }
   3015         }
   3016         return;
   3017       }
   3018       break;
   3019     }
   3020     case db_x: {
   3021       if (instr->Bits(22, 20) == 0x5) {
   3022         if (instr->Bits(7, 4) == 0x1) {
   3023           int rm = instr->RmValue();
   3024           int32_t rm_val = get_register(rm);
   3025           int rs = instr->RsValue();
   3026           int32_t rs_val = get_register(rs);
   3027           if (instr->Bits(15, 12) == 0xF) {
   3028             // SMMUL (in V8 notation matching ARM ISA format)
   3029             // Format(instr, "smmul'cond 'rn, 'rm, 'rs");
   3030             rn_val = base::bits::SignedMulHigh32(rm_val, rs_val);
   3031           } else {
   3032             // SMMLA (in V8 notation matching ARM ISA format)
   3033             // Format(instr, "smmla'cond 'rn, 'rm, 'rs, 'rd");
   3034             int rd = instr->RdValue();
   3035             int32_t rd_val = get_register(rd);
   3036             rn_val = base::bits::SignedMulHighAndAdd32(rm_val, rs_val, rd_val);
   3037           }
   3038           set_register(rn, rn_val);
   3039           return;
   3040         }
   3041       }
   3042       if (instr->Bits(5, 4) == 0x1) {
   3043         if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
   3044           // (s/u)div (in V8 notation matching ARM ISA format) rn = rm/rs
   3045           // Format(instr, "'(s/u)div'cond'b 'rn, 'rm, 'rs);
   3046           int rm = instr->RmValue();
   3047           int32_t rm_val = get_register(rm);
   3048           int rs = instr->RsValue();
   3049           int32_t rs_val = get_register(rs);
   3050           int32_t ret_val = 0;
   3051           // udiv
   3052           if (instr->Bit(21) == 0x1) {
   3053             ret_val = bit_cast<int32_t>(base::bits::UnsignedDiv32(
   3054                 bit_cast<uint32_t>(rm_val), bit_cast<uint32_t>(rs_val)));
   3055           } else {
   3056             ret_val = base::bits::SignedDiv32(rm_val, rs_val);
   3057           }
   3058           set_register(rn, ret_val);
   3059           return;
   3060         }
   3061       }
   3062       // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
   3063       addr = rn_val - shifter_operand;
   3064       if (instr->HasW()) {
   3065         set_register(rn, addr);
   3066       }
   3067       break;
   3068     }
   3069     case ib_x: {
   3070       if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
   3071         uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
   3072         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
   3073         uint32_t msbit = widthminus1 + lsbit;
   3074         if (msbit <= 31) {
   3075           if (instr->Bit(22)) {
   3076             // ubfx - unsigned bitfield extract.
   3077             uint32_t rm_val =
   3078                 static_cast<uint32_t>(get_register(instr->RmValue()));
   3079             uint32_t extr_val = rm_val << (31 - msbit);
   3080             extr_val = extr_val >> (31 - widthminus1);
   3081             set_register(instr->RdValue(), extr_val);
   3082           } else {
   3083             // sbfx - signed bitfield extract.
   3084             int32_t rm_val = get_register(instr->RmValue());
   3085             int32_t extr_val = rm_val << (31 - msbit);
   3086             extr_val = extr_val >> (31 - widthminus1);
   3087             set_register(instr->RdValue(), extr_val);
   3088           }
   3089         } else {
   3090           UNREACHABLE();
   3091         }
   3092         return;
   3093       } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
   3094         uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
   3095         uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
   3096         if (msbit >= lsbit) {
   3097           // bfc or bfi - bitfield clear/insert.
   3098           uint32_t rd_val =
   3099               static_cast<uint32_t>(get_register(instr->RdValue()));
   3100           uint32_t bitcount = msbit - lsbit + 1;
   3101           uint32_t mask = 0xffffffffu >> (32 - bitcount);
   3102           rd_val &= ~(mask << lsbit);
   3103           if (instr->RmValue() != 15) {
   3104             // bfi - bitfield insert.
   3105             uint32_t rm_val =
   3106                 static_cast<uint32_t>(get_register(instr->RmValue()));
   3107             rm_val &= mask;
   3108             rd_val |= rm_val << lsbit;
   3109           }
   3110           set_register(instr->RdValue(), rd_val);
   3111         } else {
   3112           UNREACHABLE();
   3113         }
   3114         return;
   3115       } else {
   3116         // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
   3117         addr = rn_val + shifter_operand;
   3118         if (instr->HasW()) {
   3119           set_register(rn, addr);
   3120         }
   3121       }
   3122       break;
   3123     }
   3124     default: {
   3125       UNREACHABLE();
   3126       break;
   3127     }
   3128   }
   3129   if (instr->HasB()) {
   3130     if (instr->HasL()) {
   3131       uint8_t byte = ReadB(addr);
   3132       set_register(rd, byte);
   3133     } else {
   3134       uint8_t byte = get_register(rd);
   3135       WriteB(addr, byte);
   3136     }
   3137   } else {
   3138     if (instr->HasL()) {
   3139       set_register(rd, ReadW(addr, instr));
   3140     } else {
   3141       WriteW(addr, get_register(rd), instr);
   3142     }
   3143   }
   3144 }
   3145 
   3146 
   3147 void Simulator::DecodeType4(Instruction* instr) {
   3148   DCHECK(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
   3149   if (instr->HasL()) {
   3150     // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
   3151     HandleRList(instr, true);
   3152   } else {
   3153     // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
   3154     HandleRList(instr, false);
   3155   }
   3156 }
   3157 
   3158 
   3159 void Simulator::DecodeType5(Instruction* instr) {
   3160   // Format(instr, "b'l'cond 'target");
   3161   int off = (instr->SImmed24Value() << 2);
   3162   intptr_t pc_address = get_pc();
   3163   if (instr->HasLink()) {
   3164     set_register(lr, pc_address + Instruction::kInstrSize);
   3165   }
   3166   int pc_reg = get_register(pc);
   3167   set_pc(pc_reg + off);
   3168 }
   3169 
   3170 
   3171 void Simulator::DecodeType6(Instruction* instr) {
   3172   DecodeType6CoprocessorIns(instr);
   3173 }
   3174 
   3175 
   3176 void Simulator::DecodeType7(Instruction* instr) {
   3177   if (instr->Bit(24) == 1) {
   3178     SoftwareInterrupt(instr);
   3179   } else {
   3180     switch (instr->CoprocessorValue()) {
   3181       case 10:  // Fall through.
   3182       case 11:
   3183         DecodeTypeVFP(instr);
   3184         break;
   3185       case 15:
   3186         DecodeTypeCP15(instr);
   3187         break;
   3188       default:
   3189         UNIMPLEMENTED();
   3190     }
   3191   }
   3192 }
   3193 
   3194 
   3195 // void Simulator::DecodeTypeVFP(Instruction* instr)
   3196 // The Following ARMv7 VFPv instructions are currently supported.
   3197 // vmov :Sn = Rt
   3198 // vmov :Rt = Sn
   3199 // vcvt: Dd = Sm
   3200 // vcvt: Sd = Dm
   3201 // vcvt.f64.s32 Dd, Dd, #<fbits>
   3202 // Dd = vabs(Dm)
   3203 // Sd = vabs(Sm)
   3204 // Dd = vneg(Dm)
   3205 // Sd = vneg(Sm)
   3206 // Dd = vadd(Dn, Dm)
   3207 // Sd = vadd(Sn, Sm)
   3208 // Dd = vsub(Dn, Dm)
   3209 // Sd = vsub(Sn, Sm)
   3210 // Dd = vmul(Dn, Dm)
   3211 // Sd = vmul(Sn, Sm)
   3212 // Dd = vdiv(Dn, Dm)
   3213 // Sd = vdiv(Sn, Sm)
   3214 // vcmp(Dd, Dm)
   3215 // vcmp(Sd, Sm)
   3216 // Dd = vsqrt(Dm)
   3217 // Sd = vsqrt(Sm)
   3218 // vmrs
   3219 // vdup.size Qd, Rt.
   3220 void Simulator::DecodeTypeVFP(Instruction* instr) {
   3221   DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
   3222   DCHECK(instr->Bits(11, 9) == 0x5);
   3223 
   3224   // Obtain single precision register codes.
   3225   int m = instr->VFPMRegValue(kSinglePrecision);
   3226   int d = instr->VFPDRegValue(kSinglePrecision);
   3227   int n = instr->VFPNRegValue(kSinglePrecision);
   3228   // Obtain double precision register codes.
   3229   int vm = instr->VFPMRegValue(kDoublePrecision);
   3230   int vd = instr->VFPDRegValue(kDoublePrecision);
   3231   int vn = instr->VFPNRegValue(kDoublePrecision);
   3232 
   3233   if (instr->Bit(4) == 0) {
   3234     if (instr->Opc1Value() == 0x7) {
   3235       // Other data processing instructions
   3236       if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
   3237         // vmov register to register.
   3238         if (instr->SzValue() == 0x1) {
   3239           uint32_t data[2];
   3240           get_d_register(vm, data);
   3241           set_d_register(vd, data);
   3242         } else {
   3243           set_s_register(d, get_s_register(m));
   3244         }
   3245       } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
   3246         // vabs
   3247         if (instr->SzValue() == 0x1) {
   3248           double dm_value = get_double_from_d_register(vm);
   3249           double dd_value = std::fabs(dm_value);
   3250           dd_value = canonicalizeNaN(dd_value);
   3251           set_d_register_from_double(vd, dd_value);
   3252         } else {
   3253           float sm_value = get_float_from_s_register(m);
   3254           float sd_value = std::fabs(sm_value);
   3255           sd_value = canonicalizeNaN(sd_value);
   3256           set_s_register_from_float(d, sd_value);
   3257         }
   3258       } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
   3259         // vneg
   3260         if (instr->SzValue() == 0x1) {
   3261           double dm_value = get_double_from_d_register(vm);
   3262           double dd_value = -dm_value;
   3263           dd_value = canonicalizeNaN(dd_value);
   3264           set_d_register_from_double(vd, dd_value);
   3265         } else {
   3266           float sm_value = get_float_from_s_register(m);
   3267           float sd_value = -sm_value;
   3268           sd_value = canonicalizeNaN(sd_value);
   3269           set_s_register_from_float(d, sd_value);
   3270         }
   3271       } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
   3272         DecodeVCVTBetweenDoubleAndSingle(instr);
   3273       } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
   3274         DecodeVCVTBetweenFloatingPointAndInteger(instr);
   3275       } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
   3276                  (instr->Bit(8) == 1)) {
   3277         // vcvt.f64.s32 Dd, Dd, #<fbits>
   3278         int fraction_bits = 32 - ((instr->Bits(3, 0) << 1) | instr->Bit(5));
   3279         int fixed_value = get_sinteger_from_s_register(vd * 2);
   3280         double divide = 1 << fraction_bits;
   3281         set_d_register_from_double(vd, fixed_value / divide);
   3282       } else if (((instr->Opc2Value() >> 1) == 0x6) &&
   3283                  (instr->Opc3Value() & 0x1)) {
   3284         DecodeVCVTBetweenFloatingPointAndInteger(instr);
   3285       } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
   3286                  (instr->Opc3Value() & 0x1)) {
   3287         DecodeVCMP(instr);
   3288       } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
   3289         // vsqrt
   3290         lazily_initialize_fast_sqrt(isolate_);
   3291         if (instr->SzValue() == 0x1) {
   3292           double dm_value = get_double_from_d_register(vm);
   3293           double dd_value = fast_sqrt(dm_value, isolate_);
   3294           dd_value = canonicalizeNaN(dd_value);
   3295           set_d_register_from_double(vd, dd_value);
   3296         } else {
   3297           float sm_value = get_float_from_s_register(m);
   3298           float sd_value = fast_sqrt(sm_value, isolate_);
   3299           sd_value = canonicalizeNaN(sd_value);
   3300           set_s_register_from_float(d, sd_value);
   3301         }
   3302       } else if (instr->Opc3Value() == 0x0) {
   3303         // vmov immediate.
   3304         if (instr->SzValue() == 0x1) {
   3305           set_d_register_from_double(vd, instr->DoubleImmedVmov());
   3306         } else {
   3307           set_s_register_from_float(d, instr->DoubleImmedVmov());
   3308         }
   3309       } else if (((instr->Opc2Value() == 0x6)) && (instr->Opc3Value() == 0x3)) {
   3310         // vrintz - truncate
   3311         if (instr->SzValue() == 0x1) {
   3312           double dm_value = get_double_from_d_register(vm);
   3313           double dd_value = trunc(dm_value);
   3314           dd_value = canonicalizeNaN(dd_value);
   3315           set_d_register_from_double(vd, dd_value);
   3316         } else {
   3317           float sm_value = get_float_from_s_register(m);
   3318           float sd_value = truncf(sm_value);
   3319           sd_value = canonicalizeNaN(sd_value);
   3320           set_s_register_from_float(d, sd_value);
   3321         }
   3322       } else {
   3323         UNREACHABLE();  // Not used by V8.
   3324       }
   3325     } else if (instr->Opc1Value() == 0x3) {
   3326       if (instr->Opc3Value() & 0x1) {
   3327         // vsub
   3328         if (instr->SzValue() == 0x1) {
   3329           double dn_value = get_double_from_d_register(vn);
   3330           double dm_value = get_double_from_d_register(vm);
   3331           double dd_value = dn_value - dm_value;
   3332           dd_value = canonicalizeNaN(dd_value);
   3333           set_d_register_from_double(vd, dd_value);
   3334         } else {
   3335           float sn_value = get_float_from_s_register(n);
   3336           float sm_value = get_float_from_s_register(m);
   3337           float sd_value = sn_value - sm_value;
   3338           sd_value = canonicalizeNaN(sd_value);
   3339           set_s_register_from_float(d, sd_value);
   3340         }
   3341       } else {
   3342         // vadd
   3343         if (instr->SzValue() == 0x1) {
   3344           double dn_value = get_double_from_d_register(vn);
   3345           double dm_value = get_double_from_d_register(vm);
   3346           double dd_value = dn_value + dm_value;
   3347           dd_value = canonicalizeNaN(dd_value);
   3348           set_d_register_from_double(vd, dd_value);
   3349         } else {
   3350           float sn_value = get_float_from_s_register(n);
   3351           float sm_value = get_float_from_s_register(m);
   3352           float sd_value = sn_value + sm_value;
   3353           sd_value = canonicalizeNaN(sd_value);
   3354           set_s_register_from_float(d, sd_value);
   3355         }
   3356       }
   3357     } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
   3358       // vmul
   3359       if (instr->SzValue() == 0x1) {
   3360         double dn_value = get_double_from_d_register(vn);
   3361         double dm_value = get_double_from_d_register(vm);
   3362         double dd_value = dn_value * dm_value;
   3363         dd_value = canonicalizeNaN(dd_value);
   3364         set_d_register_from_double(vd, dd_value);
   3365       } else {
   3366         float sn_value = get_float_from_s_register(n);
   3367         float sm_value = get_float_from_s_register(m);
   3368         float sd_value = sn_value * sm_value;
   3369         sd_value = canonicalizeNaN(sd_value);
   3370         set_s_register_from_float(d, sd_value);
   3371       }
   3372     } else if ((instr->Opc1Value() == 0x0)) {
   3373       // vmla, vmls
   3374       const bool is_vmls = (instr->Opc3Value() & 0x1);
   3375       if (instr->SzValue() == 0x1) {
   3376         const double dd_val = get_double_from_d_register(vd);
   3377         const double dn_val = get_double_from_d_register(vn);
   3378         const double dm_val = get_double_from_d_register(vm);
   3379 
   3380         // Note: we do the mul and add/sub in separate steps to avoid getting a
   3381         // result with too high precision.
   3382         set_d_register_from_double(vd, dn_val * dm_val);
   3383         if (is_vmls) {
   3384           set_d_register_from_double(
   3385               vd, canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
   3386         } else {
   3387           set_d_register_from_double(
   3388               vd, canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
   3389         }
   3390       } else {
   3391         const float sd_val = get_float_from_s_register(d);
   3392         const float sn_val = get_float_from_s_register(n);
   3393         const float sm_val = get_float_from_s_register(m);
   3394 
   3395         // Note: we do the mul and add/sub in separate steps to avoid getting a
   3396         // result with too high precision.
   3397         set_s_register_from_float(d, sn_val * sm_val);
   3398         if (is_vmls) {
   3399           set_s_register_from_float(
   3400               d, canonicalizeNaN(sd_val - get_float_from_s_register(d)));
   3401         } else {
   3402           set_s_register_from_float(
   3403               d, canonicalizeNaN(sd_val + get_float_from_s_register(d)));
   3404         }
   3405       }
   3406     } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
   3407       // vdiv
   3408       if (instr->SzValue() == 0x1) {
   3409         double dn_value = get_double_from_d_register(vn);
   3410         double dm_value = get_double_from_d_register(vm);
   3411         double dd_value = dn_value / dm_value;
   3412         div_zero_vfp_flag_ = (dm_value == 0);
   3413         dd_value = canonicalizeNaN(dd_value);
   3414         set_d_register_from_double(vd, dd_value);
   3415       } else {
   3416         float sn_value = get_float_from_s_register(n);
   3417         float sm_value = get_float_from_s_register(m);
   3418         float sd_value = sn_value / sm_value;
   3419         div_zero_vfp_flag_ = (sm_value == 0);
   3420         sd_value = canonicalizeNaN(sd_value);
   3421         set_s_register_from_float(d, sd_value);
   3422       }
   3423     } else {
   3424       UNIMPLEMENTED();  // Not used by V8.
   3425     }
   3426   } else {
   3427     if ((instr->VCValue() == 0x0) &&
   3428         (instr->VAValue() == 0x0)) {
   3429       DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
   3430     } else if ((instr->VLValue() == 0x0) && (instr->VCValue() == 0x1)) {
   3431       if (instr->Bit(23) == 0) {
   3432         // vmov (ARM core register to scalar)
   3433         int vd = instr->VFPNRegValue(kDoublePrecision);
   3434         int rt = instr->RtValue();
   3435         int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
   3436         if ((opc1_opc2 & 0xb) == 0) {
   3437           // NeonS32/NeonU32
   3438           uint32_t data[2];
   3439           get_d_register(vd, data);
   3440           data[instr->Bit(21)] = get_register(rt);
   3441           set_d_register(vd, data);
   3442         } else {
   3443           uint64_t data;
   3444           get_d_register(vd, &data);
   3445           uint64_t rt_value = get_register(rt);
   3446           if ((opc1_opc2 & 0x8) != 0) {
   3447             // NeonS8 / NeonU8
   3448             int i = opc1_opc2 & 0x7;
   3449             int shift = i * kBitsPerByte;
   3450             const uint64_t mask = 0xFF;
   3451             data &= ~(mask << shift);
   3452             data |= (rt_value & mask) << shift;
   3453             set_d_register(vd, &data);
   3454           } else if ((opc1_opc2 & 0x1) != 0) {
   3455             // NeonS16 / NeonU16
   3456             int i = (opc1_opc2 >> 1) & 0x3;
   3457             int shift = i * kBitsPerByte * kShortSize;
   3458             const uint64_t mask = 0xFFFF;
   3459             data &= ~(mask << shift);
   3460             data |= (rt_value & mask) << shift;
   3461             set_d_register(vd, &data);
   3462           } else {
   3463             UNREACHABLE();  // Not used by V8.
   3464           }
   3465         }
   3466       } else {
   3467         // vdup.size Qd, Rt.
   3468         NeonSize size = Neon32;
   3469         if (instr->Bit(5) != 0)
   3470           size = Neon16;
   3471         else if (instr->Bit(22) != 0)
   3472           size = Neon8;
   3473         int vd = instr->VFPNRegValue(kSimd128Precision);
   3474         int rt = instr->RtValue();
   3475         uint32_t rt_value = get_register(rt);
   3476         uint32_t q_data[4];
   3477         switch (size) {
   3478           case Neon8: {
   3479             rt_value &= 0xFF;
   3480             uint8_t* dst = reinterpret_cast<uint8_t*>(q_data);
   3481             for (int i = 0; i < 16; i++) {
   3482               dst[i] = rt_value;
   3483             }
   3484             break;
   3485           }
   3486           case Neon16: {
   3487             // Perform pairwise op.
   3488             rt_value &= 0xFFFFu;
   3489             uint32_t rt_rt = (rt_value << 16) | (rt_value & 0xFFFFu);
   3490             for (int i = 0; i < 4; i++) {
   3491               q_data[i] = rt_rt;
   3492             }
   3493             break;
   3494           }
   3495           case Neon32: {
   3496             for (int i = 0; i < 4; i++) {
   3497               q_data[i] = rt_value;
   3498             }
   3499             break;
   3500           }
   3501           default:
   3502             UNREACHABLE();
   3503             break;
   3504         }
   3505         set_q_register(vd, q_data);
   3506       }
   3507     } else if ((instr->VLValue() == 0x1) && (instr->VCValue() == 0x1)) {
   3508       // vmov (scalar to ARM core register)
   3509       int vn = instr->VFPNRegValue(kDoublePrecision);
   3510       int rt = instr->RtValue();
   3511       int opc1_opc2 = (instr->Bits(22, 21) << 2) | instr->Bits(6, 5);
   3512       uint64_t data;
   3513       get_d_register(vn, &data);
   3514       if ((opc1_opc2 & 0xb) == 0) {
   3515         // NeonS32 / NeonU32
   3516         int32_t int_data[2];
   3517         memcpy(int_data, &data, sizeof(int_data));
   3518         set_register(rt, int_data[instr->Bit(21)]);
   3519       } else {
   3520         uint64_t data;
   3521         get_d_register(vn, &data);
   3522         bool u = instr->Bit(23) != 0;
   3523         if ((opc1_opc2 & 0x8) != 0) {
   3524           // NeonS8 / NeonU8
   3525           int i = opc1_opc2 & 0x7;
   3526           int shift = i * kBitsPerByte;
   3527           uint32_t scalar = (data >> shift) & 0xFFu;
   3528           if (!u && (scalar & 0x80) != 0) scalar |= 0xffffff00;
   3529           set_register(rt, scalar);
   3530         } else if ((opc1_opc2 & 0x1) != 0) {
   3531           // NeonS16 / NeonU16
   3532           int i = (opc1_opc2 >> 1) & 0x3;
   3533           int shift = i * kBitsPerByte * kShortSize;
   3534           uint32_t scalar = (data >> shift) & 0xFFFFu;
   3535           if (!u && (scalar & 0x8000) != 0) scalar |= 0xffff0000;
   3536           set_register(rt, scalar);
   3537         } else {
   3538           UNREACHABLE();  // Not used by V8.
   3539         }
   3540       }
   3541     } else if ((instr->VLValue() == 0x1) &&
   3542                (instr->VCValue() == 0x0) &&
   3543                (instr->VAValue() == 0x7) &&
   3544                (instr->Bits(19, 16) == 0x1)) {
   3545       // vmrs
   3546       uint32_t rt = instr->RtValue();
   3547       if (rt == 0xF) {
   3548         Copy_FPSCR_to_APSR();
   3549       } else {
   3550         // Emulate FPSCR from the Simulator flags.
   3551         uint32_t fpscr = (n_flag_FPSCR_ << 31) |
   3552                          (z_flag_FPSCR_ << 30) |
   3553                          (c_flag_FPSCR_ << 29) |
   3554                          (v_flag_FPSCR_ << 28) |
   3555                          (FPSCR_default_NaN_mode_ << 25) |
   3556                          (inexact_vfp_flag_ << 4) |
   3557                          (underflow_vfp_flag_ << 3) |
   3558                          (overflow_vfp_flag_ << 2) |
   3559                          (div_zero_vfp_flag_ << 1) |
   3560                          (inv_op_vfp_flag_ << 0) |
   3561                          (FPSCR_rounding_mode_);
   3562         set_register(rt, fpscr);
   3563       }
   3564     } else if ((instr->VLValue() == 0x0) &&
   3565                (instr->VCValue() == 0x0) &&
   3566                (instr->VAValue() == 0x7) &&
   3567                (instr->Bits(19, 16) == 0x1)) {
   3568       // vmsr
   3569       uint32_t rt = instr->RtValue();
   3570       if (rt == pc) {
   3571         UNREACHABLE();
   3572       } else {
   3573         uint32_t rt_value = get_register(rt);
   3574         n_flag_FPSCR_ = (rt_value >> 31) & 1;
   3575         z_flag_FPSCR_ = (rt_value >> 30) & 1;
   3576         c_flag_FPSCR_ = (rt_value >> 29) & 1;
   3577         v_flag_FPSCR_ = (rt_value >> 28) & 1;
   3578         FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
   3579         inexact_vfp_flag_ = (rt_value >> 4) & 1;
   3580         underflow_vfp_flag_ = (rt_value >> 3) & 1;
   3581         overflow_vfp_flag_ = (rt_value >> 2) & 1;
   3582         div_zero_vfp_flag_ = (rt_value >> 1) & 1;
   3583         inv_op_vfp_flag_ = (rt_value >> 0) & 1;
   3584         FPSCR_rounding_mode_ =
   3585             static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
   3586       }
   3587     } else {
   3588       UNIMPLEMENTED();  // Not used by V8.
   3589     }
   3590   }
   3591 }
   3592 
   3593 void Simulator::DecodeTypeCP15(Instruction* instr) {
   3594   DCHECK((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0));
   3595   DCHECK(instr->CoprocessorValue() == 15);
   3596 
   3597   if (instr->Bit(4) == 1) {
   3598     // mcr
   3599     int crn = instr->Bits(19, 16);
   3600     int crm = instr->Bits(3, 0);
   3601     int opc1 = instr->Bits(23, 21);
   3602     int opc2 = instr->Bits(7, 5);
   3603     if ((opc1 == 0) && (crn == 7)) {
   3604       // ARMv6 memory barrier operations.
   3605       // Details available in ARM DDI 0406C.b, B3-1750.
   3606       if (((crm == 10) && (opc2 == 5)) ||  // CP15DMB
   3607           ((crm == 10) && (opc2 == 4)) ||  // CP15DSB
   3608           ((crm == 5) && (opc2 == 4))) {   // CP15ISB
   3609         // These are ignored by the simulator for now.
   3610       } else {
   3611         UNIMPLEMENTED();
   3612       }
   3613     }
   3614   } else {
   3615     UNIMPLEMENTED();
   3616   }
   3617 }
   3618 
   3619 void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
   3620     Instruction* instr) {
   3621   DCHECK((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
   3622          (instr->VAValue() == 0x0));
   3623 
   3624   int t = instr->RtValue();
   3625   int n = instr->VFPNRegValue(kSinglePrecision);
   3626   bool to_arm_register = (instr->VLValue() == 0x1);
   3627 
   3628   if (to_arm_register) {
   3629     int32_t int_value = get_sinteger_from_s_register(n);
   3630     set_register(t, int_value);
   3631   } else {
   3632     int32_t rs_val = get_register(t);
   3633     set_s_register_from_sinteger(n, rs_val);
   3634   }
   3635 }
   3636 
   3637 
   3638 void Simulator::DecodeVCMP(Instruction* instr) {
   3639   DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
   3640   DCHECK(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
   3641          (instr->Opc3Value() & 0x1));
   3642   // Comparison.
   3643 
   3644   VFPRegPrecision precision = kSinglePrecision;
   3645   if (instr->SzValue() == 0x1) {
   3646     precision = kDoublePrecision;
   3647   }
   3648 
   3649   int d = instr->VFPDRegValue(precision);
   3650   int m = 0;
   3651   if (instr->Opc2Value() == 0x4) {
   3652     m = instr->VFPMRegValue(precision);
   3653   }
   3654 
   3655   if (precision == kDoublePrecision) {
   3656     double dd_value = get_double_from_d_register(d);
   3657     double dm_value = 0.0;
   3658     if (instr->Opc2Value() == 0x4) {
   3659       dm_value = get_double_from_d_register(m);
   3660     }
   3661 
   3662     // Raise exceptions for quiet NaNs if necessary.
   3663     if (instr->Bit(7) == 1) {
   3664       if (std::isnan(dd_value)) {
   3665         inv_op_vfp_flag_ = true;
   3666       }
   3667     }
   3668 
   3669     Compute_FPSCR_Flags(dd_value, dm_value);
   3670   } else {
   3671     float sd_value = get_float_from_s_register(d);
   3672     float sm_value = 0.0;
   3673     if (instr->Opc2Value() == 0x4) {
   3674       sm_value = get_float_from_s_register(m);
   3675     }
   3676 
   3677     // Raise exceptions for quiet NaNs if necessary.
   3678     if (instr->Bit(7) == 1) {
   3679       if (std::isnan(sd_value)) {
   3680         inv_op_vfp_flag_ = true;
   3681       }
   3682     }
   3683 
   3684     Compute_FPSCR_Flags(sd_value, sm_value);
   3685   }
   3686 }
   3687 
   3688 
   3689 void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
   3690   DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
   3691   DCHECK((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
   3692 
   3693   VFPRegPrecision dst_precision = kDoublePrecision;
   3694   VFPRegPrecision src_precision = kSinglePrecision;
   3695   if (instr->SzValue() == 1) {
   3696     dst_precision = kSinglePrecision;
   3697     src_precision = kDoublePrecision;
   3698   }
   3699 
   3700   int dst = instr->VFPDRegValue(dst_precision);
   3701   int src = instr->VFPMRegValue(src_precision);
   3702 
   3703   if (dst_precision == kSinglePrecision) {
   3704     double val = get_double_from_d_register(src);
   3705     set_s_register_from_float(dst, static_cast<float>(val));
   3706   } else {
   3707     float val = get_float_from_s_register(src);
   3708     set_d_register_from_double(dst, static_cast<double>(val));
   3709   }
   3710 }
   3711 
   3712 bool get_inv_op_vfp_flag(VFPRoundingMode mode,
   3713                          double val,
   3714                          bool unsigned_) {
   3715   DCHECK((mode == RN) || (mode == RM) || (mode == RZ));
   3716   double max_uint = static_cast<double>(0xffffffffu);
   3717   double max_int = static_cast<double>(kMaxInt);
   3718   double min_int = static_cast<double>(kMinInt);
   3719 
   3720   // Check for NaN.
   3721   if (val != val) {
   3722     return true;
   3723   }
   3724 
   3725   // Check for overflow. This code works because 32bit integers can be
   3726   // exactly represented by ieee-754 64bit floating-point values.
   3727   switch (mode) {
   3728     case RN:
   3729       return  unsigned_ ? (val >= (max_uint + 0.5)) ||
   3730                           (val < -0.5)
   3731                         : (val >= (max_int + 0.5)) ||
   3732                           (val < (min_int - 0.5));
   3733 
   3734     case RM:
   3735       return  unsigned_ ? (val >= (max_uint + 1.0)) ||
   3736                           (val < 0)
   3737                         : (val >= (max_int + 1.0)) ||
   3738                           (val < min_int);
   3739 
   3740     case RZ:
   3741       return  unsigned_ ? (val >= (max_uint + 1.0)) ||
   3742                           (val <= -1)
   3743                         : (val >= (max_int + 1.0)) ||
   3744                           (val <= (min_int - 1.0));
   3745     default:
   3746       UNREACHABLE();
   3747       return true;
   3748   }
   3749 }
   3750 
   3751 
   3752 // We call this function only if we had a vfp invalid exception.
   3753 // It returns the correct saturated value.
   3754 int VFPConversionSaturate(double val, bool unsigned_res) {
   3755   if (val != val) {
   3756     return 0;
   3757   } else {
   3758     if (unsigned_res) {
   3759       return (val < 0) ? 0 : 0xffffffffu;
   3760     } else {
   3761       return (val < 0) ? kMinInt : kMaxInt;
   3762     }
   3763   }
   3764 }
   3765 
   3766 int32_t Simulator::ConvertDoubleToInt(double val, bool unsigned_integer,
   3767                                       VFPRoundingMode mode) {
   3768   int32_t result =
   3769       unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
   3770 
   3771   inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
   3772 
   3773   double abs_diff = unsigned_integer
   3774                         ? std::fabs(val - static_cast<uint32_t>(result))
   3775                         : std::fabs(val - result);
   3776 
   3777   inexact_vfp_flag_ = (abs_diff != 0);
   3778 
   3779   if (inv_op_vfp_flag_) {
   3780     result = VFPConversionSaturate(val, unsigned_integer);
   3781   } else {
   3782     switch (mode) {
   3783       case RN: {
   3784         int val_sign = (val > 0) ? 1 : -1;
   3785         if (abs_diff > 0.5) {
   3786           result += val_sign;
   3787         } else if (abs_diff == 0.5) {
   3788           // Round to even if exactly halfway.
   3789           result = ((result % 2) == 0) ? result : result + val_sign;
   3790         }
   3791         break;
   3792       }
   3793 
   3794       case RM:
   3795         result = result > val ? result - 1 : result;
   3796         break;
   3797 
   3798       case RZ:
   3799         // Nothing to do.
   3800         break;
   3801 
   3802       default:
   3803         UNREACHABLE();
   3804     }
   3805   }
   3806   return result;
   3807 }
   3808 
   3809 void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
   3810   DCHECK((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
   3811          (instr->Bits(27, 23) == 0x1D));
   3812   DCHECK(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
   3813          (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
   3814 
   3815   // Conversion between floating-point and integer.
   3816   bool to_integer = (instr->Bit(18) == 1);
   3817 
   3818   VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
   3819                                                           : kSinglePrecision;
   3820 
   3821   if (to_integer) {
   3822     // We are playing with code close to the C++ standard's limits below,
   3823     // hence the very simple code and heavy checks.
   3824     //
   3825     // Note:
   3826     // C++ defines default type casting from floating point to integer as
   3827     // (close to) rounding toward zero ("fractional part discarded").
   3828 
   3829     int dst = instr->VFPDRegValue(kSinglePrecision);
   3830     int src = instr->VFPMRegValue(src_precision);
   3831 
   3832     // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
   3833     // mode or the default Round to Zero mode.
   3834     VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
   3835                                                 : RZ;
   3836     DCHECK((mode == RM) || (mode == RZ) || (mode == RN));
   3837 
   3838     bool unsigned_integer = (instr->Bit(16) == 0);
   3839     bool double_precision = (src_precision == kDoublePrecision);
   3840 
   3841     double val = double_precision ? get_double_from_d_register(src)
   3842                                   : get_float_from_s_register(src);
   3843 
   3844     int32_t temp = ConvertDoubleToInt(val, unsigned_integer, mode);
   3845 
   3846     // Update the destination register.
   3847     set_s_register_from_sinteger(dst, temp);
   3848 
   3849   } else {
   3850     bool unsigned_integer = (instr->Bit(7) == 0);
   3851 
   3852     int dst = instr->VFPDRegValue(src_precision);
   3853     int src = instr->VFPMRegValue(kSinglePrecision);
   3854 
   3855     int val = get_sinteger_from_s_register(src);
   3856 
   3857     if (src_precision == kDoublePrecision) {
   3858       if (unsigned_integer) {
   3859         set_d_register_from_double(
   3860             dst, static_cast<double>(static_cast<uint32_t>(val)));
   3861       } else {
   3862         set_d_register_from_double(dst, static_cast<double>(val));
   3863       }
   3864     } else {
   3865       if (unsigned_integer) {
   3866         set_s_register_from_float(
   3867             dst, static_cast<float>(static_cast<uint32_t>(val)));
   3868       } else {
   3869         set_s_register_from_float(dst, static_cast<float>(val));
   3870       }
   3871     }
   3872   }
   3873 }
   3874 
   3875 
   3876 // void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
   3877 // Decode Type 6 coprocessor instructions.
   3878 // Dm = vmov(Rt, Rt2)
   3879 // <Rt, Rt2> = vmov(Dm)
   3880 // Ddst = MEM(Rbase + 4*offset).
   3881 // MEM(Rbase + 4*offset) = Dsrc.
   3882 void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
   3883   DCHECK((instr->TypeValue() == 6));
   3884 
   3885   if (instr->CoprocessorValue() == 0xA) {
   3886     switch (instr->OpcodeValue()) {
   3887       case 0x8:
   3888       case 0xA:
   3889       case 0xC:
   3890       case 0xE: {  // Load and store single precision float to memory.
   3891         int rn = instr->RnValue();
   3892         int vd = instr->VFPDRegValue(kSinglePrecision);
   3893         int offset = instr->Immed8Value();
   3894         if (!instr->HasU()) {
   3895           offset = -offset;
   3896         }
   3897 
   3898         int32_t address = get_register(rn) + 4 * offset;
   3899         // Load and store address for singles must be at least four-byte
   3900         // aligned.
   3901         DCHECK((address % 4) == 0);
   3902         if (instr->HasL()) {
   3903           // Load single from memory: vldr.
   3904           set_s_register_from_sinteger(vd, ReadW(address, instr));
   3905         } else {
   3906           // Store single to memory: vstr.
   3907           WriteW(address, get_sinteger_from_s_register(vd), instr);
   3908         }
   3909         break;
   3910       }
   3911       case 0x4:
   3912       case 0x5:
   3913       case 0x6:
   3914       case 0x7:
   3915       case 0x9:
   3916       case 0xB:
   3917         // Load/store multiple single from memory: vldm/vstm.
   3918         HandleVList(instr);
   3919         break;
   3920       default:
   3921         UNIMPLEMENTED();  // Not used by V8.
   3922     }
   3923   } else if (instr->CoprocessorValue() == 0xB) {
   3924     switch (instr->OpcodeValue()) {
   3925       case 0x2:
   3926         // Load and store double to two GP registers
   3927         if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
   3928           UNIMPLEMENTED();  // Not used by V8.
   3929         } else {
   3930           int rt = instr->RtValue();
   3931           int rn = instr->RnValue();
   3932           int vm = instr->VFPMRegValue(kDoublePrecision);
   3933           if (instr->HasL()) {
   3934             uint32_t data[2];
   3935             get_d_register(vm, data);
   3936             set_register(rt, data[0]);
   3937             set_register(rn, data[1]);
   3938           } else {
   3939             int32_t data[] = { get_register(rt), get_register(rn) };
   3940             set_d_register(vm, reinterpret_cast<uint32_t*>(data));
   3941           }
   3942         }
   3943         break;
   3944       case 0x8:
   3945       case 0xA:
   3946       case 0xC:
   3947       case 0xE: {  // Load and store double to memory.
   3948         int rn = instr->RnValue();
   3949         int vd = instr->VFPDRegValue(kDoublePrecision);
   3950         int offset = instr->Immed8Value();
   3951         if (!instr->HasU()) {
   3952           offset = -offset;
   3953         }
   3954         int32_t address = get_register(rn) + 4 * offset;
   3955         // Load and store address for doubles must be at least four-byte
   3956         // aligned.
   3957         DCHECK((address % 4) == 0);
   3958         if (instr->HasL()) {
   3959           // Load double from memory: vldr.
   3960           int32_t data[] = {
   3961             ReadW(address, instr),
   3962             ReadW(address + 4, instr)
   3963           };
   3964           set_d_register(vd, reinterpret_cast<uint32_t*>(data));
   3965         } else {
   3966           // Store double to memory: vstr.
   3967           uint32_t data[2];
   3968           get_d_register(vd, data);
   3969           WriteW(address, data[0], instr);
   3970           WriteW(address + 4, data[1], instr);
   3971         }
   3972         break;
   3973       }
   3974       case 0x4:
   3975       case 0x5:
   3976       case 0x6:
   3977       case 0x7:
   3978       case 0x9:
   3979       case 0xB:
   3980         // Load/store multiple double from memory: vldm/vstm.
   3981         HandleVList(instr);
   3982         break;
   3983       default:
   3984         UNIMPLEMENTED();  // Not used by V8.
   3985     }
   3986   } else {
   3987     UNIMPLEMENTED();  // Not used by V8.
   3988   }
   3989 }
   3990 
   3991 // Templated operations for NEON instructions.
   3992 // TODO(bbudge) Add more templates for use in DecodeSpecialCondition.
   3993 template <typename T>
   3994 int64_t Widen(T value) {
   3995   static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller");
   3996   return static_cast<int64_t>(value);
   3997 }
   3998 
   3999 template <typename T>
   4000 T Clamp(int64_t value) {
   4001   static_assert(sizeof(int64_t) > sizeof(T), "T must be int32_t or smaller");
   4002   int64_t min = static_cast<int64_t>(std::numeric_limits<T>::min());
   4003   int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max());
   4004   int64_t clamped = std::max(min, std::min(max, value));
   4005   return static_cast<T>(clamped);
   4006 }
   4007 
   4008 template <typename T>
   4009 void AddSaturate(Simulator* simulator, int Vd, int Vm, int Vn) {
   4010   static const int kLanes = 16 / sizeof(T);
   4011   T src1[kLanes], src2[kLanes];
   4012   simulator->get_q_register(Vn, src1);
   4013   simulator->get_q_register(Vm, src2);
   4014   for (int i = 0; i < kLanes; i++) {
   4015     src1[i] = Clamp<T>(Widen(src1[i]) + Widen(src2[i]));
   4016   }
   4017   simulator->set_q_register(Vd, src1);
   4018 }
   4019 
   4020 template <typename T>
   4021 void SubSaturate(Simulator* simulator, int Vd, int Vm, int Vn) {
   4022   static const int kLanes = 16 / sizeof(T);
   4023   T src1[kLanes], src2[kLanes];
   4024   simulator->get_q_register(Vn, src1);
   4025   simulator->get_q_register(Vm, src2);
   4026   for (int i = 0; i < kLanes; i++) {
   4027     src1[i] = Clamp<T>(Widen(src1[i]) - Widen(src2[i]));
   4028   }
   4029   simulator->set_q_register(Vd, src1);
   4030 }
   4031 
   4032 void Simulator::DecodeSpecialCondition(Instruction* instr) {
   4033   switch (instr->SpecialValue()) {
   4034     case 4: {
   4035       int Vd, Vm, Vn;
   4036       if (instr->Bit(6) == 0) {
   4037         Vd = instr->VFPDRegValue(kDoublePrecision);
   4038         Vm = instr->VFPMRegValue(kDoublePrecision);
   4039         Vn = instr->VFPNRegValue(kDoublePrecision);
   4040       } else {
   4041         Vd = instr->VFPDRegValue(kSimd128Precision);
   4042         Vm = instr->VFPMRegValue(kSimd128Precision);
   4043         Vn = instr->VFPNRegValue(kSimd128Precision);
   4044       }
   4045       switch (instr->Bits(11, 8)) {
   4046         case 0x0: {
   4047           if (instr->Bit(4) == 1) {
   4048             // vqadd.s<size> Qd, Qm, Qn.
   4049             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4050             switch (size) {
   4051               case Neon8:
   4052                 AddSaturate<int8_t>(this, Vd, Vm, Vn);
   4053                 break;
   4054               case Neon16:
   4055                 AddSaturate<int16_t>(this, Vd, Vm, Vn);
   4056                 break;
   4057               case Neon32:
   4058                 AddSaturate<int32_t>(this, Vd, Vm, Vn);
   4059                 break;
   4060               default:
   4061                 UNREACHABLE();
   4062                 break;
   4063             }
   4064           } else {
   4065             UNIMPLEMENTED();
   4066           }
   4067           break;
   4068         }
   4069         case 0x1: {
   4070           if (instr->Bits(21, 20) == 2 && instr->Bit(6) == 1 &&
   4071               instr->Bit(4) == 1) {
   4072             // vmov Qd, Qm.
   4073             // vorr, Qd, Qm, Qn.
   4074             uint32_t src1[4];
   4075             get_q_register(Vm, src1);
   4076             if (Vm != Vn) {
   4077               uint32_t src2[4];
   4078               get_q_register(Vn, src2);
   4079               for (int i = 0; i < 4; i++) {
   4080                 src1[i] = src1[i] | src2[i];
   4081               }
   4082             }
   4083             set_q_register(Vd, src1);
   4084           } else if (instr->Bits(21, 20) == 0 && instr->Bit(6) == 1 &&
   4085                      instr->Bit(4) == 1) {
   4086             // vand Qd, Qm, Qn.
   4087             uint32_t src1[4], src2[4];
   4088             get_q_register(Vn, src1);
   4089             get_q_register(Vm, src2);
   4090             for (int i = 0; i < 4; i++) {
   4091               src1[i] = src1[i] & src2[i];
   4092             }
   4093             set_q_register(Vd, src1);
   4094           } else {
   4095             UNIMPLEMENTED();
   4096           }
   4097           break;
   4098         }
   4099         case 0x2: {
   4100           if (instr->Bit(4) == 1) {
   4101             // vqsub.s<size> Qd, Qm, Qn.
   4102             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4103             switch (size) {
   4104               case Neon8:
   4105                 SubSaturate<int8_t>(this, Vd, Vm, Vn);
   4106                 break;
   4107               case Neon16:
   4108                 SubSaturate<int16_t>(this, Vd, Vm, Vn);
   4109                 break;
   4110               case Neon32:
   4111                 SubSaturate<int32_t>(this, Vd, Vm, Vn);
   4112                 break;
   4113               default:
   4114                 UNREACHABLE();
   4115                 break;
   4116             }
   4117           } else {
   4118             UNIMPLEMENTED();
   4119           }
   4120           break;
   4121         }
   4122         case 0x3: {
   4123           // vcge/vcgt.s<size> Qd, Qm, Qn.
   4124           bool ge = instr->Bit(4) == 1;
   4125           NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4126           switch (size) {
   4127             case Neon8: {
   4128               int8_t src1[16], src2[16];
   4129               get_q_register(Vn, src1);
   4130               get_q_register(Vm, src2);
   4131               for (int i = 0; i < 16; i++) {
   4132                 if (ge)
   4133                   src1[i] = src1[i] >= src2[i] ? 0xFF : 0;
   4134                 else
   4135                   src1[i] = src1[i] > src2[i] ? 0xFF : 0;
   4136               }
   4137               set_q_register(Vd, src1);
   4138               break;
   4139             }
   4140             case Neon16: {
   4141               int16_t src1[8], src2[8];
   4142               get_q_register(Vn, src1);
   4143               get_q_register(Vm, src2);
   4144               for (int i = 0; i < 8; i++) {
   4145                 if (ge)
   4146                   src1[i] = src1[i] >= src2[i] ? 0xFFFF : 0;
   4147                 else
   4148                   src1[i] = src1[i] > src2[i] ? 0xFFFF : 0;
   4149               }
   4150               set_q_register(Vd, src1);
   4151               break;
   4152             }
   4153             case Neon32: {
   4154               int32_t src1[4], src2[4];
   4155               get_q_register(Vn, src1);
   4156               get_q_register(Vm, src2);
   4157               for (int i = 0; i < 4; i++) {
   4158                 if (ge)
   4159                   src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFF : 0;
   4160                 else
   4161                   src1[i] = src1[i] > src2[i] ? 0xFFFFFFFF : 0;
   4162               }
   4163               set_q_register(Vd, src1);
   4164               break;
   4165             }
   4166             default:
   4167               UNREACHABLE();
   4168               break;
   4169           }
   4170           break;
   4171         }
   4172         case 0x6: {
   4173           // vmin/vmax.s<size> Qd, Qm, Qn.
   4174           NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4175           bool min = instr->Bit(4) != 0;
   4176           switch (size) {
   4177             case Neon8: {
   4178               int8_t src1[16], src2[16];
   4179               get_q_register(Vn, src1);
   4180               get_q_register(Vm, src2);
   4181               for (int i = 0; i < 16; i++) {
   4182                 if (min)
   4183                   src1[i] = std::min(src1[i], src2[i]);
   4184                 else
   4185                   src1[i] = std::max(src1[i], src2[i]);
   4186               }
   4187               set_q_register(Vd, src1);
   4188               break;
   4189             }
   4190             case Neon16: {
   4191               int16_t src1[8], src2[8];
   4192               get_q_register(Vn, src1);
   4193               get_q_register(Vm, src2);
   4194               for (int i = 0; i < 8; i++) {
   4195                 if (min)
   4196                   src1[i] = std::min(src1[i], src2[i]);
   4197                 else
   4198                   src1[i] = std::max(src1[i], src2[i]);
   4199               }
   4200               set_q_register(Vd, src1);
   4201               break;
   4202             }
   4203             case Neon32: {
   4204               int32_t src1[4], src2[4];
   4205               get_q_register(Vn, src1);
   4206               get_q_register(Vm, src2);
   4207               for (int i = 0; i < 4; i++) {
   4208                 if (min)
   4209                   src1[i] = std::min(src1[i], src2[i]);
   4210                 else
   4211                   src1[i] = std::max(src1[i], src2[i]);
   4212               }
   4213               set_q_register(Vd, src1);
   4214               break;
   4215             }
   4216             default:
   4217               UNREACHABLE();
   4218               break;
   4219           }
   4220           break;
   4221         }
   4222         case 0x8: {
   4223           // vadd/vtst
   4224           NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4225           if (instr->Bit(4) == 0) {
   4226             // vadd.i<size> Qd, Qm, Qn.
   4227             switch (size) {
   4228               case Neon8: {
   4229                 uint8_t src1[16], src2[16];
   4230                 get_q_register(Vn, src1);
   4231                 get_q_register(Vm, src2);
   4232                 for (int i = 0; i < 16; i++) {
   4233                   src1[i] += src2[i];
   4234                 }
   4235                 set_q_register(Vd, src1);
   4236                 break;
   4237               }
   4238               case Neon16: {
   4239                 uint16_t src1[8], src2[8];
   4240                 get_q_register(Vn, src1);
   4241                 get_q_register(Vm, src2);
   4242                 for (int i = 0; i < 8; i++) {
   4243                   src1[i] += src2[i];
   4244                 }
   4245                 set_q_register(Vd, src1);
   4246                 break;
   4247               }
   4248               case Neon32: {
   4249                 uint32_t src1[4], src2[4];
   4250                 get_q_register(Vn, src1);
   4251                 get_q_register(Vm, src2);
   4252                 for (int i = 0; i < 4; i++) {
   4253                   src1[i] += src2[i];
   4254                 }
   4255                 set_q_register(Vd, src1);
   4256                 break;
   4257               }
   4258               default:
   4259                 UNREACHABLE();
   4260                 break;
   4261             }
   4262           } else {
   4263             // vtst.i<size> Qd, Qm, Qn.
   4264             switch (size) {
   4265               case Neon8: {
   4266                 uint8_t src1[16], src2[16];
   4267                 get_q_register(Vn, src1);
   4268                 get_q_register(Vm, src2);
   4269                 for (int i = 0; i < 16; i++) {
   4270                   src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFu : 0;
   4271                 }
   4272                 set_q_register(Vd, src1);
   4273                 break;
   4274               }
   4275               case Neon16: {
   4276                 uint16_t src1[8], src2[8];
   4277                 get_q_register(Vn, src1);
   4278                 get_q_register(Vm, src2);
   4279                 for (int i = 0; i < 8; i++) {
   4280                   src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFu : 0;
   4281                 }
   4282                 set_q_register(Vd, src1);
   4283                 break;
   4284               }
   4285               case Neon32: {
   4286                 uint32_t src1[4], src2[4];
   4287                 get_q_register(Vn, src1);
   4288                 get_q_register(Vm, src2);
   4289                 for (int i = 0; i < 4; i++) {
   4290                   src1[i] = (src1[i] & src2[i]) != 0 ? 0xFFFFFFFFu : 0;
   4291                 }
   4292                 set_q_register(Vd, src1);
   4293                 break;
   4294               }
   4295               default:
   4296                 UNREACHABLE();
   4297                 break;
   4298             }
   4299           }
   4300           break;
   4301         }
   4302         case 0x9: {
   4303           if (instr->Bit(6) == 1 && instr->Bit(4) == 1) {
   4304             // vmul.i<size> Qd, Qm, Qn.
   4305             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4306             switch (size) {
   4307               case Neon8: {
   4308                 uint8_t src1[16], src2[16];
   4309                 get_q_register(Vn, src1);
   4310                 get_q_register(Vm, src2);
   4311                 for (int i = 0; i < 16; i++) {
   4312                   src1[i] *= src2[i];
   4313                 }
   4314                 set_q_register(Vd, src1);
   4315                 break;
   4316               }
   4317               case Neon16: {
   4318                 uint16_t src1[8], src2[8];
   4319                 get_q_register(Vn, src1);
   4320                 get_q_register(Vm, src2);
   4321                 for (int i = 0; i < 8; i++) {
   4322                   src1[i] *= src2[i];
   4323                 }
   4324                 set_q_register(Vd, src1);
   4325                 break;
   4326               }
   4327               case Neon32: {
   4328                 uint32_t src1[4], src2[4];
   4329                 get_q_register(Vn, src1);
   4330                 get_q_register(Vm, src2);
   4331                 for (int i = 0; i < 4; i++) {
   4332                   src1[i] *= src2[i];
   4333                 }
   4334                 set_q_register(Vd, src1);
   4335                 break;
   4336               }
   4337               default:
   4338                 UNREACHABLE();
   4339                 break;
   4340             }
   4341           } else {
   4342             UNIMPLEMENTED();
   4343           }
   4344           break;
   4345         }
   4346         case 0xd: {
   4347           if (instr->Bit(4) == 0) {
   4348             float src1[4], src2[4];
   4349             get_q_register(Vn, src1);
   4350             get_q_register(Vm, src2);
   4351             for (int i = 0; i < 4; i++) {
   4352               if (instr->Bit(21) == 0) {
   4353                 // vadd.f32 Qd, Qm, Qn.
   4354                 src1[i] = src1[i] + src2[i];
   4355               } else {
   4356                 // vsub.f32 Qd, Qm, Qn.
   4357                 src1[i] = src1[i] - src2[i];
   4358               }
   4359             }
   4360             set_q_register(Vd, src1);
   4361           } else {
   4362             UNIMPLEMENTED();
   4363           }
   4364           break;
   4365         }
   4366         case 0xe: {
   4367           if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 0) {
   4368             // vceq.f32.
   4369             float src1[4], src2[4];
   4370             get_q_register(Vn, src1);
   4371             get_q_register(Vm, src2);
   4372             uint32_t dst[4];
   4373             for (int i = 0; i < 4; i++) {
   4374               dst[i] = (src1[i] == src2[i]) ? 0xFFFFFFFF : 0;
   4375             }
   4376             set_q_register(Vd, dst);
   4377           } else {
   4378             UNIMPLEMENTED();
   4379           }
   4380           break;
   4381         }
   4382         case 0xf: {
   4383           if (instr->Bit(20) == 0 && instr->Bit(6) == 1) {
   4384             float src1[4], src2[4];
   4385             get_q_register(Vn, src1);
   4386             get_q_register(Vm, src2);
   4387             if (instr->Bit(4) == 1) {
   4388               if (instr->Bit(21) == 0) {
   4389                 // vrecps.f32 Qd, Qm, Qn.
   4390                 for (int i = 0; i < 4; i++) {
   4391                   src1[i] = 2.0f - src1[i] * src2[i];
   4392                 }
   4393               } else {
   4394                 // vrsqrts.f32 Qd, Qm, Qn.
   4395                 for (int i = 0; i < 4; i++) {
   4396                   src1[i] = (3.0f - src1[i] * src2[i]) * 0.5f;
   4397                 }
   4398               }
   4399             } else {
   4400               if (instr->Bit(21) == 1) {
   4401                 // vmin.f32 Qd, Qm, Qn.
   4402                 for (int i = 0; i < 4; i++) {
   4403                   src1[i] = std::min(src1[i], src2[i]);
   4404                 }
   4405               } else {
   4406                 // vmax.f32 Qd, Qm, Qn.
   4407                 for (int i = 0; i < 4; i++) {
   4408                   src1[i] = std::max(src1[i], src2[i]);
   4409                 }
   4410               }
   4411             }
   4412             set_q_register(Vd, src1);
   4413           } else {
   4414             UNIMPLEMENTED();
   4415           }
   4416           break;
   4417         }
   4418         default:
   4419           UNIMPLEMENTED();
   4420           break;
   4421       }
   4422       break;
   4423     }
   4424     case 5:
   4425       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
   4426           (instr->Bit(4) == 1)) {
   4427         // vmovl signed
   4428         if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
   4429         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
   4430         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
   4431         int imm3 = instr->Bits(21, 19);
   4432         if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
   4433         int esize = 8 * imm3;
   4434         int elements = 64 / esize;
   4435         int8_t from[8];
   4436         get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
   4437         int16_t to[8];
   4438         int e = 0;
   4439         while (e < elements) {
   4440           to[e] = from[e];
   4441           e++;
   4442         }
   4443         set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
   4444       } else if (instr->Bits(21, 20) == 3 && instr->Bit(4) == 0) {
   4445         // vext.
   4446         int imm4 = instr->Bits(11, 8);
   4447         int Vd = instr->VFPDRegValue(kSimd128Precision);
   4448         int Vm = instr->VFPMRegValue(kSimd128Precision);
   4449         int Vn = instr->VFPNRegValue(kSimd128Precision);
   4450         uint8_t src1[16], src2[16], dst[16];
   4451         get_q_register(Vn, src1);
   4452         get_q_register(Vm, src2);
   4453         int boundary = kSimd128Size - imm4;
   4454         int i = 0;
   4455         for (; i < boundary; i++) {
   4456           dst[i] = src1[i + imm4];
   4457         }
   4458         for (; i < 16; i++) {
   4459           dst[i] = src2[i - boundary];
   4460         }
   4461         set_q_register(Vd, dst);
   4462       } else if (instr->Bits(11, 7) == 0xA && instr->Bit(4) == 1) {
   4463         // vshl.i<size> Qd, Qm, shift
   4464         int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
   4465         int shift = instr->Bits(21, 16) - size;
   4466         int Vd = instr->VFPDRegValue(kSimd128Precision);
   4467         int Vm = instr->VFPMRegValue(kSimd128Precision);
   4468         NeonSize ns = static_cast<NeonSize>(size / 16);
   4469         switch (ns) {
   4470           case Neon8: {
   4471             uint8_t src[16];
   4472             get_q_register(Vm, src);
   4473             for (int i = 0; i < 16; i++) {
   4474               src[i] <<= shift;
   4475             }
   4476             set_q_register(Vd, src);
   4477             break;
   4478           }
   4479           case Neon16: {
   4480             uint16_t src[8];
   4481             get_q_register(Vm, src);
   4482             for (int i = 0; i < 8; i++) {
   4483               src[i] <<= shift;
   4484             }
   4485             set_q_register(Vd, src);
   4486             break;
   4487           }
   4488           case Neon32: {
   4489             uint32_t src[4];
   4490             get_q_register(Vm, src);
   4491             for (int i = 0; i < 4; i++) {
   4492               src[i] <<= shift;
   4493             }
   4494             set_q_register(Vd, src);
   4495             break;
   4496           }
   4497           default:
   4498             UNREACHABLE();
   4499             break;
   4500         }
   4501       } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
   4502         // vshr.s<size> Qd, Qm, shift
   4503         int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
   4504         int shift = 2 * size - instr->Bits(21, 16);
   4505         int Vd = instr->VFPDRegValue(kSimd128Precision);
   4506         int Vm = instr->VFPMRegValue(kSimd128Precision);
   4507         NeonSize ns = static_cast<NeonSize>(size / 16);
   4508         switch (ns) {
   4509           case Neon8: {
   4510             int8_t src[16];
   4511             get_q_register(Vm, src);
   4512             for (int i = 0; i < 16; i++) {
   4513               src[i] = ArithmeticShiftRight(src[i], shift);
   4514             }
   4515             set_q_register(Vd, src);
   4516             break;
   4517           }
   4518           case Neon16: {
   4519             int16_t src[8];
   4520             get_q_register(Vm, src);
   4521             for (int i = 0; i < 8; i++) {
   4522               src[i] = ArithmeticShiftRight(src[i], shift);
   4523             }
   4524             set_q_register(Vd, src);
   4525             break;
   4526           }
   4527           case Neon32: {
   4528             int32_t src[4];
   4529             get_q_register(Vm, src);
   4530             for (int i = 0; i < 4; i++) {
   4531               src[i] = ArithmeticShiftRight(src[i], shift);
   4532             }
   4533             set_q_register(Vd, src);
   4534             break;
   4535           }
   4536           default:
   4537             UNREACHABLE();
   4538             break;
   4539         }
   4540       } else {
   4541         UNIMPLEMENTED();
   4542       }
   4543       break;
   4544     case 6: {
   4545       int Vd, Vm, Vn;
   4546       if (instr->Bit(6) == 0) {
   4547         Vd = instr->VFPDRegValue(kDoublePrecision);
   4548         Vm = instr->VFPMRegValue(kDoublePrecision);
   4549         Vn = instr->VFPNRegValue(kDoublePrecision);
   4550       } else {
   4551         Vd = instr->VFPDRegValue(kSimd128Precision);
   4552         Vm = instr->VFPMRegValue(kSimd128Precision);
   4553         Vn = instr->VFPNRegValue(kSimd128Precision);
   4554       }
   4555       switch (instr->Bits(11, 8)) {
   4556         case 0x0: {
   4557           if (instr->Bit(4) == 1) {
   4558             // vqadd.u<size> Qd, Qm, Qn.
   4559             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4560             switch (size) {
   4561               case Neon8:
   4562                 AddSaturate<uint8_t>(this, Vd, Vm, Vn);
   4563                 break;
   4564               case Neon16:
   4565                 AddSaturate<uint16_t>(this, Vd, Vm, Vn);
   4566                 break;
   4567               case Neon32:
   4568                 AddSaturate<uint32_t>(this, Vd, Vm, Vn);
   4569                 break;
   4570               default:
   4571                 UNREACHABLE();
   4572                 break;
   4573             }
   4574           } else {
   4575             UNIMPLEMENTED();
   4576           }
   4577           break;
   4578         }
   4579         case 0x1: {
   4580           if (instr->Bits(21, 20) == 1 && instr->Bit(4) == 1) {
   4581             // vbsl.size Qd, Qm, Qn.
   4582             uint32_t dst[4], src1[4], src2[4];
   4583             get_q_register(Vd, dst);
   4584             get_q_register(Vn, src1);
   4585             get_q_register(Vm, src2);
   4586             for (int i = 0; i < 4; i++) {
   4587               dst[i] = (dst[i] & src1[i]) | (~dst[i] & src2[i]);
   4588             }
   4589             set_q_register(Vd, dst);
   4590           } else if (instr->Bits(21, 20) == 0 && instr->Bit(4) == 1) {
   4591             if (instr->Bit(6) == 0) {
   4592               // veor Dd, Dn, Dm
   4593               uint64_t src1, src2;
   4594               get_d_register(Vn, &src1);
   4595               get_d_register(Vm, &src2);
   4596               src1 ^= src2;
   4597               set_d_register(Vd, &src1);
   4598 
   4599             } else {
   4600               // veor Qd, Qn, Qm
   4601               uint32_t src1[4], src2[4];
   4602               get_q_register(Vn, src1);
   4603               get_q_register(Vm, src2);
   4604               for (int i = 0; i < 4; i++) src1[i] ^= src2[i];
   4605               set_q_register(Vd, src1);
   4606             }
   4607           } else {
   4608             UNIMPLEMENTED();
   4609           }
   4610           break;
   4611         }
   4612         case 0x2: {
   4613           if (instr->Bit(4) == 1) {
   4614             // vqsub.u<size> Qd, Qm, Qn.
   4615             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4616             switch (size) {
   4617               case Neon8:
   4618                 SubSaturate<uint8_t>(this, Vd, Vm, Vn);
   4619                 break;
   4620               case Neon16:
   4621                 SubSaturate<uint16_t>(this, Vd, Vm, Vn);
   4622                 break;
   4623               case Neon32:
   4624                 SubSaturate<uint32_t>(this, Vd, Vm, Vn);
   4625                 break;
   4626               default:
   4627                 UNREACHABLE();
   4628                 break;
   4629             }
   4630           } else {
   4631             UNIMPLEMENTED();
   4632           }
   4633           break;
   4634         }
   4635         case 0x3: {
   4636           // vcge/vcgt.u<size> Qd, Qm, Qn.
   4637           bool ge = instr->Bit(4) == 1;
   4638           NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4639           switch (size) {
   4640             case Neon8: {
   4641               uint8_t src1[16], src2[16];
   4642               get_q_register(Vn, src1);
   4643               get_q_register(Vm, src2);
   4644               for (int i = 0; i < 16; i++) {
   4645                 if (ge)
   4646                   src1[i] = src1[i] >= src2[i] ? 0xFFu : 0;
   4647                 else
   4648                   src1[i] = src1[i] > src2[i] ? 0xFFu : 0;
   4649               }
   4650               set_q_register(Vd, src1);
   4651               break;
   4652             }
   4653             case Neon16: {
   4654               uint16_t src1[8], src2[8];
   4655               get_q_register(Vn, src1);
   4656               get_q_register(Vm, src2);
   4657               for (int i = 0; i < 8; i++) {
   4658                 if (ge)
   4659                   src1[i] = src1[i] >= src2[i] ? 0xFFFFu : 0;
   4660                 else
   4661                   src1[i] = src1[i] > src2[i] ? 0xFFFFu : 0;
   4662               }
   4663               set_q_register(Vd, src1);
   4664               break;
   4665             }
   4666             case Neon32: {
   4667               uint32_t src1[4], src2[4];
   4668               get_q_register(Vn, src1);
   4669               get_q_register(Vm, src2);
   4670               for (int i = 0; i < 4; i++) {
   4671                 if (ge)
   4672                   src1[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0;
   4673                 else
   4674                   src1[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0;
   4675               }
   4676               set_q_register(Vd, src1);
   4677               break;
   4678             }
   4679             default:
   4680               UNREACHABLE();
   4681               break;
   4682           }
   4683           break;
   4684         }
   4685         case 0x6: {
   4686           // vmin/vmax.u<size> Qd, Qm, Qn.
   4687           NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4688           bool min = instr->Bit(4) != 0;
   4689           switch (size) {
   4690             case Neon8: {
   4691               uint8_t src1[16], src2[16];
   4692               get_q_register(Vn, src1);
   4693               get_q_register(Vm, src2);
   4694               for (int i = 0; i < 16; i++) {
   4695                 if (min)
   4696                   src1[i] = std::min(src1[i], src2[i]);
   4697                 else
   4698                   src1[i] = std::max(src1[i], src2[i]);
   4699               }
   4700               set_q_register(Vd, src1);
   4701               break;
   4702             }
   4703             case Neon16: {
   4704               uint16_t src1[8], src2[8];
   4705               get_q_register(Vn, src1);
   4706               get_q_register(Vm, src2);
   4707               for (int i = 0; i < 8; i++) {
   4708                 if (min)
   4709                   src1[i] = std::min(src1[i], src2[i]);
   4710                 else
   4711                   src1[i] = std::max(src1[i], src2[i]);
   4712               }
   4713               set_q_register(Vd, src1);
   4714               break;
   4715             }
   4716             case Neon32: {
   4717               uint32_t src1[4], src2[4];
   4718               get_q_register(Vn, src1);
   4719               get_q_register(Vm, src2);
   4720               for (int i = 0; i < 4; i++) {
   4721                 if (min)
   4722                   src1[i] = std::min(src1[i], src2[i]);
   4723                 else
   4724                   src1[i] = std::max(src1[i], src2[i]);
   4725               }
   4726               set_q_register(Vd, src1);
   4727               break;
   4728             }
   4729             default:
   4730               UNREACHABLE();
   4731               break;
   4732           }
   4733           break;
   4734         }
   4735         case 0x8: {
   4736           if (instr->Bit(4) == 0) {
   4737             // vsub.size Qd, Qm, Qn.
   4738             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4739             switch (size) {
   4740               case Neon8: {
   4741                 uint8_t src1[16], src2[16];
   4742                 get_q_register(Vn, src1);
   4743                 get_q_register(Vm, src2);
   4744                 for (int i = 0; i < 16; i++) {
   4745                   src1[i] -= src2[i];
   4746                 }
   4747                 set_q_register(Vd, src1);
   4748                 break;
   4749               }
   4750               case Neon16: {
   4751                 uint16_t src1[8], src2[8];
   4752                 get_q_register(Vn, src1);
   4753                 get_q_register(Vm, src2);
   4754                 for (int i = 0; i < 8; i++) {
   4755                   src1[i] -= src2[i];
   4756                 }
   4757                 set_q_register(Vd, src1);
   4758                 break;
   4759               }
   4760               case Neon32: {
   4761                 uint32_t src1[4], src2[4];
   4762                 get_q_register(Vn, src1);
   4763                 get_q_register(Vm, src2);
   4764                 for (int i = 0; i < 4; i++) {
   4765                   src1[i] -= src2[i];
   4766                 }
   4767                 set_q_register(Vd, src1);
   4768                 break;
   4769               }
   4770               default:
   4771                 UNREACHABLE();
   4772                 break;
   4773             }
   4774           } else {
   4775             // vceq.size Qd, Qm, Qn.
   4776             NeonSize size = static_cast<NeonSize>(instr->Bits(21, 20));
   4777             switch (size) {
   4778               case Neon8: {
   4779                 uint8_t src1[16], src2[16];
   4780                 get_q_register(Vn, src1);
   4781                 get_q_register(Vm, src2);
   4782                 for (int i = 0; i < 16; i++) {
   4783                   src1[i] = (src1[i] == src2[i]) ? 0xFFu : 0;
   4784                 }
   4785                 set_q_register(Vd, src1);
   4786                 break;
   4787               }
   4788               case Neon16: {
   4789                 uint16_t src1[8], src2[8];
   4790                 get_q_register(Vn, src1);
   4791                 get_q_register(Vm, src2);
   4792                 for (int i = 0; i < 8; i++) {
   4793                   src1[i] = (src1[i] == src2[i]) ? 0xFFFFu : 0;
   4794                 }
   4795                 set_q_register(Vd, src1);
   4796                 break;
   4797               }
   4798               case Neon32: {
   4799                 uint32_t src1[4], src2[4];
   4800                 get_q_register(Vn, src1);
   4801                 get_q_register(Vm, src2);
   4802                 for (int i = 0; i < 4; i++) {
   4803                   src1[i] = (src1[i] == src2[i]) ? 0xFFFFFFFFu : 0;
   4804                 }
   4805                 set_q_register(Vd, src1);
   4806                 break;
   4807               }
   4808               default:
   4809                 UNREACHABLE();
   4810                 break;
   4811             }
   4812           }
   4813           break;
   4814         }
   4815         case 0xd: {
   4816           if (instr->Bit(21) == 0 && instr->Bit(6) == 1 && instr->Bit(4) == 1) {
   4817             // vmul.f32 Qd, Qn, Qm
   4818             float src1[4], src2[4];
   4819             get_q_register(Vn, src1);
   4820             get_q_register(Vm, src2);
   4821             for (int i = 0; i < 4; i++) {
   4822               src1[i] = src1[i] * src2[i];
   4823             }
   4824             set_q_register(Vd, src1);
   4825           } else {
   4826             UNIMPLEMENTED();
   4827           }
   4828           break;
   4829         }
   4830         case 0xe: {
   4831           if (instr->Bit(20) == 0 && instr->Bit(4) == 0) {
   4832             // vcge/vcgt.f32 Qd, Qm, Qn
   4833             bool ge = instr->Bit(21) == 0;
   4834             float src1[4], src2[4];
   4835             get_q_register(Vn, src1);
   4836             get_q_register(Vm, src2);
   4837             uint32_t dst[4];
   4838             for (int i = 0; i < 4; i++) {
   4839               if (ge) {
   4840                 dst[i] = src1[i] >= src2[i] ? 0xFFFFFFFFu : 0;
   4841               } else {
   4842                 dst[i] = src1[i] > src2[i] ? 0xFFFFFFFFu : 0;
   4843               }
   4844             }
   4845             set_q_register(Vd, dst);
   4846           } else {
   4847             UNIMPLEMENTED();
   4848           }
   4849           break;
   4850         }
   4851         default:
   4852           UNREACHABLE();
   4853           break;
   4854       }
   4855       break;
   4856     }
   4857     case 7:
   4858       if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
   4859           (instr->Bit(4) == 1)) {
   4860         // vmovl unsigned
   4861         if ((instr->VdValue() & 1) != 0) UNIMPLEMENTED();
   4862         int Vd = (instr->Bit(22) << 3) | (instr->VdValue() >> 1);
   4863         int Vm = (instr->Bit(5) << 4) | instr->VmValue();
   4864         int imm3 = instr->Bits(21, 19);
   4865         if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
   4866         int esize = 8 * imm3;
   4867         int elements = 64 / esize;
   4868         uint8_t from[8];
   4869         get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
   4870         uint16_t to[8];
   4871         int e = 0;
   4872         while (e < elements) {
   4873           to[e] = from[e];
   4874           e++;
   4875         }
   4876         set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
   4877       } else if (instr->Opc1Value() == 7 && instr->Bit(4) == 0) {
   4878         if (instr->Bits(19, 16) == 0xB && instr->Bits(11, 9) == 0x3 &&
   4879             instr->Bit(6) == 1) {
   4880           // vcvt.<Td>.<Tm> Qd, Qm.
   4881           int Vd = instr->VFPDRegValue(kSimd128Precision);
   4882           int Vm = instr->VFPMRegValue(kSimd128Precision);
   4883           uint32_t q_data[4];
   4884           get_q_register(Vm, q_data);
   4885           int op = instr->Bits(8, 7);
   4886           for (int i = 0; i < 4; i++) {
   4887             switch (op) {
   4888               case 0:
   4889                 // f32 <- s32, round towards nearest.
   4890                 q_data[i] = bit_cast<uint32_t>(std::round(
   4891                     static_cast<float>(bit_cast<int32_t>(q_data[i]))));
   4892                 break;
   4893               case 1:
   4894                 // f32 <- u32, round towards nearest.
   4895                 q_data[i] = bit_cast<uint32_t>(
   4896                     std::round(static_cast<float>(q_data[i])));
   4897                 break;
   4898               case 2:
   4899                 // s32 <- f32, round to zero.
   4900                 q_data[i] = static_cast<uint32_t>(
   4901                     ConvertDoubleToInt(bit_cast<float>(q_data[i]), false, RZ));
   4902                 break;
   4903               case 3:
   4904                 // u32 <- f32, round to zero.
   4905                 q_data[i] = static_cast<uint32_t>(
   4906                     ConvertDoubleToInt(bit_cast<float>(q_data[i]), true, RZ));
   4907                 break;
   4908             }
   4909           }
   4910           set_q_register(Vd, q_data);
   4911         } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 7) == 0) {
   4912           if (instr->Bit(6) == 0) {
   4913             // vswp Dd, Dm.
   4914             uint64_t dval, mval;
   4915             int vd = instr->VFPDRegValue(kDoublePrecision);
   4916             int vm = instr->VFPMRegValue(kDoublePrecision);
   4917             get_d_register(vd, &dval);
   4918             get_d_register(vm, &mval);
   4919             set_d_register(vm, &dval);
   4920             set_d_register(vd, &mval);
   4921           } else {
   4922             // vswp Qd, Qm.
   4923             uint32_t dval[4], mval[4];
   4924             int vd = instr->VFPDRegValue(kSimd128Precision);
   4925             int vm = instr->VFPMRegValue(kSimd128Precision);
   4926             get_q_register(vd, dval);
   4927             get_q_register(vm, mval);
   4928             set_q_register(vm, dval);
   4929             set_q_register(vd, mval);
   4930           }
   4931         } else if (instr->Bits(11, 7) == 0x18) {
   4932           // vdup.32 Qd, Sm.
   4933           int vd = instr->VFPDRegValue(kSimd128Precision);
   4934           int vm = instr->VFPMRegValue(kDoublePrecision);
   4935           int index = instr->Bit(19);
   4936           uint32_t s_data = get_s_register(vm * 2 + index);
   4937           uint32_t q_data[4];
   4938           for (int i = 0; i < 4; i++) q_data[i] = s_data;
   4939           set_q_register(vd, q_data);
   4940         } else if (instr->Bits(19, 16) == 0 && instr->Bits(11, 6) == 0x17) {
   4941           // vmvn Qd, Qm.
   4942           int vd = instr->VFPDRegValue(kSimd128Precision);
   4943           int vm = instr->VFPMRegValue(kSimd128Precision);
   4944           uint32_t q_data[4];
   4945           get_q_register(vm, q_data);
   4946           for (int i = 0; i < 4; i++) q_data[i] = ~q_data[i];
   4947           set_q_register(vd, q_data);
   4948         } else if (instr->Bits(11, 10) == 0x2) {
   4949           // vtb[l,x] Dd, <list>, Dm.
   4950           int vd = instr->VFPDRegValue(kDoublePrecision);
   4951           int vn = instr->VFPNRegValue(kDoublePrecision);
   4952           int vm = instr->VFPMRegValue(kDoublePrecision);
   4953           int table_len = (instr->Bits(9, 8) + 1) * kDoubleSize;
   4954           bool vtbx = instr->Bit(6) != 0;  // vtbl / vtbx
   4955           uint64_t destination = 0, indices = 0, result = 0;
   4956           get_d_register(vd, &destination);
   4957           get_d_register(vm, &indices);
   4958           for (int i = 0; i < kDoubleSize; i++) {
   4959             int shift = i * kBitsPerByte;
   4960             int index = (indices >> shift) & 0xFF;
   4961             if (index < table_len) {
   4962               uint64_t table;
   4963               get_d_register(vn + index / kDoubleSize, &table);
   4964               result |=
   4965                   ((table >> ((index % kDoubleSize) * kBitsPerByte)) & 0xFF)
   4966                   << shift;
   4967             } else if (vtbx) {
   4968               result |= destination & (0xFFull << shift);
   4969             }
   4970           }
   4971           set_d_register(vd, &result);
   4972         } else if (instr->Bits(17, 16) == 0x2 && instr->Bits(11, 6) == 0x7) {
   4973           // vzip.<size> Qd, Qm.
   4974           NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
   4975           int Vd = instr->VFPDRegValue(kSimd128Precision);
   4976           int Vm = instr->VFPMRegValue(kSimd128Precision);
   4977           switch (size) {
   4978             case Neon8: {
   4979               uint8_t src1[16], src2[16], dst1[16], dst2[16];
   4980               get_q_register(Vd, src1);
   4981               get_q_register(Vm, src2);
   4982               for (int i = 0; i < 8; i++) {
   4983                 dst1[i * 2] = src1[i];
   4984                 dst1[i * 2 + 1] = src2[i];
   4985                 dst2[i * 2] = src1[i + 8];
   4986                 dst2[i * 2 + 1] = src2[i + 8];
   4987               }
   4988               set_q_register(Vd, dst1);
   4989               set_q_register(Vm, dst2);
   4990               break;
   4991             }
   4992             case Neon16: {
   4993               uint16_t src1[8], src2[8], dst1[8], dst2[8];
   4994               get_q_register(Vd, src1);
   4995               get_q_register(Vm, src2);
   4996               for (int i = 0; i < 8; i += 2) {
   4997                 dst1[i] = src1[i / 2];
   4998                 dst1[i + 1] = src2[i / 2];
   4999                 dst2[i] = src1[i / 2 + 4];
   5000                 dst2[i + 1] = src2[i / 2 + 4];
   5001               }
   5002               set_q_register(Vd, dst1);
   5003               set_q_register(Vm, dst2);
   5004               break;
   5005             }
   5006             case Neon32: {
   5007               uint32_t src1[4], src2[4], dst1[4], dst2[4];
   5008               get_q_register(Vd, src1);
   5009               get_q_register(Vm, src2);
   5010               for (int i = 0; i < 2; i++) {
   5011                 dst1[i * 2] = src1[i];
   5012                 dst1[i * 2 + 1] = src2[i];
   5013                 dst2[i * 2] = src1[i + 2];
   5014                 dst2[i * 2 + 1] = src2[i + 2];
   5015               }
   5016               set_q_register(Vd, dst1);
   5017               set_q_register(Vm, dst2);
   5018               break;
   5019             }
   5020             default:
   5021               UNREACHABLE();
   5022               break;
   5023           }
   5024         } else if (instr->Bits(17, 16) == 0 && instr->Bits(11, 9) == 0) {
   5025           // vrev<op>.size Qd, Qm
   5026           int Vd = instr->VFPDRegValue(kSimd128Precision);
   5027           int Vm = instr->VFPMRegValue(kSimd128Precision);
   5028           NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
   5029           NeonSize op = static_cast<NeonSize>(static_cast<int>(Neon64) -
   5030                                               instr->Bits(8, 7));
   5031           switch (op) {
   5032             case Neon16: {
   5033               DCHECK_EQ(Neon8, size);
   5034               uint8_t src[16];
   5035               get_q_register(Vm, src);
   5036               for (int i = 0; i < 16; i += 2) {
   5037                 std::swap(src[i], src[i + 1]);
   5038               }
   5039               set_q_register(Vd, src);
   5040               break;
   5041             }
   5042             case Neon32: {
   5043               switch (size) {
   5044                 case Neon16: {
   5045                   uint16_t src[8];
   5046                   get_q_register(Vm, src);
   5047                   for (int i = 0; i < 8; i += 2) {
   5048                     std::swap(src[i], src[i + 1]);
   5049                   }
   5050                   set_q_register(Vd, src);
   5051                   break;
   5052                 }
   5053                 case Neon8: {
   5054                   uint8_t src[16];
   5055                   get_q_register(Vm, src);
   5056                   for (int i = 0; i < 4; i++) {
   5057                     std::swap(src[i * 4], src[i * 4 + 3]);
   5058                     std::swap(src[i * 4 + 1], src[i * 4 + 2]);
   5059                   }
   5060                   set_q_register(Vd, src);
   5061                   break;
   5062                 }
   5063                 default:
   5064                   UNREACHABLE();
   5065                   break;
   5066               }
   5067               break;
   5068             }
   5069             case Neon64: {
   5070               switch (size) {
   5071                 case Neon32: {
   5072                   uint32_t src[4];
   5073                   get_q_register(Vm, src);
   5074                   std::swap(src[0], src[1]);
   5075                   std::swap(src[2], src[3]);
   5076                   set_q_register(Vd, src);
   5077                   break;
   5078                 }
   5079                 case Neon16: {
   5080                   uint16_t src[8];
   5081                   get_q_register(Vm, src);
   5082                   for (int i = 0; i < 4; i++) {
   5083                     std::swap(src[i * 4], src[i * 4 + 3]);
   5084                     std::swap(src[i * 4 + 1], src[i * 4 + 2]);
   5085                   }
   5086                   set_q_register(Vd, src);
   5087                   break;
   5088                 }
   5089                 case Neon8: {
   5090                   uint8_t src[16];
   5091                   get_q_register(Vm, src);
   5092                   for (int i = 0; i < 4; i++) {
   5093                     std::swap(src[i], src[7 - i]);
   5094                     std::swap(src[i + 8], src[15 - i]);
   5095                   }
   5096                   set_q_register(Vd, src);
   5097                   break;
   5098                 }
   5099                 default:
   5100                   UNREACHABLE();
   5101                   break;
   5102               }
   5103               break;
   5104             }
   5105             default:
   5106               UNREACHABLE();
   5107               break;
   5108           }
   5109         } else if (instr->Bits(17, 16) == 0x1 && instr->Bit(11) == 0) {
   5110           int Vd = instr->VFPDRegValue(kSimd128Precision);
   5111           int Vm = instr->VFPMRegValue(kSimd128Precision);
   5112           NeonSize size = static_cast<NeonSize>(instr->Bits(19, 18));
   5113           if (instr->Bits(9, 6) == 0xd) {
   5114             // vabs<type>.<size> Qd, Qm
   5115             if (instr->Bit(10) != 0) {
   5116               // floating point (clear sign bits)
   5117               uint32_t src[4];
   5118               get_q_register(Vm, src);
   5119               for (int i = 0; i < 4; i++) {
   5120                 src[i] &= ~0x80000000;
   5121               }
   5122               set_q_register(Vd, src);
   5123             } else {
   5124               // signed integer
   5125               switch (size) {
   5126                 case Neon8: {
   5127                   int8_t src[16];
   5128                   get_q_register(Vm, src);
   5129                   for (int i = 0; i < 16; i++) {
   5130                     src[i] = std::abs(src[i]);
   5131                   }
   5132                   set_q_register(Vd, src);
   5133                   break;
   5134                 }
   5135                 case Neon16: {
   5136                   int16_t src[8];
   5137                   get_q_register(Vm, src);
   5138                   for (int i = 0; i < 8; i++) {
   5139                     src[i] = std::abs(src[i]);
   5140                   }
   5141                   set_q_register(Vd, src);
   5142                   break;
   5143                 }
   5144                 case Neon32: {
   5145                   int32_t src[4];
   5146                   get_q_register(Vm, src);
   5147                   for (int i = 0; i < 4; i++) {
   5148                     src[i] = std::abs(src[i]);
   5149                   }
   5150                   set_q_register(Vd, src);
   5151                   break;
   5152                 }
   5153                 default:
   5154                   UNIMPLEMENTED();
   5155                   break;
   5156               }
   5157             }
   5158           } else if (instr->Bits(9, 6) == 0xf) {
   5159             // vneg<type>.<size> Qd, Qm (signed integer)
   5160             if (instr->Bit(10) != 0) {
   5161               // floating point (toggle sign bits)
   5162               uint32_t src[4];
   5163               get_q_register(Vm, src);
   5164               for (int i = 0; i < 4; i++) {
   5165                 src[i] ^= 0x80000000;
   5166               }
   5167               set_q_register(Vd, src);
   5168             } else {
   5169               // signed integer
   5170               switch (size) {
   5171                 case Neon8: {
   5172                   int8_t src[16];
   5173                   get_q_register(Vm, src);
   5174                   for (int i = 0; i < 16; i++) {
   5175                     src[i] = -src[i];
   5176                   }
   5177                   set_q_register(Vd, src);
   5178                   break;
   5179                 }
   5180                 case Neon16:
   5181                   int16_t src[8];
   5182                   get_q_register(Vm, src);
   5183                   for (int i = 0; i < 8; i++) {
   5184                     src[i] = -src[i];
   5185                   }
   5186                   set_q_register(Vd, src);
   5187                   break;
   5188                 case Neon32: {
   5189                   int32_t src[4];
   5190                   get_q_register(Vm, src);
   5191                   for (int i = 0; i < 4; i++) {
   5192                     src[i] = -src[i];
   5193                   }
   5194                   set_q_register(Vd, src);
   5195                   break;
   5196                 }
   5197                 default:
   5198                   UNIMPLEMENTED();
   5199                   break;
   5200               }
   5201             }
   5202           } else {
   5203             UNIMPLEMENTED();
   5204           }
   5205         } else if (instr->Bits(19, 18) == 0x2 && instr->Bits(11, 8) == 0x5) {
   5206           // vrecpe/vrsqrte.f32 Qd, Qm.
   5207           int Vd = instr->VFPDRegValue(kSimd128Precision);
   5208           int Vm = instr->VFPMRegValue(kSimd128Precision);
   5209           uint32_t src[4];
   5210           get_q_register(Vm, src);
   5211           if (instr->Bit(7) == 0) {
   5212             for (int i = 0; i < 4; i++) {
   5213               float denom = bit_cast<float>(src[i]);
   5214               div_zero_vfp_flag_ = (denom == 0);
   5215               float result = 1.0f / denom;
   5216               result = canonicalizeNaN(result);
   5217               src[i] = bit_cast<uint32_t>(result);
   5218             }
   5219           } else {
   5220             lazily_initialize_fast_sqrt(isolate_);
   5221             for (int i = 0; i < 4; i++) {
   5222               float radicand = bit_cast<float>(src[i]);
   5223               float result = 1.0f / fast_sqrt(radicand, isolate_);
   5224               result = canonicalizeNaN(result);
   5225               src[i] = bit_cast<uint32_t>(result);
   5226             }
   5227           }
   5228           set_q_register(Vd, src);
   5229         } else {
   5230           UNIMPLEMENTED();
   5231         }
   5232       } else if (instr->Bits(11, 7) == 0 && instr->Bit(4) == 1) {
   5233         // vshr.u<size> Qd, Qm, shift
   5234         int size = base::bits::RoundDownToPowerOfTwo32(instr->Bits(21, 16));
   5235         int shift = 2 * size - instr->Bits(21, 16);
   5236         int Vd = instr->VFPDRegValue(kSimd128Precision);
   5237         int Vm = instr->VFPMRegValue(kSimd128Precision);
   5238         NeonSize ns = static_cast<NeonSize>(size / 16);
   5239         switch (ns) {
   5240           case Neon8: {
   5241             uint8_t src[16];
   5242             get_q_register(Vm, src);
   5243             for (int i = 0; i < 16; i++) {
   5244               src[i] >>= shift;
   5245             }
   5246             set_q_register(Vd, src);
   5247             break;
   5248           }
   5249           case Neon16: {
   5250             uint16_t src[8];
   5251             get_q_register(Vm, src);
   5252             for (int i = 0; i < 8; i++) {
   5253               src[i] >>= shift;
   5254             }
   5255             set_q_register(Vd, src);
   5256             break;
   5257           }
   5258           case Neon32: {
   5259             uint32_t src[4];
   5260             get_q_register(Vm, src);
   5261             for (int i = 0; i < 4; i++) {
   5262               src[i] >>= shift;
   5263             }
   5264             set_q_register(Vd, src);
   5265             break;
   5266           }
   5267           default:
   5268             UNREACHABLE();
   5269             break;
   5270         }
   5271       } else {
   5272         UNIMPLEMENTED();
   5273       }
   5274       break;
   5275     case 8:
   5276       if (instr->Bits(21, 20) == 0) {
   5277         // vst1
   5278         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
   5279         int Rn = instr->VnValue();
   5280         int type = instr->Bits(11, 8);
   5281         int Rm = instr->VmValue();
   5282         int32_t address = get_register(Rn);
   5283         int regs = 0;
   5284         switch (type) {
   5285           case nlt_1:
   5286             regs = 1;
   5287             break;
   5288           case nlt_2:
   5289             regs = 2;
   5290             break;
   5291           case nlt_3:
   5292             regs = 3;
   5293             break;
   5294           case nlt_4:
   5295             regs = 4;
   5296             break;
   5297           default:
   5298             UNIMPLEMENTED();
   5299             break;
   5300         }
   5301         int r = 0;
   5302         while (r < regs) {
   5303           uint32_t data[2];
   5304           get_d_register(Vd + r, data);
   5305           WriteW(address, data[0], instr);
   5306           WriteW(address + 4, data[1], instr);
   5307           address += 8;
   5308           r++;
   5309         }
   5310         if (Rm != 15) {
   5311           if (Rm == 13) {
   5312             set_register(Rn, address);
   5313           } else {
   5314             set_register(Rn, get_register(Rn) + get_register(Rm));
   5315           }
   5316         }
   5317       } else if (instr->Bits(21, 20) == 2) {
   5318         // vld1
   5319         int Vd = (instr->Bit(22) << 4) | instr->VdValue();
   5320         int Rn = instr->VnValue();
   5321         int type = instr->Bits(11, 8);
   5322         int Rm = instr->VmValue();
   5323         int32_t address = get_register(Rn);
   5324         int regs = 0;
   5325         switch (type) {
   5326           case nlt_1:
   5327             regs = 1;
   5328             break;
   5329           case nlt_2:
   5330             regs = 2;
   5331             break;
   5332           case nlt_3:
   5333             regs = 3;
   5334             break;
   5335           case nlt_4:
   5336             regs = 4;
   5337             break;
   5338           default:
   5339             UNIMPLEMENTED();
   5340             break;
   5341         }
   5342         int r = 0;
   5343         while (r < regs) {
   5344           uint32_t data[2];
   5345           data[0] = ReadW(address, instr);
   5346           data[1] = ReadW(address + 4, instr);
   5347           set_d_register(Vd + r, data);
   5348           address += 8;
   5349           r++;
   5350         }
   5351         if (Rm != 15) {
   5352           if (Rm == 13) {
   5353             set_register(Rn, address);
   5354           } else {
   5355             set_register(Rn, get_register(Rn) + get_register(Rm));
   5356           }
   5357         }
   5358       } else {
   5359         UNIMPLEMENTED();
   5360       }
   5361       break;
   5362     case 0xA:
   5363     case 0xB:
   5364       if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
   5365         // pld: ignore instruction.
   5366       } else if (instr->SpecialValue() == 0xA && instr->Bits(22, 20) == 7) {
   5367         // dsb, dmb, isb: ignore instruction for now.
   5368         // TODO(binji): implement
   5369         // Also refer to the ARMv6 CP15 equivalents in DecodeTypeCP15.
   5370       } else {
   5371         UNIMPLEMENTED();
   5372       }
   5373       break;
   5374     case 0x1D:
   5375       if (instr->Opc1Value() == 0x7 && instr->Opc3Value() == 0x1 &&
   5376           instr->Bits(11, 9) == 0x5 && instr->Bits(19, 18) == 0x2) {
   5377         if (instr->SzValue() == 0x1) {
   5378           int vm = instr->VFPMRegValue(kDoublePrecision);
   5379           int vd = instr->VFPDRegValue(kDoublePrecision);
   5380           double dm_value = get_double_from_d_register(vm);
   5381           double dd_value = 0.0;
   5382           int rounding_mode = instr->Bits(17, 16);
   5383           switch (rounding_mode) {
   5384             case 0x0:  // vrinta - round with ties to away from zero
   5385               dd_value = round(dm_value);
   5386               break;
   5387             case 0x1: {  // vrintn - round with ties to even
   5388               dd_value = nearbyint(dm_value);
   5389               break;
   5390             }
   5391             case 0x2:  // vrintp - ceil
   5392               dd_value = ceil(dm_value);
   5393               break;
   5394             case 0x3:  // vrintm - floor
   5395               dd_value = floor(dm_value);
   5396               break;
   5397             default:
   5398               UNREACHABLE();  // Case analysis is exhaustive.
   5399               break;
   5400           }
   5401           dd_value = canonicalizeNaN(dd_value);
   5402           set_d_register_from_double(vd, dd_value);
   5403         } else {
   5404           int m = instr->VFPMRegValue(kSinglePrecision);
   5405           int d = instr->VFPDRegValue(kSinglePrecision);
   5406           float sm_value = get_float_from_s_register(m);
   5407           float sd_value = 0.0;
   5408           int rounding_mode = instr->Bits(17, 16);
   5409           switch (rounding_mode) {
   5410             case 0x0:  // vrinta - round with ties to away from zero
   5411               sd_value = roundf(sm_value);
   5412               break;
   5413             case 0x1: {  // vrintn - round with ties to even
   5414               sd_value = nearbyintf(sm_value);
   5415               break;
   5416             }
   5417             case 0x2:  // vrintp - ceil
   5418               sd_value = ceilf(sm_value);
   5419               break;
   5420             case 0x3:  // vrintm - floor
   5421               sd_value = floorf(sm_value);
   5422               break;
   5423             default:
   5424               UNREACHABLE();  // Case analysis is exhaustive.
   5425               break;
   5426           }
   5427           sd_value = canonicalizeNaN(sd_value);
   5428           set_s_register_from_float(d, sd_value);
   5429         }
   5430       } else if ((instr->Opc1Value() == 0x4) && (instr->Bits(11, 9) == 0x5) &&
   5431                  (instr->Bit(4) == 0x0)) {
   5432         if (instr->SzValue() == 0x1) {
   5433           int m = instr->VFPMRegValue(kDoublePrecision);
   5434           int n = instr->VFPNRegValue(kDoublePrecision);
   5435           int d = instr->VFPDRegValue(kDoublePrecision);
   5436           double dn_value = get_double_from_d_register(n);
   5437           double dm_value = get_double_from_d_register(m);
   5438           double dd_value;
   5439           if (instr->Bit(6) == 0x1) {  // vminnm
   5440             if ((dn_value < dm_value) || std::isnan(dm_value)) {
   5441               dd_value = dn_value;
   5442             } else if ((dm_value < dn_value) || std::isnan(dn_value)) {
   5443               dd_value = dm_value;
   5444             } else {
   5445               DCHECK_EQ(dn_value, dm_value);
   5446               // Make sure that we pick the most negative sign for +/-0.
   5447               dd_value = std::signbit(dn_value) ? dn_value : dm_value;
   5448             }
   5449           } else {  // vmaxnm
   5450             if ((dn_value > dm_value) || std::isnan(dm_value)) {
   5451               dd_value = dn_value;
   5452             } else if ((dm_value > dn_value) || std::isnan(dn_value)) {
   5453               dd_value = dm_value;
   5454             } else {
   5455               DCHECK_EQ(dn_value, dm_value);
   5456               // Make sure that we pick the most positive sign for +/-0.
   5457               dd_value = std::signbit(dn_value) ? dm_value : dn_value;
   5458             }
   5459           }
   5460           dd_value = canonicalizeNaN(dd_value);
   5461           set_d_register_from_double(d, dd_value);
   5462         } else {
   5463           int m = instr->VFPMRegValue(kSinglePrecision);
   5464           int n = instr->VFPNRegValue(kSinglePrecision);
   5465           int d = instr->VFPDRegValue(kSinglePrecision);
   5466           float sn_value = get_float_from_s_register(n);
   5467           float sm_value = get_float_from_s_register(m);
   5468           float sd_value;
   5469           if (instr->Bit(6) == 0x1) {  // vminnm
   5470             if ((sn_value < sm_value) || std::isnan(sm_value)) {
   5471               sd_value = sn_value;
   5472             } else if ((sm_value < sn_value) || std::isnan(sn_value)) {
   5473               sd_value = sm_value;
   5474             } else {
   5475               DCHECK_EQ(sn_value, sm_value);
   5476               // Make sure that we pick the most negative sign for +/-0.
   5477               sd_value = std::signbit(sn_value) ? sn_value : sm_value;
   5478             }
   5479           } else {  // vmaxnm
   5480             if ((sn_value > sm_value) || std::isnan(sm_value)) {
   5481               sd_value = sn_value;
   5482             } else if ((sm_value > sn_value) || std::isnan(sn_value)) {
   5483               sd_value = sm_value;
   5484             } else {
   5485               DCHECK_EQ(sn_value, sm_value);
   5486               // Make sure that we pick the most positive sign for +/-0.
   5487               sd_value = std::signbit(sn_value) ? sm_value : sn_value;
   5488             }
   5489           }
   5490           sd_value = canonicalizeNaN(sd_value);
   5491           set_s_register_from_float(d, sd_value);
   5492         }
   5493       } else {
   5494         UNIMPLEMENTED();
   5495       }
   5496       break;
   5497     case 0x1C:
   5498       if ((instr->Bits(11, 9) == 0x5) && (instr->Bit(6) == 0) &&
   5499           (instr->Bit(4) == 0)) {
   5500         // VSEL* (floating-point)
   5501         bool condition_holds;
   5502         switch (instr->Bits(21, 20)) {
   5503           case 0x0:  // VSELEQ
   5504             condition_holds = (z_flag_ == 1);
   5505             break;
   5506           case 0x1:  // VSELVS
   5507             condition_holds = (v_flag_ == 1);
   5508             break;
   5509           case 0x2:  // VSELGE
   5510             condition_holds = (n_flag_ == v_flag_);
   5511             break;
   5512           case 0x3:  // VSELGT
   5513             condition_holds = ((z_flag_ == 0) && (n_flag_ == v_flag_));
   5514             break;
   5515           default:
   5516             UNREACHABLE();  // Case analysis is exhaustive.
   5517             break;
   5518         }
   5519         if (instr->SzValue() == 0x1) {
   5520           int n = instr->VFPNRegValue(kDoublePrecision);
   5521           int m = instr->VFPMRegValue(kDoublePrecision);
   5522           int d = instr->VFPDRegValue(kDoublePrecision);
   5523           double result = get_double_from_d_register(condition_holds ? n : m);
   5524           set_d_register_from_double(d, result);
   5525         } else {
   5526           int n = instr->VFPNRegValue(kSinglePrecision);
   5527           int m = instr->VFPMRegValue(kSinglePrecision);
   5528           int d = instr->VFPDRegValue(kSinglePrecision);
   5529           float result = get_float_from_s_register(condition_holds ? n : m);
   5530           set_s_register_from_float(d, result);
   5531         }
   5532       } else {
   5533         UNIMPLEMENTED();
   5534       }
   5535       break;
   5536     default:
   5537       UNIMPLEMENTED();
   5538       break;
   5539   }
   5540 }
   5541 
   5542 
   5543 // Executes the current instruction.
   5544 void Simulator::InstructionDecode(Instruction* instr) {
   5545   if (v8::internal::FLAG_check_icache) {
   5546     CheckICache(isolate_->simulator_i_cache(), instr);
   5547   }
   5548   pc_modified_ = false;
   5549   if (::v8::internal::FLAG_trace_sim) {
   5550     disasm::NameConverter converter;
   5551     disasm::Disassembler dasm(converter);
   5552     // use a reasonably large buffer
   5553     v8::internal::EmbeddedVector<char, 256> buffer;
   5554     dasm.InstructionDecode(buffer,
   5555                            reinterpret_cast<byte*>(instr));
   5556     PrintF("  0x%08" V8PRIxPTR "  %s\n", reinterpret_cast<intptr_t>(instr),
   5557            buffer.start());
   5558   }
   5559   if (instr->ConditionField() == kSpecialCondition) {
   5560     DecodeSpecialCondition(instr);
   5561   } else if (ConditionallyExecute(instr)) {
   5562     switch (instr->TypeValue()) {
   5563       case 0:
   5564       case 1: {
   5565         DecodeType01(instr);
   5566         break;
   5567       }
   5568       case 2: {
   5569         DecodeType2(instr);
   5570         break;
   5571       }
   5572       case 3: {
   5573         DecodeType3(instr);
   5574         break;
   5575       }
   5576       case 4: {
   5577         DecodeType4(instr);
   5578         break;
   5579       }
   5580       case 5: {
   5581         DecodeType5(instr);
   5582         break;
   5583       }
   5584       case 6: {
   5585         DecodeType6(instr);
   5586         break;
   5587       }
   5588       case 7: {
   5589         DecodeType7(instr);
   5590         break;
   5591       }
   5592       default: {
   5593         UNIMPLEMENTED();
   5594         break;
   5595       }
   5596     }
   5597   // If the instruction is a non taken conditional stop, we need to skip the
   5598   // inlined message address.
   5599   } else if (instr->IsStop()) {
   5600     set_pc(get_pc() + 2 * Instruction::kInstrSize);
   5601   }
   5602   if (!pc_modified_) {
   5603     set_register(pc, reinterpret_cast<int32_t>(instr)
   5604                          + Instruction::kInstrSize);
   5605   }
   5606 }
   5607 
   5608 
   5609 void Simulator::Execute() {
   5610   // Get the PC to simulate. Cannot use the accessor here as we need the
   5611   // raw PC value and not the one used as input to arithmetic instructions.
   5612   int program_counter = get_pc();
   5613 
   5614   if (::v8::internal::FLAG_stop_sim_at == 0) {
   5615     // Fast version of the dispatch loop without checking whether the simulator
   5616     // should be stopping at a particular executed instruction.
   5617     while (program_counter != end_sim_pc) {
   5618       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   5619       icount_++;
   5620       InstructionDecode(instr);
   5621       program_counter = get_pc();
   5622     }
   5623   } else {
   5624     // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
   5625     // we reach the particular instuction count.
   5626     while (program_counter != end_sim_pc) {
   5627       Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
   5628       icount_++;
   5629       if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
   5630         ArmDebugger dbg(this);
   5631         dbg.Debug();
   5632       } else {
   5633         InstructionDecode(instr);
   5634       }
   5635       program_counter = get_pc();
   5636     }
   5637   }
   5638 }
   5639 
   5640 
   5641 void Simulator::CallInternal(byte* entry) {
   5642   // Adjust JS-based stack limit to C-based stack limit.
   5643   isolate_->stack_guard()->AdjustStackLimitForSimulator();
   5644 
   5645   // Prepare to execute the code at entry
   5646   set_register(pc, reinterpret_cast<int32_t>(entry));
   5647   // Put down marker for end of simulation. The simulator will stop simulation
   5648   // when the PC reaches this value. By saving the "end simulation" value into
   5649   // the LR the simulation stops when returning to this call point.
   5650   set_register(lr, end_sim_pc);
   5651 
   5652   // Remember the values of callee-saved registers.
   5653   // The code below assumes that r9 is not used as sb (static base) in
   5654   // simulator code and therefore is regarded as a callee-saved register.
   5655   int32_t r4_val = get_register(r4);
   5656   int32_t r5_val = get_register(r5);
   5657   int32_t r6_val = get_register(r6);
   5658   int32_t r7_val = get_register(r7);
   5659   int32_t r8_val = get_register(r8);
   5660   int32_t r9_val = get_register(r9);
   5661   int32_t r10_val = get_register(r10);
   5662   int32_t r11_val = get_register(r11);
   5663 
   5664   // Set up the callee-saved registers with a known value. To be able to check
   5665   // that they are preserved properly across JS execution.
   5666   int32_t callee_saved_value = icount_;
   5667   set_register(r4, callee_saved_value);
   5668   set_register(r5, callee_saved_value);
   5669   set_register(r6, callee_saved_value);
   5670   set_register(r7, callee_saved_value);
   5671   set_register(r8, callee_saved_value);
   5672   set_register(r9, callee_saved_value);
   5673   set_register(r10, callee_saved_value);
   5674   set_register(r11, callee_saved_value);
   5675 
   5676   // Start the simulation
   5677   Execute();
   5678 
   5679   // Check that the callee-saved registers have been preserved.
   5680   CHECK_EQ(callee_saved_value, get_register(r4));
   5681   CHECK_EQ(callee_saved_value, get_register(r5));
   5682   CHECK_EQ(callee_saved_value, get_register(r6));
   5683   CHECK_EQ(callee_saved_value, get_register(r7));
   5684   CHECK_EQ(callee_saved_value, get_register(r8));
   5685   CHECK_EQ(callee_saved_value, get_register(r9));
   5686   CHECK_EQ(callee_saved_value, get_register(r10));
   5687   CHECK_EQ(callee_saved_value, get_register(r11));
   5688 
   5689   // Restore callee-saved registers with the original value.
   5690   set_register(r4, r4_val);
   5691   set_register(r5, r5_val);
   5692   set_register(r6, r6_val);
   5693   set_register(r7, r7_val);
   5694   set_register(r8, r8_val);
   5695   set_register(r9, r9_val);
   5696   set_register(r10, r10_val);
   5697   set_register(r11, r11_val);
   5698 }
   5699 
   5700 
   5701 int32_t Simulator::Call(byte* entry, int argument_count, ...) {
   5702   va_list parameters;
   5703   va_start(parameters, argument_count);
   5704   // Set up arguments
   5705 
   5706   // First four arguments passed in registers.
   5707   DCHECK(argument_count >= 4);
   5708   set_register(r0, va_arg(parameters, int32_t));
   5709   set_register(r1, va_arg(parameters, int32_t));
   5710   set_register(r2, va_arg(parameters, int32_t));
   5711   set_register(r3, va_arg(parameters, int32_t));
   5712 
   5713   // Remaining arguments passed on stack.
   5714   int original_stack = get_register(sp);
   5715   // Compute position of stack on entry to generated code.
   5716   int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
   5717   if (base::OS::ActivationFrameAlignment() != 0) {
   5718     entry_stack &= -base::OS::ActivationFrameAlignment();
   5719   }
   5720   // Store remaining arguments on stack, from low to high memory.
   5721   intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
   5722   for (int i = 4; i < argument_count; i++) {
   5723     stack_argument[i - 4] = va_arg(parameters, int32_t);
   5724   }
   5725   va_end(parameters);
   5726   set_register(sp, entry_stack);
   5727 
   5728   CallInternal(entry);
   5729 
   5730   // Pop stack passed arguments.
   5731   CHECK_EQ(entry_stack, get_register(sp));
   5732   set_register(sp, original_stack);
   5733 
   5734   int32_t result = get_register(r0);
   5735   return result;
   5736 }
   5737 
   5738 
   5739 void Simulator::CallFP(byte* entry, double d0, double d1) {
   5740   if (use_eabi_hardfloat()) {
   5741     set_d_register_from_double(0, d0);
   5742     set_d_register_from_double(1, d1);
   5743   } else {
   5744     set_register_pair_from_double(0, &d0);
   5745     set_register_pair_from_double(2, &d1);
   5746   }
   5747   CallInternal(entry);
   5748 }
   5749 
   5750 
   5751 int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
   5752   CallFP(entry, d0, d1);
   5753   int32_t result = get_register(r0);
   5754   return result;
   5755 }
   5756 
   5757 
   5758 double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
   5759   CallFP(entry, d0, d1);
   5760   if (use_eabi_hardfloat()) {
   5761     return get_double_from_d_register(0);
   5762   } else {
   5763     return get_double_from_register_pair(0);
   5764   }
   5765 }
   5766 
   5767 
   5768 uintptr_t Simulator::PushAddress(uintptr_t address) {
   5769   int new_sp = get_register(sp) - sizeof(uintptr_t);
   5770   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
   5771   *stack_slot = address;
   5772   set_register(sp, new_sp);
   5773   return new_sp;
   5774 }
   5775 
   5776 
   5777 uintptr_t Simulator::PopAddress() {
   5778   int current_sp = get_register(sp);
   5779   uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
   5780   uintptr_t address = *stack_slot;
   5781   set_register(sp, current_sp + sizeof(uintptr_t));
   5782   return address;
   5783 }
   5784 
   5785 Simulator::LocalMonitor::LocalMonitor()
   5786     : access_state_(MonitorAccess::Open),
   5787       tagged_addr_(0),
   5788       size_(TransactionSize::None) {}
   5789 
   5790 void Simulator::LocalMonitor::Clear() {
   5791   access_state_ = MonitorAccess::Open;
   5792   tagged_addr_ = 0;
   5793   size_ = TransactionSize::None;
   5794 }
   5795 
   5796 void Simulator::LocalMonitor::NotifyLoad(int32_t addr) {
   5797   if (access_state_ == MonitorAccess::Exclusive) {
   5798     // A load could cause a cache eviction which will affect the monitor. As a
   5799     // result, it's most strict to unconditionally clear the local monitor on
   5800     // load.
   5801     Clear();
   5802   }
   5803 }
   5804 
   5805 void Simulator::LocalMonitor::NotifyLoadExcl(int32_t addr,
   5806                                              TransactionSize size) {
   5807   access_state_ = MonitorAccess::Exclusive;
   5808   tagged_addr_ = addr;
   5809   size_ = size;
   5810 }
   5811 
   5812 void Simulator::LocalMonitor::NotifyStore(int32_t addr) {
   5813   if (access_state_ == MonitorAccess::Exclusive) {
   5814     // It is implementation-defined whether a non-exclusive store to an address
   5815     // covered by the local monitor during exclusive access transitions to open
   5816     // or exclusive access. See ARM DDI 0406C.b, A3.4.1.
   5817     //
   5818     // However, a store could cause a cache eviction which will affect the
   5819     // monitor. As a result, it's most strict to unconditionally clear the
   5820     // local monitor on store.
   5821     Clear();
   5822   }
   5823 }
   5824 
   5825 bool Simulator::LocalMonitor::NotifyStoreExcl(int32_t addr,
   5826                                               TransactionSize size) {
   5827   if (access_state_ == MonitorAccess::Exclusive) {
   5828     // It is allowed for a processor to require that the address matches
   5829     // exactly (A3.4.5), so this comparison does not mask addr.
   5830     if (addr == tagged_addr_ && size_ == size) {
   5831       Clear();
   5832       return true;
   5833     } else {
   5834       // It is implementation-defined whether an exclusive store to a
   5835       // non-tagged address will update memory. Behavior is unpredictable if
   5836       // the transaction size of the exclusive store differs from that of the
   5837       // exclusive load. See ARM DDI 0406C.b, A3.4.5.
   5838       Clear();
   5839       return false;
   5840     }
   5841   } else {
   5842     DCHECK(access_state_ == MonitorAccess::Open);
   5843     return false;
   5844   }
   5845 }
   5846 
   5847 Simulator::GlobalMonitor::Processor::Processor()
   5848     : access_state_(MonitorAccess::Open),
   5849       tagged_addr_(0),
   5850       next_(nullptr),
   5851       prev_(nullptr),
   5852       failure_counter_(0) {}
   5853 
   5854 void Simulator::GlobalMonitor::Processor::Clear_Locked() {
   5855   access_state_ = MonitorAccess::Open;
   5856   tagged_addr_ = 0;
   5857 }
   5858 
   5859 void Simulator::GlobalMonitor::Processor::NotifyLoadExcl_Locked(int32_t addr) {
   5860   access_state_ = MonitorAccess::Exclusive;
   5861   tagged_addr_ = addr;
   5862 }
   5863 
   5864 void Simulator::GlobalMonitor::Processor::NotifyStore_Locked(
   5865     int32_t addr, bool is_requesting_processor) {
   5866   if (access_state_ == MonitorAccess::Exclusive) {
   5867     // It is implementation-defined whether a non-exclusive store by the
   5868     // requesting processor to an address covered by the global monitor
   5869     // during exclusive access transitions to open or exclusive access.
   5870     //
   5871     // For any other processor, the access state always transitions to open
   5872     // access.
   5873     //
   5874     // See ARM DDI 0406C.b, A3.4.2.
   5875     //
   5876     // However, similar to the local monitor, it is possible that a store
   5877     // caused a cache eviction, which can affect the montior, so
   5878     // conservatively, we always clear the monitor.
   5879     Clear_Locked();
   5880   }
   5881 }
   5882 
   5883 bool Simulator::GlobalMonitor::Processor::NotifyStoreExcl_Locked(
   5884     int32_t addr, bool is_requesting_processor) {
   5885   if (access_state_ == MonitorAccess::Exclusive) {
   5886     if (is_requesting_processor) {
   5887       // It is allowed for a processor to require that the address matches
   5888       // exactly (A3.4.5), so this comparison does not mask addr.
   5889       if (addr == tagged_addr_) {
   5890         // The access state for the requesting processor after a successful
   5891         // exclusive store is implementation-defined, but according to the ARM
   5892         // DDI, this has no effect on the subsequent operation of the global
   5893         // monitor.
   5894         Clear_Locked();
   5895         // Introduce occasional strex failures. This is to simulate the
   5896         // behavior of hardware, which can randomly fail due to background
   5897         // cache evictions.
   5898         if (failure_counter_++ >= kMaxFailureCounter) {
   5899           failure_counter_ = 0;
   5900           return false;
   5901         } else {
   5902           return true;
   5903         }
   5904       }
   5905     } else if ((addr & kExclusiveTaggedAddrMask) ==
   5906                (tagged_addr_ & kExclusiveTaggedAddrMask)) {
   5907       // Check the masked addresses when responding to a successful lock by
   5908       // another processor so the implementation is more conservative (i.e. the
   5909       // granularity of locking is as large as possible.)
   5910       Clear_Locked();
   5911       return false;
   5912     }
   5913   }
   5914   return false;
   5915 }
   5916 
   5917 Simulator::GlobalMonitor::GlobalMonitor() : head_(nullptr) {}
   5918 
   5919 void Simulator::GlobalMonitor::NotifyLoadExcl_Locked(int32_t addr,
   5920                                                      Processor* processor) {
   5921   processor->NotifyLoadExcl_Locked(addr);
   5922   PrependProcessor_Locked(processor);
   5923 }
   5924 
   5925 void Simulator::GlobalMonitor::NotifyStore_Locked(int32_t addr,
   5926                                                   Processor* processor) {
   5927   // Notify each processor of the store operation.
   5928   for (Processor* iter = head_; iter; iter = iter->next_) {
   5929     bool is_requesting_processor = iter == processor;
   5930     iter->NotifyStore_Locked(addr, is_requesting_processor);
   5931   }
   5932 }
   5933 
   5934 bool Simulator::GlobalMonitor::NotifyStoreExcl_Locked(int32_t addr,
   5935                                                       Processor* processor) {
   5936   DCHECK(IsProcessorInLinkedList_Locked(processor));
   5937   if (processor->NotifyStoreExcl_Locked(addr, true)) {
   5938     // Notify the other processors that this StoreExcl succeeded.
   5939     for (Processor* iter = head_; iter; iter = iter->next_) {
   5940       if (iter != processor) {
   5941         iter->NotifyStoreExcl_Locked(addr, false);
   5942       }
   5943     }
   5944     return true;
   5945   } else {
   5946     return false;
   5947   }
   5948 }
   5949 
   5950 bool Simulator::GlobalMonitor::IsProcessorInLinkedList_Locked(
   5951     Processor* processor) const {
   5952   return head_ == processor || processor->next_ || processor->prev_;
   5953 }
   5954 
   5955 void Simulator::GlobalMonitor::PrependProcessor_Locked(Processor* processor) {
   5956   if (IsProcessorInLinkedList_Locked(processor)) {
   5957     return;
   5958   }
   5959 
   5960   if (head_) {
   5961     head_->prev_ = processor;
   5962   }
   5963   processor->prev_ = nullptr;
   5964   processor->next_ = head_;
   5965   head_ = processor;
   5966 }
   5967 
   5968 void Simulator::GlobalMonitor::RemoveProcessor(Processor* processor) {
   5969   base::LockGuard<base::Mutex> lock_guard(&mutex);
   5970   if (!IsProcessorInLinkedList_Locked(processor)) {
   5971     return;
   5972   }
   5973 
   5974   if (processor->prev_) {
   5975     processor->prev_->next_ = processor->next_;
   5976   } else {
   5977     head_ = processor->next_;
   5978   }
   5979   if (processor->next_) {
   5980     processor->next_->prev_ = processor->prev_;
   5981   }
   5982   processor->prev_ = nullptr;
   5983   processor->next_ = nullptr;
   5984 }
   5985 
   5986 }  // namespace internal
   5987 }  // namespace v8
   5988 
   5989 #endif  // USE_SIMULATOR
   5990 
   5991 #endif  // V8_TARGET_ARCH_ARM
   5992