The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / arm / simulator-arm.cc @ f230a1cf

History | View | Annotate | Download (123 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include <stdlib.h>
29
#include <cmath>
30
#include <cstdarg>
31
#include "v8.h"
32

    
33
#if V8_TARGET_ARCH_ARM
34

    
35
#include "disasm.h"
36
#include "assembler.h"
37
#include "codegen.h"
38
#include "arm/constants-arm.h"
39
#include "arm/simulator-arm.h"
40

    
41
#if defined(USE_SIMULATOR)
42

    
43
// Only build the simulator if not compiling for real ARM hardware.
44
namespace v8 {
45
namespace internal {
46

    
47
// This macro provides a platform independent use of sscanf. The reason for
48
// SScanF not being implemented in a platform independent way through
49
// ::v8::internal::OS in the same way as SNPrintF is that the
50
// Windows C Run-Time Library does not provide vsscanf.
51
#define SScanF sscanf  // NOLINT
52

    
53
// The ArmDebugger class is used by the simulator while debugging simulated ARM
54
// code.
55
class ArmDebugger {
56
 public:
57
  explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
58
  ~ArmDebugger();
59

    
60
  void Stop(Instruction* instr);
61
  void Debug();
62

    
63
 private:
64
  static const Instr kBreakpointInstr =
65
      (al | (7*B25) | (1*B24) | kBreakpoint);
66
  static const Instr kNopInstr = (al | (13*B21));
67

    
68
  Simulator* sim_;
69

    
70
  int32_t GetRegisterValue(int regnum);
71
  double GetRegisterPairDoubleValue(int regnum);
72
  double GetVFPDoubleRegisterValue(int regnum);
73
  bool GetValue(const char* desc, int32_t* value);
74
  bool GetVFPSingleValue(const char* desc, float* value);
75
  bool GetVFPDoubleValue(const char* desc, double* value);
76

    
77
  // Set or delete a breakpoint. Returns true if successful.
78
  bool SetBreakpoint(Instruction* breakpc);
79
  bool DeleteBreakpoint(Instruction* breakpc);
80

    
81
  // Undo and redo all breakpoints. This is needed to bracket disassembly and
82
  // execution to skip past breakpoints when run from the debugger.
83
  void UndoBreakpoints();
84
  void RedoBreakpoints();
85
};
86

    
87

    
88
ArmDebugger::~ArmDebugger() {
89
}
90

    
91

    
92

    
93
#ifdef GENERATED_CODE_COVERAGE
94
static FILE* coverage_log = NULL;
95

    
96

    
97
static void InitializeCoverage() {
98
  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
99
  if (file_name != NULL) {
100
    coverage_log = fopen(file_name, "aw+");
101
  }
102
}
103

    
104

    
105
void ArmDebugger::Stop(Instruction* instr) {
106
  // Get the stop code.
107
  uint32_t code = instr->SvcValue() & kStopCodeMask;
108
  // Retrieve the encoded address, which comes just after this stop.
109
  char** msg_address =
110
    reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
111
  char* msg = *msg_address;
112
  ASSERT(msg != NULL);
113

    
114
  // Update this stop description.
115
  if (isWatchedStop(code) && !watched_stops_[code].desc) {
116
    watched_stops_[code].desc = msg;
117
  }
118

    
119
  if (strlen(msg) > 0) {
120
    if (coverage_log != NULL) {
121
      fprintf(coverage_log, "%s\n", msg);
122
      fflush(coverage_log);
123
    }
124
    // Overwrite the instruction and address with nops.
125
    instr->SetInstructionBits(kNopInstr);
126
    reinterpret_cast<Instruction*>(msg_address)->SetInstructionBits(kNopInstr);
127
  }
128
  sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
129
}
130

    
131
#else  // ndef GENERATED_CODE_COVERAGE
132

    
133
static void InitializeCoverage() {
134
}
135

    
136

    
137
void ArmDebugger::Stop(Instruction* instr) {
138
  // Get the stop code.
139
  uint32_t code = instr->SvcValue() & kStopCodeMask;
140
  // Retrieve the encoded address, which comes just after this stop.
141
  char* msg = *reinterpret_cast<char**>(sim_->get_pc()
142
                                        + Instruction::kInstrSize);
143
  // Update this stop description.
144
  if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
145
    sim_->watched_stops_[code].desc = msg;
146
  }
147
  // Print the stop message and code if it is not the default code.
148
  if (code != kMaxStopCode) {
149
    PrintF("Simulator hit stop %u: %s\n", code, msg);
150
  } else {
151
    PrintF("Simulator hit %s\n", msg);
152
  }
153
  sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
154
  Debug();
155
}
156
#endif
157

    
158

    
159
int32_t ArmDebugger::GetRegisterValue(int regnum) {
160
  if (regnum == kPCRegister) {
161
    return sim_->get_pc();
162
  } else {
163
    return sim_->get_register(regnum);
164
  }
165
}
166

    
167

    
168
double ArmDebugger::GetRegisterPairDoubleValue(int regnum) {
169
  return sim_->get_double_from_register_pair(regnum);
170
}
171

    
172

    
173
double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
174
  return sim_->get_double_from_d_register(regnum);
175
}
176

    
177

    
178
bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
179
  int regnum = Registers::Number(desc);
180
  if (regnum != kNoRegister) {
181
    *value = GetRegisterValue(regnum);
182
    return true;
183
  } else {
184
    if (strncmp(desc, "0x", 2) == 0) {
185
      return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
186
    } else {
187
      return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
188
    }
189
  }
190
  return false;
191
}
192

    
193

    
194
bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
195
  bool is_double;
196
  int regnum = VFPRegisters::Number(desc, &is_double);
197
  if (regnum != kNoRegister && !is_double) {
198
    *value = sim_->get_float_from_s_register(regnum);
199
    return true;
200
  }
201
  return false;
202
}
203

    
204

    
205
bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
206
  bool is_double;
207
  int regnum = VFPRegisters::Number(desc, &is_double);
208
  if (regnum != kNoRegister && is_double) {
209
    *value = sim_->get_double_from_d_register(regnum);
210
    return true;
211
  }
212
  return false;
213
}
214

    
215

    
216
bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
217
  // Check if a breakpoint can be set. If not return without any side-effects.
218
  if (sim_->break_pc_ != NULL) {
219
    return false;
220
  }
221

    
222
  // Set the breakpoint.
223
  sim_->break_pc_ = breakpc;
224
  sim_->break_instr_ = breakpc->InstructionBits();
225
  // Not setting the breakpoint instruction in the code itself. It will be set
226
  // when the debugger shell continues.
227
  return true;
228
}
229

    
230

    
231
bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
232
  if (sim_->break_pc_ != NULL) {
233
    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
234
  }
235

    
236
  sim_->break_pc_ = NULL;
237
  sim_->break_instr_ = 0;
238
  return true;
239
}
240

    
241

    
242
void ArmDebugger::UndoBreakpoints() {
243
  if (sim_->break_pc_ != NULL) {
244
    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
245
  }
246
}
247

    
248

    
249
void ArmDebugger::RedoBreakpoints() {
250
  if (sim_->break_pc_ != NULL) {
251
    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
252
  }
253
}
254

    
255

    
256
void ArmDebugger::Debug() {
257
  intptr_t last_pc = -1;
258
  bool done = false;
259

    
260
#define COMMAND_SIZE 63
261
#define ARG_SIZE 255
262

    
263
#define STR(a) #a
264
#define XSTR(a) STR(a)
265

    
266
  char cmd[COMMAND_SIZE + 1];
267
  char arg1[ARG_SIZE + 1];
268
  char arg2[ARG_SIZE + 1];
269
  char* argv[3] = { cmd, arg1, arg2 };
270

    
271
  // make sure to have a proper terminating character if reaching the limit
272
  cmd[COMMAND_SIZE] = 0;
273
  arg1[ARG_SIZE] = 0;
274
  arg2[ARG_SIZE] = 0;
275

    
276
  // Undo all set breakpoints while running in the debugger shell. This will
277
  // make them invisible to all commands.
278
  UndoBreakpoints();
279

    
280
  while (!done && !sim_->has_bad_pc()) {
281
    if (last_pc != sim_->get_pc()) {
282
      disasm::NameConverter converter;
283
      disasm::Disassembler dasm(converter);
284
      // use a reasonably large buffer
285
      v8::internal::EmbeddedVector<char, 256> buffer;
286
      dasm.InstructionDecode(buffer,
287
                             reinterpret_cast<byte*>(sim_->get_pc()));
288
      PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
289
      last_pc = sim_->get_pc();
290
    }
291
    char* line = ReadLine("sim> ");
292
    if (line == NULL) {
293
      break;
294
    } else {
295
      char* last_input = sim_->last_debugger_input();
296
      if (strcmp(line, "\n") == 0 && last_input != NULL) {
297
        line = last_input;
298
      } else {
299
        // Ownership is transferred to sim_;
300
        sim_->set_last_debugger_input(line);
301
      }
302
      // Use sscanf to parse the individual parts of the command line. At the
303
      // moment no command expects more than two parameters.
304
      int argc = SScanF(line,
305
                        "%" XSTR(COMMAND_SIZE) "s "
306
                        "%" XSTR(ARG_SIZE) "s "
307
                        "%" XSTR(ARG_SIZE) "s",
308
                        cmd, arg1, arg2);
309
      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
310
        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
311
      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
312
        // Execute the one instruction we broke at with breakpoints disabled.
313
        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
314
        // Leave the debugger shell.
315
        done = true;
316
      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
317
        if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
318
          int32_t value;
319
          float svalue;
320
          double dvalue;
321
          if (strcmp(arg1, "all") == 0) {
322
            for (int i = 0; i < kNumRegisters; i++) {
323
              value = GetRegisterValue(i);
324
              PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
325
              if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
326
                  i < 8 &&
327
                  (i % 2) == 0) {
328
                dvalue = GetRegisterPairDoubleValue(i);
329
                PrintF(" (%f)\n", dvalue);
330
              } else {
331
                PrintF("\n");
332
              }
333
            }
334
            for (int i = 0; i < DwVfpRegister::NumRegisters(); i++) {
335
              dvalue = GetVFPDoubleRegisterValue(i);
336
              uint64_t as_words = BitCast<uint64_t>(dvalue);
337
              PrintF("%3s: %f 0x%08x %08x\n",
338
                     VFPRegisters::Name(i, true),
339
                     dvalue,
340
                     static_cast<uint32_t>(as_words >> 32),
341
                     static_cast<uint32_t>(as_words & 0xffffffff));
342
            }
343
          } else {
344
            if (GetValue(arg1, &value)) {
345
              PrintF("%s: 0x%08x %d \n", arg1, value, value);
346
            } else if (GetVFPSingleValue(arg1, &svalue)) {
347
              uint32_t as_word = BitCast<uint32_t>(svalue);
348
              PrintF("%s: %f 0x%08x\n", arg1, svalue, as_word);
349
            } else if (GetVFPDoubleValue(arg1, &dvalue)) {
350
              uint64_t as_words = BitCast<uint64_t>(dvalue);
351
              PrintF("%s: %f 0x%08x %08x\n",
352
                     arg1,
353
                     dvalue,
354
                     static_cast<uint32_t>(as_words >> 32),
355
                     static_cast<uint32_t>(as_words & 0xffffffff));
356
            } else {
357
              PrintF("%s unrecognized\n", arg1);
358
            }
359
          }
360
        } else {
361
          PrintF("print <register>\n");
362
        }
363
      } else if ((strcmp(cmd, "po") == 0)
364
                 || (strcmp(cmd, "printobject") == 0)) {
365
        if (argc == 2) {
366
          int32_t value;
367
          if (GetValue(arg1, &value)) {
368
            Object* obj = reinterpret_cast<Object*>(value);
369
            PrintF("%s: \n", arg1);
370
#ifdef DEBUG
371
            obj->PrintLn();
372
#else
373
            obj->ShortPrint();
374
            PrintF("\n");
375
#endif
376
          } else {
377
            PrintF("%s unrecognized\n", arg1);
378
          }
379
        } else {
380
          PrintF("printobject <value>\n");
381
        }
382
      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
383
        int32_t* cur = NULL;
384
        int32_t* end = NULL;
385
        int next_arg = 1;
386

    
387
        if (strcmp(cmd, "stack") == 0) {
388
          cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
389
        } else {  // "mem"
390
          int32_t value;
391
          if (!GetValue(arg1, &value)) {
392
            PrintF("%s unrecognized\n", arg1);
393
            continue;
394
          }
395
          cur = reinterpret_cast<int32_t*>(value);
396
          next_arg++;
397
        }
398

    
399
        int32_t words;
400
        if (argc == next_arg) {
401
          words = 10;
402
        } else {
403
          if (!GetValue(argv[next_arg], &words)) {
404
            words = 10;
405
          }
406
        }
407
        end = cur + words;
408

    
409
        while (cur < end) {
410
          PrintF("  0x%08x:  0x%08x %10d",
411
                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
412
          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
413
          int value = *cur;
414
          Heap* current_heap = v8::internal::Isolate::Current()->heap();
415
          if (((value & 1) == 0) || current_heap->Contains(obj)) {
416
            PrintF(" (");
417
            if ((value & 1) == 0) {
418
              PrintF("smi %d", value / 2);
419
            } else {
420
              obj->ShortPrint();
421
            }
422
            PrintF(")");
423
          }
424
          PrintF("\n");
425
          cur++;
426
        }
427
      } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
428
        disasm::NameConverter converter;
429
        disasm::Disassembler dasm(converter);
430
        // use a reasonably large buffer
431
        v8::internal::EmbeddedVector<char, 256> buffer;
432

    
433
        byte* prev = NULL;
434
        byte* cur = NULL;
435
        byte* end = NULL;
436

    
437
        if (argc == 1) {
438
          cur = reinterpret_cast<byte*>(sim_->get_pc());
439
          end = cur + (10 * Instruction::kInstrSize);
440
        } else if (argc == 2) {
441
          int regnum = Registers::Number(arg1);
442
          if (regnum != kNoRegister || strncmp(arg1, "0x", 2) == 0) {
443
            // The argument is an address or a register name.
444
            int32_t value;
445
            if (GetValue(arg1, &value)) {
446
              cur = reinterpret_cast<byte*>(value);
447
              // Disassemble 10 instructions at <arg1>.
448
              end = cur + (10 * Instruction::kInstrSize);
449
            }
450
          } else {
451
            // The argument is the number of instructions.
452
            int32_t value;
453
            if (GetValue(arg1, &value)) {
454
              cur = reinterpret_cast<byte*>(sim_->get_pc());
455
              // Disassemble <arg1> instructions.
456
              end = cur + (value * Instruction::kInstrSize);
457
            }
458
          }
459
        } else {
460
          int32_t value1;
461
          int32_t value2;
462
          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
463
            cur = reinterpret_cast<byte*>(value1);
464
            end = cur + (value2 * Instruction::kInstrSize);
465
          }
466
        }
467

    
468
        while (cur < end) {
469
          prev = cur;
470
          cur += dasm.InstructionDecode(buffer, cur);
471
          PrintF("  0x%08x  %s\n",
472
                 reinterpret_cast<intptr_t>(prev), buffer.start());
473
        }
474
      } else if (strcmp(cmd, "gdb") == 0) {
475
        PrintF("relinquishing control to gdb\n");
476
        v8::internal::OS::DebugBreak();
477
        PrintF("regaining control from gdb\n");
478
      } else if (strcmp(cmd, "break") == 0) {
479
        if (argc == 2) {
480
          int32_t value;
481
          if (GetValue(arg1, &value)) {
482
            if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
483
              PrintF("setting breakpoint failed\n");
484
            }
485
          } else {
486
            PrintF("%s unrecognized\n", arg1);
487
          }
488
        } else {
489
          PrintF("break <address>\n");
490
        }
491
      } else if (strcmp(cmd, "del") == 0) {
492
        if (!DeleteBreakpoint(NULL)) {
493
          PrintF("deleting breakpoint failed\n");
494
        }
495
      } else if (strcmp(cmd, "flags") == 0) {
496
        PrintF("N flag: %d; ", sim_->n_flag_);
497
        PrintF("Z flag: %d; ", sim_->z_flag_);
498
        PrintF("C flag: %d; ", sim_->c_flag_);
499
        PrintF("V flag: %d\n", sim_->v_flag_);
500
        PrintF("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
501
        PrintF("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
502
        PrintF("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
503
        PrintF("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
504
        PrintF("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
505
      } else if (strcmp(cmd, "stop") == 0) {
506
        int32_t value;
507
        intptr_t stop_pc = sim_->get_pc() - 2 * Instruction::kInstrSize;
508
        Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
509
        Instruction* msg_address =
510
          reinterpret_cast<Instruction*>(stop_pc + Instruction::kInstrSize);
511
        if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
512
          // Remove the current stop.
513
          if (sim_->isStopInstruction(stop_instr)) {
514
            stop_instr->SetInstructionBits(kNopInstr);
515
            msg_address->SetInstructionBits(kNopInstr);
516
          } else {
517
            PrintF("Not at debugger stop.\n");
518
          }
519
        } else if (argc == 3) {
520
          // Print information about all/the specified breakpoint(s).
521
          if (strcmp(arg1, "info") == 0) {
522
            if (strcmp(arg2, "all") == 0) {
523
              PrintF("Stop information:\n");
524
              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
525
                sim_->PrintStopInfo(i);
526
              }
527
            } else if (GetValue(arg2, &value)) {
528
              sim_->PrintStopInfo(value);
529
            } else {
530
              PrintF("Unrecognized argument.\n");
531
            }
532
          } else if (strcmp(arg1, "enable") == 0) {
533
            // Enable all/the specified breakpoint(s).
534
            if (strcmp(arg2, "all") == 0) {
535
              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
536
                sim_->EnableStop(i);
537
              }
538
            } else if (GetValue(arg2, &value)) {
539
              sim_->EnableStop(value);
540
            } else {
541
              PrintF("Unrecognized argument.\n");
542
            }
543
          } else if (strcmp(arg1, "disable") == 0) {
544
            // Disable all/the specified breakpoint(s).
545
            if (strcmp(arg2, "all") == 0) {
546
              for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
547
                sim_->DisableStop(i);
548
              }
549
            } else if (GetValue(arg2, &value)) {
550
              sim_->DisableStop(value);
551
            } else {
552
              PrintF("Unrecognized argument.\n");
553
            }
554
          }
555
        } else {
556
          PrintF("Wrong usage. Use help command for more information.\n");
557
        }
558
      } else if ((strcmp(cmd, "t") == 0) || strcmp(cmd, "trace") == 0) {
559
        ::v8::internal::FLAG_trace_sim = !::v8::internal::FLAG_trace_sim;
560
        PrintF("Trace of executed instructions is %s\n",
561
               ::v8::internal::FLAG_trace_sim ? "on" : "off");
562
      } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
563
        PrintF("cont\n");
564
        PrintF("  continue execution (alias 'c')\n");
565
        PrintF("stepi\n");
566
        PrintF("  step one instruction (alias 'si')\n");
567
        PrintF("print <register>\n");
568
        PrintF("  print register content (alias 'p')\n");
569
        PrintF("  use register name 'all' to print all registers\n");
570
        PrintF("  add argument 'fp' to print register pair double values\n");
571
        PrintF("printobject <register>\n");
572
        PrintF("  print an object from a register (alias 'po')\n");
573
        PrintF("flags\n");
574
        PrintF("  print flags\n");
575
        PrintF("stack [<words>]\n");
576
        PrintF("  dump stack content, default dump 10 words)\n");
577
        PrintF("mem <address> [<words>]\n");
578
        PrintF("  dump memory content, default dump 10 words)\n");
579
        PrintF("disasm [<instructions>]\n");
580
        PrintF("disasm [<address/register>]\n");
581
        PrintF("disasm [[<address/register>] <instructions>]\n");
582
        PrintF("  disassemble code, default is 10 instructions\n");
583
        PrintF("  from pc (alias 'di')\n");
584
        PrintF("gdb\n");
585
        PrintF("  enter gdb\n");
586
        PrintF("break <address>\n");
587
        PrintF("  set a break point on the address\n");
588
        PrintF("del\n");
589
        PrintF("  delete the breakpoint\n");
590
        PrintF("trace (alias 't')\n");
591
        PrintF("  toogle the tracing of all executed statements\n");
592
        PrintF("stop feature:\n");
593
        PrintF("  Description:\n");
594
        PrintF("    Stops are debug instructions inserted by\n");
595
        PrintF("    the Assembler::stop() function.\n");
596
        PrintF("    When hitting a stop, the Simulator will\n");
597
        PrintF("    stop and and give control to the ArmDebugger.\n");
598
        PrintF("    The first %d stop codes are watched:\n",
599
               Simulator::kNumOfWatchedStops);
600
        PrintF("    - They can be enabled / disabled: the Simulator\n");
601
        PrintF("      will / won't stop when hitting them.\n");
602
        PrintF("    - The Simulator keeps track of how many times they \n");
603
        PrintF("      are met. (See the info command.) Going over a\n");
604
        PrintF("      disabled stop still increases its counter. \n");
605
        PrintF("  Commands:\n");
606
        PrintF("    stop info all/<code> : print infos about number <code>\n");
607
        PrintF("      or all stop(s).\n");
608
        PrintF("    stop enable/disable all/<code> : enables / disables\n");
609
        PrintF("      all or number <code> stop(s)\n");
610
        PrintF("    stop unstop\n");
611
        PrintF("      ignore the stop instruction at the current location\n");
612
        PrintF("      from now on\n");
613
      } else {
614
        PrintF("Unknown command: %s\n", cmd);
615
      }
616
    }
617
  }
618

    
619
  // Add all the breakpoints back to stop execution and enter the debugger
620
  // shell when hit.
621
  RedoBreakpoints();
622

    
623
#undef COMMAND_SIZE
624
#undef ARG_SIZE
625

    
626
#undef STR
627
#undef XSTR
628
}
629

    
630

    
631
static bool ICacheMatch(void* one, void* two) {
632
  ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
633
  ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
634
  return one == two;
635
}
636

    
637

    
638
static uint32_t ICacheHash(void* key) {
639
  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
640
}
641

    
642

    
643
static bool AllOnOnePage(uintptr_t start, int size) {
644
  intptr_t start_page = (start & ~CachePage::kPageMask);
645
  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
646
  return start_page == end_page;
647
}
648

    
649

    
650
void Simulator::set_last_debugger_input(char* input) {
651
  DeleteArray(last_debugger_input_);
652
  last_debugger_input_ = input;
653
}
654

    
655

    
656
void Simulator::FlushICache(v8::internal::HashMap* i_cache,
657
                            void* start_addr,
658
                            size_t size) {
659
  intptr_t start = reinterpret_cast<intptr_t>(start_addr);
660
  int intra_line = (start & CachePage::kLineMask);
661
  start -= intra_line;
662
  size += intra_line;
663
  size = ((size - 1) | CachePage::kLineMask) + 1;
664
  int offset = (start & CachePage::kPageMask);
665
  while (!AllOnOnePage(start, size - 1)) {
666
    int bytes_to_flush = CachePage::kPageSize - offset;
667
    FlushOnePage(i_cache, start, bytes_to_flush);
668
    start += bytes_to_flush;
669
    size -= bytes_to_flush;
670
    ASSERT_EQ(0, start & CachePage::kPageMask);
671
    offset = 0;
672
  }
673
  if (size != 0) {
674
    FlushOnePage(i_cache, start, size);
675
  }
676
}
677

    
678

    
679
CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
680
  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
681
                                                        ICacheHash(page),
682
                                                        true);
683
  if (entry->value == NULL) {
684
    CachePage* new_page = new CachePage();
685
    entry->value = new_page;
686
  }
687
  return reinterpret_cast<CachePage*>(entry->value);
688
}
689

    
690

    
691
// Flush from start up to and not including start + size.
692
void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
693
                             intptr_t start,
694
                             int size) {
695
  ASSERT(size <= CachePage::kPageSize);
696
  ASSERT(AllOnOnePage(start, size - 1));
697
  ASSERT((start & CachePage::kLineMask) == 0);
698
  ASSERT((size & CachePage::kLineMask) == 0);
699
  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
700
  int offset = (start & CachePage::kPageMask);
701
  CachePage* cache_page = GetCachePage(i_cache, page);
702
  char* valid_bytemap = cache_page->ValidityByte(offset);
703
  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
704
}
705

    
706

    
707
void Simulator::CheckICache(v8::internal::HashMap* i_cache,
708
                            Instruction* instr) {
709
  intptr_t address = reinterpret_cast<intptr_t>(instr);
710
  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
711
  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
712
  int offset = (address & CachePage::kPageMask);
713
  CachePage* cache_page = GetCachePage(i_cache, page);
714
  char* cache_valid_byte = cache_page->ValidityByte(offset);
715
  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
716
  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
717
  if (cache_hit) {
718
    // Check that the data in memory matches the contents of the I-cache.
719
    CHECK(memcmp(reinterpret_cast<void*>(instr),
720
                 cache_page->CachedData(offset),
721
                 Instruction::kInstrSize) == 0);
722
  } else {
723
    // Cache miss.  Load memory into the cache.
724
    OS::MemCopy(cached_line, line, CachePage::kLineLength);
725
    *cache_valid_byte = CachePage::LINE_VALID;
726
  }
727
}
728

    
729

    
730
void Simulator::Initialize(Isolate* isolate) {
731
  if (isolate->simulator_initialized()) return;
732
  isolate->set_simulator_initialized(true);
733
  ::v8::internal::ExternalReference::set_redirector(isolate,
734
                                                    &RedirectExternalReference);
735
}
736

    
737

    
738
Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
739
  i_cache_ = isolate_->simulator_i_cache();
740
  if (i_cache_ == NULL) {
741
    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
742
    isolate_->set_simulator_i_cache(i_cache_);
743
  }
744
  Initialize(isolate);
745
  // Set up simulator support first. Some of this information is needed to
746
  // setup the architecture state.
747
  size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
748
  stack_ = reinterpret_cast<char*>(malloc(stack_size));
749
  pc_modified_ = false;
750
  icount_ = 0;
751
  break_pc_ = NULL;
752
  break_instr_ = 0;
753

    
754
  // Set up architecture state.
755
  // All registers are initialized to zero to start with.
756
  for (int i = 0; i < num_registers; i++) {
757
    registers_[i] = 0;
758
  }
759
  n_flag_ = false;
760
  z_flag_ = false;
761
  c_flag_ = false;
762
  v_flag_ = false;
763

    
764
  // Initializing VFP registers.
765
  // All registers are initialized to zero to start with
766
  // even though s_registers_ & d_registers_ share the same
767
  // physical registers in the target.
768
  for (int i = 0; i < num_d_registers * 2; i++) {
769
    vfp_registers_[i] = 0;
770
  }
771
  n_flag_FPSCR_ = false;
772
  z_flag_FPSCR_ = false;
773
  c_flag_FPSCR_ = false;
774
  v_flag_FPSCR_ = false;
775
  FPSCR_rounding_mode_ = RZ;
776
  FPSCR_default_NaN_mode_ = true;
777

    
778
  inv_op_vfp_flag_ = false;
779
  div_zero_vfp_flag_ = false;
780
  overflow_vfp_flag_ = false;
781
  underflow_vfp_flag_ = false;
782
  inexact_vfp_flag_ = false;
783

    
784
  // The sp is initialized to point to the bottom (high address) of the
785
  // allocated stack area. To be safe in potential stack underflows we leave
786
  // some buffer below.
787
  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
788
  // The lr and pc are initialized to a known bad value that will cause an
789
  // access violation if the simulator ever tries to execute it.
790
  registers_[pc] = bad_lr;
791
  registers_[lr] = bad_lr;
792
  InitializeCoverage();
793

    
794
  last_debugger_input_ = NULL;
795
}
796

    
797

    
798
// When the generated code calls an external reference we need to catch that in
799
// the simulator.  The external reference will be a function compiled for the
800
// host architecture.  We need to call that function instead of trying to
801
// execute it with the simulator.  We do that by redirecting the external
802
// reference to a svc (Supervisor Call) instruction that is handled by
803
// the simulator.  We write the original destination of the jump just at a known
804
// offset from the svc instruction so the simulator knows what to call.
805
class Redirection {
806
 public:
807
  Redirection(void* external_function, ExternalReference::Type type)
808
      : external_function_(external_function),
809
        swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
810
        type_(type),
811
        next_(NULL) {
812
    Isolate* isolate = Isolate::Current();
813
    next_ = isolate->simulator_redirection();
814
    Simulator::current(isolate)->
815
        FlushICache(isolate->simulator_i_cache(),
816
                    reinterpret_cast<void*>(&swi_instruction_),
817
                    Instruction::kInstrSize);
818
    isolate->set_simulator_redirection(this);
819
  }
820

    
821
  void* address_of_swi_instruction() {
822
    return reinterpret_cast<void*>(&swi_instruction_);
823
  }
824

    
825
  void* external_function() { return external_function_; }
826
  ExternalReference::Type type() { return type_; }
827

    
828
  static Redirection* Get(void* external_function,
829
                          ExternalReference::Type type) {
830
    Isolate* isolate = Isolate::Current();
831
    Redirection* current = isolate->simulator_redirection();
832
    for (; current != NULL; current = current->next_) {
833
      if (current->external_function_ == external_function) {
834
        ASSERT_EQ(current->type(), type);
835
        return current;
836
      }
837
    }
838
    return new Redirection(external_function, type);
839
  }
840

    
841
  static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
842
    char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
843
    char* addr_of_redirection =
844
        addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
845
    return reinterpret_cast<Redirection*>(addr_of_redirection);
846
  }
847

    
848
 private:
849
  void* external_function_;
850
  uint32_t swi_instruction_;
851
  ExternalReference::Type type_;
852
  Redirection* next_;
853
};
854

    
855

    
856
void* Simulator::RedirectExternalReference(void* external_function,
857
                                           ExternalReference::Type type) {
858
  Redirection* redirection = Redirection::Get(external_function, type);
859
  return redirection->address_of_swi_instruction();
860
}
861

    
862

    
863
// Get the active Simulator for the current thread.
864
Simulator* Simulator::current(Isolate* isolate) {
865
  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
866
      isolate->FindOrAllocatePerThreadDataForThisThread();
867
  ASSERT(isolate_data != NULL);
868

    
869
  Simulator* sim = isolate_data->simulator();
870
  if (sim == NULL) {
871
    // TODO(146): delete the simulator object when a thread/isolate goes away.
872
    sim = new Simulator(isolate);
873
    isolate_data->set_simulator(sim);
874
  }
875
  return sim;
876
}
877

    
878

    
879
// Sets the register in the architecture state. It will also deal with updating
880
// Simulator internal state for special registers such as PC.
881
void Simulator::set_register(int reg, int32_t value) {
882
  ASSERT((reg >= 0) && (reg < num_registers));
883
  if (reg == pc) {
884
    pc_modified_ = true;
885
  }
886
  registers_[reg] = value;
887
}
888

    
889

    
890
// Get the register from the architecture state. This function does handle
891
// the special case of accessing the PC register.
892
int32_t Simulator::get_register(int reg) const {
893
  ASSERT((reg >= 0) && (reg < num_registers));
894
  // Stupid code added to avoid bug in GCC.
895
  // See: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
896
  if (reg >= num_registers) return 0;
897
  // End stupid code.
898
  return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
899
}
900

    
901

    
902
double Simulator::get_double_from_register_pair(int reg) {
903
  ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
904

    
905
  double dm_val = 0.0;
906
  // Read the bits from the unsigned integer register_[] array
907
  // into the double precision floating point value and return it.
908
  char buffer[2 * sizeof(vfp_registers_[0])];
909
  OS::MemCopy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
910
  OS::MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0]));
911
  return(dm_val);
912
}
913

    
914

    
915
void Simulator::set_register_pair_from_double(int reg, double* value) {
916
  ASSERT((reg >= 0) && (reg < num_registers) && ((reg % 2) == 0));
917
  memcpy(registers_ + reg, value, sizeof(*value));
918
}
919

    
920

    
921
void Simulator::set_dw_register(int dreg, const int* dbl) {
922
  ASSERT((dreg >= 0) && (dreg < num_d_registers));
923
  registers_[dreg] = dbl[0];
924
  registers_[dreg + 1] = dbl[1];
925
}
926

    
927

    
928
void Simulator::get_d_register(int dreg, uint64_t* value) {
929
  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
930
  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
931
}
932

    
933

    
934
void Simulator::set_d_register(int dreg, const uint64_t* value) {
935
  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
936
  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
937
}
938

    
939

    
940
void Simulator::get_d_register(int dreg, uint32_t* value) {
941
  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
942
  memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
943
}
944

    
945

    
946
void Simulator::set_d_register(int dreg, const uint32_t* value) {
947
  ASSERT((dreg >= 0) && (dreg < DwVfpRegister::NumRegisters()));
948
  memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
949
}
950

    
951

    
952
void Simulator::get_q_register(int qreg, uint64_t* value) {
953
  ASSERT((qreg >= 0) && (qreg < num_q_registers));
954
  memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2);
955
}
956

    
957

    
958
void Simulator::set_q_register(int qreg, const uint64_t* value) {
959
  ASSERT((qreg >= 0) && (qreg < num_q_registers));
960
  memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2);
961
}
962

    
963

    
964
void Simulator::get_q_register(int qreg, uint32_t* value) {
965
  ASSERT((qreg >= 0) && (qreg < num_q_registers));
966
  memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4);
967
}
968

    
969

    
970
void Simulator::set_q_register(int qreg, const uint32_t* value) {
971
  ASSERT((qreg >= 0) && (qreg < num_q_registers));
972
  memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4);
973
}
974

    
975

    
976
// Raw access to the PC register.
977
void Simulator::set_pc(int32_t value) {
978
  pc_modified_ = true;
979
  registers_[pc] = value;
980
}
981

    
982

    
983
bool Simulator::has_bad_pc() const {
984
  return ((registers_[pc] == bad_lr) || (registers_[pc] == end_sim_pc));
985
}
986

    
987

    
988
// Raw access to the PC register without the special adjustment when reading.
989
int32_t Simulator::get_pc() const {
990
  return registers_[pc];
991
}
992

    
993

    
994
// Getting from and setting into VFP registers.
995
void Simulator::set_s_register(int sreg, unsigned int value) {
996
  ASSERT((sreg >= 0) && (sreg < num_s_registers));
997
  vfp_registers_[sreg] = value;
998
}
999

    
1000

    
1001
unsigned int Simulator::get_s_register(int sreg) const {
1002
  ASSERT((sreg >= 0) && (sreg < num_s_registers));
1003
  return vfp_registers_[sreg];
1004
}
1005

    
1006

    
1007
template<class InputType, int register_size>
1008
void Simulator::SetVFPRegister(int reg_index, const InputType& value) {
1009
  ASSERT(reg_index >= 0);
1010
  if (register_size == 1) ASSERT(reg_index < num_s_registers);
1011
  if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters());
1012

    
1013
  char buffer[register_size * sizeof(vfp_registers_[0])];
1014
  OS::MemCopy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
1015
  OS::MemCopy(&vfp_registers_[reg_index * register_size], buffer,
1016
              register_size * sizeof(vfp_registers_[0]));
1017
}
1018

    
1019

    
1020
template<class ReturnType, int register_size>
1021
ReturnType Simulator::GetFromVFPRegister(int reg_index) {
1022
  ASSERT(reg_index >= 0);
1023
  if (register_size == 1) ASSERT(reg_index < num_s_registers);
1024
  if (register_size == 2) ASSERT(reg_index < DwVfpRegister::NumRegisters());
1025

    
1026
  ReturnType value = 0;
1027
  char buffer[register_size * sizeof(vfp_registers_[0])];
1028
  OS::MemCopy(buffer, &vfp_registers_[register_size * reg_index],
1029
              register_size * sizeof(vfp_registers_[0]));
1030
  OS::MemCopy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
1031
  return value;
1032
}
1033

    
1034

    
1035
// Runtime FP routines take:
1036
// - two double arguments
1037
// - one double argument and zero or one integer arguments.
1038
// All are consructed here from r0-r3 or d0, d1 and r0.
1039
void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1040
  if (use_eabi_hardfloat()) {
1041
    *x = get_double_from_d_register(0);
1042
    *y = get_double_from_d_register(1);
1043
    *z = get_register(0);
1044
  } else {
1045
    // Registers 0 and 1 -> x.
1046
    *x = get_double_from_register_pair(0);
1047
    // Register 2 and 3 -> y.
1048
    *y = get_double_from_register_pair(2);
1049
    // Register 2 -> z
1050
    *z = get_register(2);
1051
  }
1052
}
1053

    
1054

    
1055
// The return value is either in r0/r1 or d0.
1056
void Simulator::SetFpResult(const double& result) {
1057
  if (use_eabi_hardfloat()) {
1058
    char buffer[2 * sizeof(vfp_registers_[0])];
1059
    OS::MemCopy(buffer, &result, sizeof(buffer));
1060
    // Copy result to d0.
1061
    OS::MemCopy(vfp_registers_, buffer, sizeof(buffer));
1062
  } else {
1063
    char buffer[2 * sizeof(registers_[0])];
1064
    OS::MemCopy(buffer, &result, sizeof(buffer));
1065
    // Copy result to r0 and r1.
1066
    OS::MemCopy(registers_, buffer, sizeof(buffer));
1067
  }
1068
}
1069

    
1070

    
1071
void Simulator::TrashCallerSaveRegisters() {
1072
  // We don't trash the registers with the return value.
1073
  registers_[2] = 0x50Bad4U;
1074
  registers_[3] = 0x50Bad4U;
1075
  registers_[12] = 0x50Bad4U;
1076
}
1077

    
1078

    
1079
// Some Operating Systems allow unaligned access on ARMv7 targets. We
1080
// assume that unaligned accesses are not allowed unless the v8 build system
1081
// defines the CAN_USE_UNALIGNED_ACCESSES macro to be non-zero.
1082
// The following statements below describes the behavior of the ARM CPUs
1083
// that don't support unaligned access.
1084
// Some ARM platforms raise an interrupt on detecting unaligned access.
1085
// On others it does a funky rotation thing.  For now we
1086
// simply disallow unaligned reads.  Note that simulator runs have the runtime
1087
// system running directly on the host system and only generated code is
1088
// executed in the simulator.  Since the host is typically IA32 we will not
1089
// get the correct ARM-like behaviour on unaligned accesses for those ARM
1090
// targets that don't support unaligned loads and stores.
1091

    
1092

    
1093
int Simulator::ReadW(int32_t addr, Instruction* instr) {
1094
  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1095
    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1096
    return *ptr;
1097
  } else {
1098
    PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1099
           addr,
1100
           reinterpret_cast<intptr_t>(instr));
1101
    UNIMPLEMENTED();
1102
    return 0;
1103
  }
1104
}
1105

    
1106

    
1107
void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1108
  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1109
    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1110
    *ptr = value;
1111
  } else {
1112
    PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1113
           addr,
1114
           reinterpret_cast<intptr_t>(instr));
1115
    UNIMPLEMENTED();
1116
  }
1117
}
1118

    
1119

    
1120
uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1121
  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1122
    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1123
    return *ptr;
1124
  } else {
1125
    PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08"
1126
           V8PRIxPTR "\n",
1127
           addr,
1128
           reinterpret_cast<intptr_t>(instr));
1129
    UNIMPLEMENTED();
1130
    return 0;
1131
  }
1132
}
1133

    
1134

    
1135
int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1136
  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1137
    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1138
    return *ptr;
1139
  } else {
1140
    PrintF("Unaligned signed halfword read at 0x%08x\n", addr);
1141
    UNIMPLEMENTED();
1142
    return 0;
1143
  }
1144
}
1145

    
1146

    
1147
void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1148
  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1149
    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1150
    *ptr = value;
1151
  } else {
1152
    PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08"
1153
           V8PRIxPTR "\n",
1154
           addr,
1155
           reinterpret_cast<intptr_t>(instr));
1156
    UNIMPLEMENTED();
1157
  }
1158
}
1159

    
1160

    
1161
void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1162
  if (FLAG_enable_unaligned_accesses || (addr & 1) == 0) {
1163
    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1164
    *ptr = value;
1165
  } else {
1166
    PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1167
           addr,
1168
           reinterpret_cast<intptr_t>(instr));
1169
    UNIMPLEMENTED();
1170
  }
1171
}
1172

    
1173

    
1174
uint8_t Simulator::ReadBU(int32_t addr) {
1175
  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1176
  return *ptr;
1177
}
1178

    
1179

    
1180
int8_t Simulator::ReadB(int32_t addr) {
1181
  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1182
  return *ptr;
1183
}
1184

    
1185

    
1186
void Simulator::WriteB(int32_t addr, uint8_t value) {
1187
  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1188
  *ptr = value;
1189
}
1190

    
1191

    
1192
void Simulator::WriteB(int32_t addr, int8_t value) {
1193
  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1194
  *ptr = value;
1195
}
1196

    
1197

    
1198
int32_t* Simulator::ReadDW(int32_t addr) {
1199
  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1200
    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1201
    return ptr;
1202
  } else {
1203
    PrintF("Unaligned read at 0x%08x\n", addr);
1204
    UNIMPLEMENTED();
1205
    return 0;
1206
  }
1207
}
1208

    
1209

    
1210
void Simulator::WriteDW(int32_t addr, int32_t value1, int32_t value2) {
1211
  if (FLAG_enable_unaligned_accesses || (addr & 3) == 0) {
1212
    int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1213
    *ptr++ = value1;
1214
    *ptr = value2;
1215
  } else {
1216
    PrintF("Unaligned write at 0x%08x\n", addr);
1217
    UNIMPLEMENTED();
1218
  }
1219
}
1220

    
1221

    
1222
// Returns the limit of the stack area to enable checking for stack overflows.
1223
uintptr_t Simulator::StackLimit() const {
1224
  // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1225
  // pushing values.
1226
  return reinterpret_cast<uintptr_t>(stack_) + 1024;
1227
}
1228

    
1229

    
1230
// Unsupported instructions use Format to print an error and stop execution.
1231
void Simulator::Format(Instruction* instr, const char* format) {
1232
  PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1233
         reinterpret_cast<intptr_t>(instr), format);
1234
  UNIMPLEMENTED();
1235
}
1236

    
1237

    
1238
// Checks if the current instruction should be executed based on its
1239
// condition bits.
1240
bool Simulator::ConditionallyExecute(Instruction* instr) {
1241
  switch (instr->ConditionField()) {
1242
    case eq: return z_flag_;
1243
    case ne: return !z_flag_;
1244
    case cs: return c_flag_;
1245
    case cc: return !c_flag_;
1246
    case mi: return n_flag_;
1247
    case pl: return !n_flag_;
1248
    case vs: return v_flag_;
1249
    case vc: return !v_flag_;
1250
    case hi: return c_flag_ && !z_flag_;
1251
    case ls: return !c_flag_ || z_flag_;
1252
    case ge: return n_flag_ == v_flag_;
1253
    case lt: return n_flag_ != v_flag_;
1254
    case gt: return !z_flag_ && (n_flag_ == v_flag_);
1255
    case le: return z_flag_ || (n_flag_ != v_flag_);
1256
    case al: return true;
1257
    default: UNREACHABLE();
1258
  }
1259
  return false;
1260
}
1261

    
1262

    
1263
// Calculate and set the Negative and Zero flags.
1264
void Simulator::SetNZFlags(int32_t val) {
1265
  n_flag_ = (val < 0);
1266
  z_flag_ = (val == 0);
1267
}
1268

    
1269

    
1270
// Set the Carry flag.
1271
void Simulator::SetCFlag(bool val) {
1272
  c_flag_ = val;
1273
}
1274

    
1275

    
1276
// Set the oVerflow flag.
1277
void Simulator::SetVFlag(bool val) {
1278
  v_flag_ = val;
1279
}
1280

    
1281

    
1282
// Calculate C flag value for additions.
1283
bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1284
  uint32_t uleft = static_cast<uint32_t>(left);
1285
  uint32_t uright = static_cast<uint32_t>(right);
1286
  uint32_t urest  = 0xffffffffU - uleft;
1287

    
1288
  return (uright > urest) ||
1289
         (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1290
}
1291

    
1292

    
1293
// Calculate C flag value for subtractions.
1294
bool Simulator::BorrowFrom(int32_t left, int32_t right) {
1295
  uint32_t uleft = static_cast<uint32_t>(left);
1296
  uint32_t uright = static_cast<uint32_t>(right);
1297

    
1298
  return (uright > uleft);
1299
}
1300

    
1301

    
1302
// Calculate V flag value for additions and subtractions.
1303
bool Simulator::OverflowFrom(int32_t alu_out,
1304
                             int32_t left, int32_t right, bool addition) {
1305
  bool overflow;
1306
  if (addition) {
1307
               // operands have the same sign
1308
    overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1309
               // and operands and result have different sign
1310
               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1311
  } else {
1312
               // operands have different signs
1313
    overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1314
               // and first operand and result have different signs
1315
               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1316
  }
1317
  return overflow;
1318
}
1319

    
1320

    
1321
// Support for VFP comparisons.
1322
void Simulator::Compute_FPSCR_Flags(double val1, double val2) {
1323
  if (std::isnan(val1) || std::isnan(val2)) {
1324
    n_flag_FPSCR_ = false;
1325
    z_flag_FPSCR_ = false;
1326
    c_flag_FPSCR_ = true;
1327
    v_flag_FPSCR_ = true;
1328
  // All non-NaN cases.
1329
  } else if (val1 == val2) {
1330
    n_flag_FPSCR_ = false;
1331
    z_flag_FPSCR_ = true;
1332
    c_flag_FPSCR_ = true;
1333
    v_flag_FPSCR_ = false;
1334
  } else if (val1 < val2) {
1335
    n_flag_FPSCR_ = true;
1336
    z_flag_FPSCR_ = false;
1337
    c_flag_FPSCR_ = false;
1338
    v_flag_FPSCR_ = false;
1339
  } else {
1340
    // Case when (val1 > val2).
1341
    n_flag_FPSCR_ = false;
1342
    z_flag_FPSCR_ = false;
1343
    c_flag_FPSCR_ = true;
1344
    v_flag_FPSCR_ = false;
1345
  }
1346
}
1347

    
1348

    
1349
void Simulator::Copy_FPSCR_to_APSR() {
1350
  n_flag_ = n_flag_FPSCR_;
1351
  z_flag_ = z_flag_FPSCR_;
1352
  c_flag_ = c_flag_FPSCR_;
1353
  v_flag_ = v_flag_FPSCR_;
1354
}
1355

    
1356

    
1357
// Addressing Mode 1 - Data-processing operands:
1358
// Get the value based on the shifter_operand with register.
1359
int32_t Simulator::GetShiftRm(Instruction* instr, bool* carry_out) {
1360
  ShiftOp shift = instr->ShiftField();
1361
  int shift_amount = instr->ShiftAmountValue();
1362
  int32_t result = get_register(instr->RmValue());
1363
  if (instr->Bit(4) == 0) {
1364
    // by immediate
1365
    if ((shift == ROR) && (shift_amount == 0)) {
1366
      UNIMPLEMENTED();
1367
      return result;
1368
    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
1369
      shift_amount = 32;
1370
    }
1371
    switch (shift) {
1372
      case ASR: {
1373
        if (shift_amount == 0) {
1374
          if (result < 0) {
1375
            result = 0xffffffff;
1376
            *carry_out = true;
1377
          } else {
1378
            result = 0;
1379
            *carry_out = false;
1380
          }
1381
        } else {
1382
          result >>= (shift_amount - 1);
1383
          *carry_out = (result & 1) == 1;
1384
          result >>= 1;
1385
        }
1386
        break;
1387
      }
1388

    
1389
      case LSL: {
1390
        if (shift_amount == 0) {
1391
          *carry_out = c_flag_;
1392
        } else {
1393
          result <<= (shift_amount - 1);
1394
          *carry_out = (result < 0);
1395
          result <<= 1;
1396
        }
1397
        break;
1398
      }
1399

    
1400
      case LSR: {
1401
        if (shift_amount == 0) {
1402
          result = 0;
1403
          *carry_out = c_flag_;
1404
        } else {
1405
          uint32_t uresult = static_cast<uint32_t>(result);
1406
          uresult >>= (shift_amount - 1);
1407
          *carry_out = (uresult & 1) == 1;
1408
          uresult >>= 1;
1409
          result = static_cast<int32_t>(uresult);
1410
        }
1411
        break;
1412
      }
1413

    
1414
      case ROR: {
1415
        if (shift_amount == 0) {
1416
          *carry_out = c_flag_;
1417
        } else {
1418
          uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1419
          uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1420
          result = right | left;
1421
          *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1422
        }
1423
        break;
1424
      }
1425

    
1426
      default: {
1427
        UNREACHABLE();
1428
        break;
1429
      }
1430
    }
1431
  } else {
1432
    // by register
1433
    int rs = instr->RsValue();
1434
    shift_amount = get_register(rs) &0xff;
1435
    switch (shift) {
1436
      case ASR: {
1437
        if (shift_amount == 0) {
1438
          *carry_out = c_flag_;
1439
        } else if (shift_amount < 32) {
1440
          result >>= (shift_amount - 1);
1441
          *carry_out = (result & 1) == 1;
1442
          result >>= 1;
1443
        } else {
1444
          ASSERT(shift_amount >= 32);
1445
          if (result < 0) {
1446
            *carry_out = true;
1447
            result = 0xffffffff;
1448
          } else {
1449
            *carry_out = false;
1450
            result = 0;
1451
          }
1452
        }
1453
        break;
1454
      }
1455

    
1456
      case LSL: {
1457
        if (shift_amount == 0) {
1458
          *carry_out = c_flag_;
1459
        } else if (shift_amount < 32) {
1460
          result <<= (shift_amount - 1);
1461
          *carry_out = (result < 0);
1462
          result <<= 1;
1463
        } else if (shift_amount == 32) {
1464
          *carry_out = (result & 1) == 1;
1465
          result = 0;
1466
        } else {
1467
          ASSERT(shift_amount > 32);
1468
          *carry_out = false;
1469
          result = 0;
1470
        }
1471
        break;
1472
      }
1473

    
1474
      case LSR: {
1475
        if (shift_amount == 0) {
1476
          *carry_out = c_flag_;
1477
        } else if (shift_amount < 32) {
1478
          uint32_t uresult = static_cast<uint32_t>(result);
1479
          uresult >>= (shift_amount - 1);
1480
          *carry_out = (uresult & 1) == 1;
1481
          uresult >>= 1;
1482
          result = static_cast<int32_t>(uresult);
1483
        } else if (shift_amount == 32) {
1484
          *carry_out = (result < 0);
1485
          result = 0;
1486
        } else {
1487
          *carry_out = false;
1488
          result = 0;
1489
        }
1490
        break;
1491
      }
1492

    
1493
      case ROR: {
1494
        if (shift_amount == 0) {
1495
          *carry_out = c_flag_;
1496
        } else {
1497
          uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
1498
          uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
1499
          result = right | left;
1500
          *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
1501
        }
1502
        break;
1503
      }
1504

    
1505
      default: {
1506
        UNREACHABLE();
1507
        break;
1508
      }
1509
    }
1510
  }
1511
  return result;
1512
}
1513

    
1514

    
1515
// Addressing Mode 1 - Data-processing operands:
1516
// Get the value based on the shifter_operand with immediate.
1517
int32_t Simulator::GetImm(Instruction* instr, bool* carry_out) {
1518
  int rotate = instr->RotateValue() * 2;
1519
  int immed8 = instr->Immed8Value();
1520
  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
1521
  *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
1522
  return imm;
1523
}
1524

    
1525

    
1526
static int count_bits(int bit_vector) {
1527
  int count = 0;
1528
  while (bit_vector != 0) {
1529
    if ((bit_vector & 1) != 0) {
1530
      count++;
1531
    }
1532
    bit_vector >>= 1;
1533
  }
1534
  return count;
1535
}
1536

    
1537

    
1538
int32_t Simulator::ProcessPU(Instruction* instr,
1539
                             int num_regs,
1540
                             int reg_size,
1541
                             intptr_t* start_address,
1542
                             intptr_t* end_address) {
1543
  int rn = instr->RnValue();
1544
  int32_t rn_val = get_register(rn);
1545
  switch (instr->PUField()) {
1546
    case da_x: {
1547
      UNIMPLEMENTED();
1548
      break;
1549
    }
1550
    case ia_x: {
1551
      *start_address = rn_val;
1552
      *end_address = rn_val + (num_regs * reg_size) - reg_size;
1553
      rn_val = rn_val + (num_regs * reg_size);
1554
      break;
1555
    }
1556
    case db_x: {
1557
      *start_address = rn_val - (num_regs * reg_size);
1558
      *end_address = rn_val - reg_size;
1559
      rn_val = *start_address;
1560
      break;
1561
    }
1562
    case ib_x: {
1563
      *start_address = rn_val + reg_size;
1564
      *end_address = rn_val + (num_regs * reg_size);
1565
      rn_val = *end_address;
1566
      break;
1567
    }
1568
    default: {
1569
      UNREACHABLE();
1570
      break;
1571
    }
1572
  }
1573
  return rn_val;
1574
}
1575

    
1576

    
1577
// Addressing Mode 4 - Load and Store Multiple
1578
void Simulator::HandleRList(Instruction* instr, bool load) {
1579
  int rlist = instr->RlistValue();
1580
  int num_regs = count_bits(rlist);
1581

    
1582
  intptr_t start_address = 0;
1583
  intptr_t end_address = 0;
1584
  int32_t rn_val =
1585
      ProcessPU(instr, num_regs, kPointerSize, &start_address, &end_address);
1586

    
1587
  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1588
  // Catch null pointers a little earlier.
1589
  ASSERT(start_address > 8191 || start_address < 0);
1590
  int reg = 0;
1591
  while (rlist != 0) {
1592
    if ((rlist & 1) != 0) {
1593
      if (load) {
1594
        set_register(reg, *address);
1595
      } else {
1596
        *address = get_register(reg);
1597
      }
1598
      address += 1;
1599
    }
1600
    reg++;
1601
    rlist >>= 1;
1602
  }
1603
  ASSERT(end_address == ((intptr_t)address) - 4);
1604
  if (instr->HasW()) {
1605
    set_register(instr->RnValue(), rn_val);
1606
  }
1607
}
1608

    
1609

    
1610
// Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
1611
void Simulator::HandleVList(Instruction* instr) {
1612
  VFPRegPrecision precision =
1613
      (instr->SzValue() == 0) ? kSinglePrecision : kDoublePrecision;
1614
  int operand_size = (precision == kSinglePrecision) ? 4 : 8;
1615

    
1616
  bool load = (instr->VLValue() == 0x1);
1617

    
1618
  int vd;
1619
  int num_regs;
1620
  vd = instr->VFPDRegValue(precision);
1621
  if (precision == kSinglePrecision) {
1622
    num_regs = instr->Immed8Value();
1623
  } else {
1624
    num_regs = instr->Immed8Value() / 2;
1625
  }
1626

    
1627
  intptr_t start_address = 0;
1628
  intptr_t end_address = 0;
1629
  int32_t rn_val =
1630
      ProcessPU(instr, num_regs, operand_size, &start_address, &end_address);
1631

    
1632
  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
1633
  for (int reg = vd; reg < vd + num_regs; reg++) {
1634
    if (precision == kSinglePrecision) {
1635
      if (load) {
1636
        set_s_register_from_sinteger(
1637
            reg, ReadW(reinterpret_cast<int32_t>(address), instr));
1638
      } else {
1639
        WriteW(reinterpret_cast<int32_t>(address),
1640
               get_sinteger_from_s_register(reg), instr);
1641
      }
1642
      address += 1;
1643
    } else {
1644
      if (load) {
1645
        int32_t data[] = {
1646
          ReadW(reinterpret_cast<int32_t>(address), instr),
1647
          ReadW(reinterpret_cast<int32_t>(address + 1), instr)
1648
        };
1649
        double d;
1650
        OS::MemCopy(&d, data, 8);
1651
        set_d_register_from_double(reg, d);
1652
      } else {
1653
        int32_t data[2];
1654
        double d = get_double_from_d_register(reg);
1655
        OS::MemCopy(data, &d, 8);
1656
        WriteW(reinterpret_cast<int32_t>(address), data[0], instr);
1657
        WriteW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
1658
      }
1659
      address += 2;
1660
    }
1661
  }
1662
  ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
1663
  if (instr->HasW()) {
1664
    set_register(instr->RnValue(), rn_val);
1665
  }
1666
}
1667

    
1668

    
1669
// Calls into the V8 runtime are based on this very simple interface.
1670
// Note: To be able to return two values from some calls the code in runtime.cc
1671
// uses the ObjectPair which is essentially two 32-bit values stuffed into a
1672
// 64-bit value. With the code below we assume that all runtime calls return
1673
// 64 bits of result. If they don't, the r1 result register contains a bogus
1674
// value, which is fine because it is caller-saved.
1675
typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1676
                                        int32_t arg1,
1677
                                        int32_t arg2,
1678
                                        int32_t arg3,
1679
                                        int32_t arg4,
1680
                                        int32_t arg5);
1681

    
1682
// These prototypes handle the four types of FP calls.
1683
typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1684
typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1685
typedef double (*SimulatorRuntimeFPCall)(double darg0);
1686
typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1687

    
1688
// This signature supports direct call in to API function native callback
1689
// (refer to InvocationCallback in v8.h).
1690
typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1691
typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, int32_t arg1);
1692

    
1693
// This signature supports direct call to accessor getter callback.
1694
typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1695
typedef void (*SimulatorRuntimeProfilingGetterCall)(
1696
    int32_t arg0, int32_t arg1, int32_t arg2);
1697

    
1698
// Software interrupt instructions are used by the simulator to call into the
1699
// C-based V8 runtime.
1700
void Simulator::SoftwareInterrupt(Instruction* instr) {
1701
  int svc = instr->SvcValue();
1702
  switch (svc) {
1703
    case kCallRtRedirected: {
1704
      // Check if stack is aligned. Error if not aligned is reported below to
1705
      // include information on the function called.
1706
      bool stack_aligned =
1707
          (get_register(sp)
1708
           & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1709
      Redirection* redirection = Redirection::FromSwiInstruction(instr);
1710
      int32_t arg0 = get_register(r0);
1711
      int32_t arg1 = get_register(r1);
1712
      int32_t arg2 = get_register(r2);
1713
      int32_t arg3 = get_register(r3);
1714
      int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1715
      int32_t arg4 = stack_pointer[0];
1716
      int32_t arg5 = stack_pointer[1];
1717
      bool fp_call =
1718
         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1719
         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1720
         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1721
         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1722
      // This is dodgy but it works because the C entry stubs are never moved.
1723
      // See comment in codegen-arm.cc and bug 1242173.
1724
      int32_t saved_lr = get_register(lr);
1725
      intptr_t external =
1726
          reinterpret_cast<intptr_t>(redirection->external_function());
1727
      if (fp_call) {
1728
        double dval0, dval1;  // one or two double parameters
1729
        int32_t ival;         // zero or one integer parameters
1730
        int64_t iresult = 0;  // integer return value
1731
        double dresult = 0;   // double return value
1732
        GetFpArgs(&dval0, &dval1, &ival);
1733
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1734
          SimulatorRuntimeCall generic_target =
1735
            reinterpret_cast<SimulatorRuntimeCall>(external);
1736
          switch (redirection->type()) {
1737
          case ExternalReference::BUILTIN_FP_FP_CALL:
1738
          case ExternalReference::BUILTIN_COMPARE_CALL:
1739
            PrintF("Call to host function at %p with args %f, %f",
1740
                   FUNCTION_ADDR(generic_target), dval0, dval1);
1741
            break;
1742
          case ExternalReference::BUILTIN_FP_CALL:
1743
            PrintF("Call to host function at %p with arg %f",
1744
                FUNCTION_ADDR(generic_target), dval0);
1745
            break;
1746
          case ExternalReference::BUILTIN_FP_INT_CALL:
1747
            PrintF("Call to host function at %p with args %f, %d",
1748
                   FUNCTION_ADDR(generic_target), dval0, ival);
1749
            break;
1750
          default:
1751
            UNREACHABLE();
1752
            break;
1753
          }
1754
          if (!stack_aligned) {
1755
            PrintF(" with unaligned stack %08x\n", get_register(sp));
1756
          }
1757
          PrintF("\n");
1758
        }
1759
        CHECK(stack_aligned);
1760
        switch (redirection->type()) {
1761
        case ExternalReference::BUILTIN_COMPARE_CALL: {
1762
          SimulatorRuntimeCompareCall target =
1763
            reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1764
          iresult = target(dval0, dval1);
1765
          set_register(r0, static_cast<int32_t>(iresult));
1766
          set_register(r1, static_cast<int32_t>(iresult >> 32));
1767
          break;
1768
        }
1769
        case ExternalReference::BUILTIN_FP_FP_CALL: {
1770
          SimulatorRuntimeFPFPCall target =
1771
            reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1772
          dresult = target(dval0, dval1);
1773
          SetFpResult(dresult);
1774
          break;
1775
        }
1776
        case ExternalReference::BUILTIN_FP_CALL: {
1777
          SimulatorRuntimeFPCall target =
1778
            reinterpret_cast<SimulatorRuntimeFPCall>(external);
1779
          dresult = target(dval0);
1780
          SetFpResult(dresult);
1781
          break;
1782
        }
1783
        case ExternalReference::BUILTIN_FP_INT_CALL: {
1784
          SimulatorRuntimeFPIntCall target =
1785
            reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1786
          dresult = target(dval0, ival);
1787
          SetFpResult(dresult);
1788
          break;
1789
        }
1790
        default:
1791
          UNREACHABLE();
1792
          break;
1793
        }
1794
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1795
          switch (redirection->type()) {
1796
          case ExternalReference::BUILTIN_COMPARE_CALL:
1797
            PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1798
            break;
1799
          case ExternalReference::BUILTIN_FP_FP_CALL:
1800
          case ExternalReference::BUILTIN_FP_CALL:
1801
          case ExternalReference::BUILTIN_FP_INT_CALL:
1802
            PrintF("Returned %f\n", dresult);
1803
            break;
1804
          default:
1805
            UNREACHABLE();
1806
            break;
1807
          }
1808
        }
1809
      } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1810
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1811
          PrintF("Call to host function at %p args %08x",
1812
              reinterpret_cast<void*>(external), arg0);
1813
          if (!stack_aligned) {
1814
            PrintF(" with unaligned stack %08x\n", get_register(sp));
1815
          }
1816
          PrintF("\n");
1817
        }
1818
        CHECK(stack_aligned);
1819
        SimulatorRuntimeDirectApiCall target =
1820
            reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1821
        target(arg0);
1822
      } else if (
1823
          redirection->type() == ExternalReference::PROFILING_API_CALL) {
1824
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1825
          PrintF("Call to host function at %p args %08x %08x",
1826
              reinterpret_cast<void*>(external), arg0, arg1);
1827
          if (!stack_aligned) {
1828
            PrintF(" with unaligned stack %08x\n", get_register(sp));
1829
          }
1830
          PrintF("\n");
1831
        }
1832
        CHECK(stack_aligned);
1833
        SimulatorRuntimeProfilingApiCall target =
1834
            reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1835
        target(arg0, arg1);
1836
      } else if (
1837
          redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1838
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1839
          PrintF("Call to host function at %p args %08x %08x",
1840
              reinterpret_cast<void*>(external), arg0, arg1);
1841
          if (!stack_aligned) {
1842
            PrintF(" with unaligned stack %08x\n", get_register(sp));
1843
          }
1844
          PrintF("\n");
1845
        }
1846
        CHECK(stack_aligned);
1847
        SimulatorRuntimeDirectGetterCall target =
1848
            reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1849
        target(arg0, arg1);
1850
      } else if (
1851
          redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1852
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1853
          PrintF("Call to host function at %p args %08x %08x %08x",
1854
              reinterpret_cast<void*>(external), arg0, arg1, arg2);
1855
          if (!stack_aligned) {
1856
            PrintF(" with unaligned stack %08x\n", get_register(sp));
1857
          }
1858
          PrintF("\n");
1859
        }
1860
        CHECK(stack_aligned);
1861
        SimulatorRuntimeProfilingGetterCall target =
1862
            reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
1863
                external);
1864
        target(arg0, arg1, arg2);
1865
      } else {
1866
        // builtin call.
1867
        ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1868
        SimulatorRuntimeCall target =
1869
            reinterpret_cast<SimulatorRuntimeCall>(external);
1870
        if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1871
          PrintF(
1872
              "Call to host function at %p "
1873
              "args %08x, %08x, %08x, %08x, %08x, %08x",
1874
              FUNCTION_ADDR(target),
1875
              arg0,
1876
              arg1,
1877
              arg2,
1878
              arg3,
1879
              arg4,
1880
              arg5);
1881
          if (!stack_aligned) {
1882
            PrintF(" with unaligned stack %08x\n", get_register(sp));
1883
          }
1884
          PrintF("\n");
1885
        }
1886
        CHECK(stack_aligned);
1887
        int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1888
        int32_t lo_res = static_cast<int32_t>(result);
1889
        int32_t hi_res = static_cast<int32_t>(result >> 32);
1890
        if (::v8::internal::FLAG_trace_sim) {
1891
          PrintF("Returned %08x\n", lo_res);
1892
        }
1893
        set_register(r0, lo_res);
1894
        set_register(r1, hi_res);
1895
      }
1896
      set_register(lr, saved_lr);
1897
      set_pc(get_register(lr));
1898
      break;
1899
    }
1900
    case kBreakpoint: {
1901
      ArmDebugger dbg(this);
1902
      dbg.Debug();
1903
      break;
1904
    }
1905
    // stop uses all codes greater than 1 << 23.
1906
    default: {
1907
      if (svc >= (1 << 23)) {
1908
        uint32_t code = svc & kStopCodeMask;
1909
        if (isWatchedStop(code)) {
1910
          IncreaseStopCounter(code);
1911
        }
1912
        // Stop if it is enabled, otherwise go on jumping over the stop
1913
        // and the message address.
1914
        if (isEnabledStop(code)) {
1915
          ArmDebugger dbg(this);
1916
          dbg.Stop(instr);
1917
        } else {
1918
          set_pc(get_pc() + 2 * Instruction::kInstrSize);
1919
        }
1920
      } else {
1921
        // This is not a valid svc code.
1922
        UNREACHABLE();
1923
        break;
1924
      }
1925
    }
1926
  }
1927
}
1928

    
1929

    
1930
double Simulator::canonicalizeNaN(double value) {
1931
  return (FPSCR_default_NaN_mode_ && std::isnan(value)) ?
1932
    FixedDoubleArray::canonical_not_the_hole_nan_as_double() : value;
1933
}
1934

    
1935

    
1936
// Stop helper functions.
1937
bool Simulator::isStopInstruction(Instruction* instr) {
1938
  return (instr->Bits(27, 24) == 0xF) && (instr->SvcValue() >= kStopCode);
1939
}
1940

    
1941

    
1942
bool Simulator::isWatchedStop(uint32_t code) {
1943
  ASSERT(code <= kMaxStopCode);
1944
  return code < kNumOfWatchedStops;
1945
}
1946

    
1947

    
1948
bool Simulator::isEnabledStop(uint32_t code) {
1949
  ASSERT(code <= kMaxStopCode);
1950
  // Unwatched stops are always enabled.
1951
  return !isWatchedStop(code) ||
1952
    !(watched_stops_[code].count & kStopDisabledBit);
1953
}
1954

    
1955

    
1956
void Simulator::EnableStop(uint32_t code) {
1957
  ASSERT(isWatchedStop(code));
1958
  if (!isEnabledStop(code)) {
1959
    watched_stops_[code].count &= ~kStopDisabledBit;
1960
  }
1961
}
1962

    
1963

    
1964
void Simulator::DisableStop(uint32_t code) {
1965
  ASSERT(isWatchedStop(code));
1966
  if (isEnabledStop(code)) {
1967
    watched_stops_[code].count |= kStopDisabledBit;
1968
  }
1969
}
1970

    
1971

    
1972
void Simulator::IncreaseStopCounter(uint32_t code) {
1973
  ASSERT(code <= kMaxStopCode);
1974
  ASSERT(isWatchedStop(code));
1975
  if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1976
    PrintF("Stop counter for code %i has overflowed.\n"
1977
           "Enabling this code and reseting the counter to 0.\n", code);
1978
    watched_stops_[code].count = 0;
1979
    EnableStop(code);
1980
  } else {
1981
    watched_stops_[code].count++;
1982
  }
1983
}
1984

    
1985

    
1986
// Print a stop status.
1987
void Simulator::PrintStopInfo(uint32_t code) {
1988
  ASSERT(code <= kMaxStopCode);
1989
  if (!isWatchedStop(code)) {
1990
    PrintF("Stop not watched.");
1991
  } else {
1992
    const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
1993
    int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1994
    // Don't print the state of unused breakpoints.
1995
    if (count != 0) {
1996
      if (watched_stops_[code].desc) {
1997
        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1998
               code, code, state, count, watched_stops_[code].desc);
1999
      } else {
2000
        PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
2001
               code, code, state, count);
2002
      }
2003
    }
2004
  }
2005
}
2006

    
2007

    
2008
// Handle execution based on instruction types.
2009

    
2010
// Instruction types 0 and 1 are both rolled into one function because they
2011
// only differ in the handling of the shifter_operand.
2012
void Simulator::DecodeType01(Instruction* instr) {
2013
  int type = instr->TypeValue();
2014
  if ((type == 0) && instr->IsSpecialType0()) {
2015
    // multiply instruction or extra loads and stores
2016
    if (instr->Bits(7, 4) == 9) {
2017
      if (instr->Bit(24) == 0) {
2018
        // Raw field decoding here. Multiply instructions have their Rd in
2019
        // funny places.
2020
        int rn = instr->RnValue();
2021
        int rm = instr->RmValue();
2022
        int rs = instr->RsValue();
2023
        int32_t rs_val = get_register(rs);
2024
        int32_t rm_val = get_register(rm);
2025
        if (instr->Bit(23) == 0) {
2026
          if (instr->Bit(21) == 0) {
2027
            // The MUL instruction description (A 4.1.33) refers to Rd as being
2028
            // the destination for the operation, but it confusingly uses the
2029
            // Rn field to encode it.
2030
            // Format(instr, "mul'cond's 'rn, 'rm, 'rs");
2031
            int rd = rn;  // Remap the rn field to the Rd register.
2032
            int32_t alu_out = rm_val * rs_val;
2033
            set_register(rd, alu_out);
2034
            if (instr->HasS()) {
2035
              SetNZFlags(alu_out);
2036
            }
2037
          } else {
2038
            int rd = instr->RdValue();
2039
            int32_t acc_value = get_register(rd);
2040
            if (instr->Bit(22) == 0) {
2041
              // The MLA instruction description (A 4.1.28) refers to the order
2042
              // of registers as "Rd, Rm, Rs, Rn". But confusingly it uses the
2043
              // Rn field to encode the Rd register and the Rd field to encode
2044
              // the Rn register.
2045
              // Format(instr, "mla'cond's 'rn, 'rm, 'rs, 'rd");
2046
              int32_t mul_out = rm_val * rs_val;
2047
              int32_t result = acc_value + mul_out;
2048
              set_register(rn, result);
2049
            } else {
2050
              // Format(instr, "mls'cond's 'rn, 'rm, 'rs, 'rd");
2051
              int32_t mul_out = rm_val * rs_val;
2052
              int32_t result = acc_value - mul_out;
2053
              set_register(rn, result);
2054
            }
2055
          }
2056
        } else {
2057
          // The signed/long multiply instructions use the terms RdHi and RdLo
2058
          // when referring to the target registers. They are mapped to the Rn
2059
          // and Rd fields as follows:
2060
          // RdLo == Rd
2061
          // RdHi == Rn (This is confusingly stored in variable rd here
2062
          //             because the mul instruction from above uses the
2063
          //             Rn field to encode the Rd register. Good luck figuring
2064
          //             this out without reading the ARM instruction manual
2065
          //             at a very detailed level.)
2066
          // Format(instr, "'um'al'cond's 'rd, 'rn, 'rs, 'rm");
2067
          int rd_hi = rn;  // Remap the rn field to the RdHi register.
2068
          int rd_lo = instr->RdValue();
2069
          int32_t hi_res = 0;
2070
          int32_t lo_res = 0;
2071
          if (instr->Bit(22) == 1) {
2072
            int64_t left_op  = static_cast<int32_t>(rm_val);
2073
            int64_t right_op = static_cast<int32_t>(rs_val);
2074
            uint64_t result = left_op * right_op;
2075
            hi_res = static_cast<int32_t>(result >> 32);
2076
            lo_res = static_cast<int32_t>(result & 0xffffffff);
2077
          } else {
2078
            // unsigned multiply
2079
            uint64_t left_op  = static_cast<uint32_t>(rm_val);
2080
            uint64_t right_op = static_cast<uint32_t>(rs_val);
2081
            uint64_t result = left_op * right_op;
2082
            hi_res = static_cast<int32_t>(result >> 32);
2083
            lo_res = static_cast<int32_t>(result & 0xffffffff);
2084
          }
2085
          set_register(rd_lo, lo_res);
2086
          set_register(rd_hi, hi_res);
2087
          if (instr->HasS()) {
2088
            UNIMPLEMENTED();
2089
          }
2090
        }
2091
      } else {
2092
        UNIMPLEMENTED();  // Not used by V8.
2093
      }
2094
    } else {
2095
      // extra load/store instructions
2096
      int rd = instr->RdValue();
2097
      int rn = instr->RnValue();
2098
      int32_t rn_val = get_register(rn);
2099
      int32_t addr = 0;
2100
      if (instr->Bit(22) == 0) {
2101
        int rm = instr->RmValue();
2102
        int32_t rm_val = get_register(rm);
2103
        switch (instr->PUField()) {
2104
          case da_x: {
2105
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
2106
            ASSERT(!instr->HasW());
2107
            addr = rn_val;
2108
            rn_val -= rm_val;
2109
            set_register(rn, rn_val);
2110
            break;
2111
          }
2112
          case ia_x: {
2113
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
2114
            ASSERT(!instr->HasW());
2115
            addr = rn_val;
2116
            rn_val += rm_val;
2117
            set_register(rn, rn_val);
2118
            break;
2119
          }
2120
          case db_x: {
2121
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
2122
            rn_val -= rm_val;
2123
            addr = rn_val;
2124
            if (instr->HasW()) {
2125
              set_register(rn, rn_val);
2126
            }
2127
            break;
2128
          }
2129
          case ib_x: {
2130
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
2131
            rn_val += rm_val;
2132
            addr = rn_val;
2133
            if (instr->HasW()) {
2134
              set_register(rn, rn_val);
2135
            }
2136
            break;
2137
          }
2138
          default: {
2139
            // The PU field is a 2-bit field.
2140
            UNREACHABLE();
2141
            break;
2142
          }
2143
        }
2144
      } else {
2145
        int32_t imm_val = (instr->ImmedHValue() << 4) | instr->ImmedLValue();
2146
        switch (instr->PUField()) {
2147
          case da_x: {
2148
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
2149
            ASSERT(!instr->HasW());
2150
            addr = rn_val;
2151
            rn_val -= imm_val;
2152
            set_register(rn, rn_val);
2153
            break;
2154
          }
2155
          case ia_x: {
2156
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
2157
            ASSERT(!instr->HasW());
2158
            addr = rn_val;
2159
            rn_val += imm_val;
2160
            set_register(rn, rn_val);
2161
            break;
2162
          }
2163
          case db_x: {
2164
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
2165
            rn_val -= imm_val;
2166
            addr = rn_val;
2167
            if (instr->HasW()) {
2168
              set_register(rn, rn_val);
2169
            }
2170
            break;
2171
          }
2172
          case ib_x: {
2173
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
2174
            rn_val += imm_val;
2175
            addr = rn_val;
2176
            if (instr->HasW()) {
2177
              set_register(rn, rn_val);
2178
            }
2179
            break;
2180
          }
2181
          default: {
2182
            // The PU field is a 2-bit field.
2183
            UNREACHABLE();
2184
            break;
2185
          }
2186
        }
2187
      }
2188
      if (((instr->Bits(7, 4) & 0xd) == 0xd) && (instr->Bit(20) == 0)) {
2189
        ASSERT((rd % 2) == 0);
2190
        if (instr->HasH()) {
2191
          // The strd instruction.
2192
          int32_t value1 = get_register(rd);
2193
          int32_t value2 = get_register(rd+1);
2194
          WriteDW(addr, value1, value2);
2195
        } else {
2196
          // The ldrd instruction.
2197
          int* rn_data = ReadDW(addr);
2198
          set_dw_register(rd, rn_data);
2199
        }
2200
      } else if (instr->HasH()) {
2201
        if (instr->HasSign()) {
2202
          if (instr->HasL()) {
2203
            int16_t val = ReadH(addr, instr);
2204
            set_register(rd, val);
2205
          } else {
2206
            int16_t val = get_register(rd);
2207
            WriteH(addr, val, instr);
2208
          }
2209
        } else {
2210
          if (instr->HasL()) {
2211
            uint16_t val = ReadHU(addr, instr);
2212
            set_register(rd, val);
2213
          } else {
2214
            uint16_t val = get_register(rd);
2215
            WriteH(addr, val, instr);
2216
          }
2217
        }
2218
      } else {
2219
        // signed byte loads
2220
        ASSERT(instr->HasSign());
2221
        ASSERT(instr->HasL());
2222
        int8_t val = ReadB(addr);
2223
        set_register(rd, val);
2224
      }
2225
      return;
2226
    }
2227
  } else if ((type == 0) && instr->IsMiscType0()) {
2228
    if (instr->Bits(22, 21) == 1) {
2229
      int rm = instr->RmValue();
2230
      switch (instr->BitField(7, 4)) {
2231
        case BX:
2232
          set_pc(get_register(rm));
2233
          break;
2234
        case BLX: {
2235
          uint32_t old_pc = get_pc();
2236
          set_pc(get_register(rm));
2237
          set_register(lr, old_pc + Instruction::kInstrSize);
2238
          break;
2239
        }
2240
        case BKPT: {
2241
          ArmDebugger dbg(this);
2242
          PrintF("Simulator hit BKPT.\n");
2243
          dbg.Debug();
2244
          break;
2245
        }
2246
        default:
2247
          UNIMPLEMENTED();
2248
      }
2249
    } else if (instr->Bits(22, 21) == 3) {
2250
      int rm = instr->RmValue();
2251
      int rd = instr->RdValue();
2252
      switch (instr->BitField(7, 4)) {
2253
        case CLZ: {
2254
          uint32_t bits = get_register(rm);
2255
          int leading_zeros = 0;
2256
          if (bits == 0) {
2257
            leading_zeros = 32;
2258
          } else {
2259
            while ((bits & 0x80000000u) == 0) {
2260
              bits <<= 1;
2261
              leading_zeros++;
2262
            }
2263
          }
2264
          set_register(rd, leading_zeros);
2265
          break;
2266
        }
2267
        default:
2268
          UNIMPLEMENTED();
2269
      }
2270
    } else {
2271
      PrintF("%08x\n", instr->InstructionBits());
2272
      UNIMPLEMENTED();
2273
    }
2274
  } else if ((type == 1) && instr->IsNopType1()) {
2275
    // NOP.
2276
  } else {
2277
    int rd = instr->RdValue();
2278
    int rn = instr->RnValue();
2279
    int32_t rn_val = get_register(rn);
2280
    int32_t shifter_operand = 0;
2281
    bool shifter_carry_out = 0;
2282
    if (type == 0) {
2283
      shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2284
    } else {
2285
      ASSERT(instr->TypeValue() == 1);
2286
      shifter_operand = GetImm(instr, &shifter_carry_out);
2287
    }
2288
    int32_t alu_out;
2289

    
2290
    switch (instr->OpcodeField()) {
2291
      case AND: {
2292
        // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2293
        // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2294
        alu_out = rn_val & shifter_operand;
2295
        set_register(rd, alu_out);
2296
        if (instr->HasS()) {
2297
          SetNZFlags(alu_out);
2298
          SetCFlag(shifter_carry_out);
2299
        }
2300
        break;
2301
      }
2302

    
2303
      case EOR: {
2304
        // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
2305
        // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
2306
        alu_out = rn_val ^ shifter_operand;
2307
        set_register(rd, alu_out);
2308
        if (instr->HasS()) {
2309
          SetNZFlags(alu_out);
2310
          SetCFlag(shifter_carry_out);
2311
        }
2312
        break;
2313
      }
2314

    
2315
      case SUB: {
2316
        // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2317
        // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2318
        alu_out = rn_val - shifter_operand;
2319
        set_register(rd, alu_out);
2320
        if (instr->HasS()) {
2321
          SetNZFlags(alu_out);
2322
          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2323
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2324
        }
2325
        break;
2326
      }
2327

    
2328
      case RSB: {
2329
        // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2330
        // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2331
        alu_out = shifter_operand - rn_val;
2332
        set_register(rd, alu_out);
2333
        if (instr->HasS()) {
2334
          SetNZFlags(alu_out);
2335
          SetCFlag(!BorrowFrom(shifter_operand, rn_val));
2336
          SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
2337
        }
2338
        break;
2339
      }
2340

    
2341
      case ADD: {
2342
        // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2343
        // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2344
        alu_out = rn_val + shifter_operand;
2345
        set_register(rd, alu_out);
2346
        if (instr->HasS()) {
2347
          SetNZFlags(alu_out);
2348
          SetCFlag(CarryFrom(rn_val, shifter_operand));
2349
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2350
        }
2351
        break;
2352
      }
2353

    
2354
      case ADC: {
2355
        // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2356
        // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2357
        alu_out = rn_val + shifter_operand + GetCarry();
2358
        set_register(rd, alu_out);
2359
        if (instr->HasS()) {
2360
          SetNZFlags(alu_out);
2361
          SetCFlag(CarryFrom(rn_val, shifter_operand, GetCarry()));
2362
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2363
        }
2364
        break;
2365
      }
2366

    
2367
      case SBC: {
2368
        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2369
        Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2370
        break;
2371
      }
2372

    
2373
      case RSC: {
2374
        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2375
        Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2376
        break;
2377
      }
2378

    
2379
      case TST: {
2380
        if (instr->HasS()) {
2381
          // Format(instr, "tst'cond 'rn, 'shift_rm");
2382
          // Format(instr, "tst'cond 'rn, 'imm");
2383
          alu_out = rn_val & shifter_operand;
2384
          SetNZFlags(alu_out);
2385
          SetCFlag(shifter_carry_out);
2386
        } else {
2387
          // Format(instr, "movw'cond 'rd, 'imm").
2388
          alu_out = instr->ImmedMovwMovtValue();
2389
          set_register(rd, alu_out);
2390
        }
2391
        break;
2392
      }
2393

    
2394
      case TEQ: {
2395
        if (instr->HasS()) {
2396
          // Format(instr, "teq'cond 'rn, 'shift_rm");
2397
          // Format(instr, "teq'cond 'rn, 'imm");
2398
          alu_out = rn_val ^ shifter_operand;
2399
          SetNZFlags(alu_out);
2400
          SetCFlag(shifter_carry_out);
2401
        } else {
2402
          // Other instructions matching this pattern are handled in the
2403
          // miscellaneous instructions part above.
2404
          UNREACHABLE();
2405
        }
2406
        break;
2407
      }
2408

    
2409
      case CMP: {
2410
        if (instr->HasS()) {
2411
          // Format(instr, "cmp'cond 'rn, 'shift_rm");
2412
          // Format(instr, "cmp'cond 'rn, 'imm");
2413
          alu_out = rn_val - shifter_operand;
2414
          SetNZFlags(alu_out);
2415
          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
2416
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
2417
        } else {
2418
          // Format(instr, "movt'cond 'rd, 'imm").
2419
          alu_out = (get_register(rd) & 0xffff) |
2420
              (instr->ImmedMovwMovtValue() << 16);
2421
          set_register(rd, alu_out);
2422
        }
2423
        break;
2424
      }
2425

    
2426
      case CMN: {
2427
        if (instr->HasS()) {
2428
          // Format(instr, "cmn'cond 'rn, 'shift_rm");
2429
          // Format(instr, "cmn'cond 'rn, 'imm");
2430
          alu_out = rn_val + shifter_operand;
2431
          SetNZFlags(alu_out);
2432
          SetCFlag(CarryFrom(rn_val, shifter_operand));
2433
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
2434
        } else {
2435
          // Other instructions matching this pattern are handled in the
2436
          // miscellaneous instructions part above.
2437
          UNREACHABLE();
2438
        }
2439
        break;
2440
      }
2441

    
2442
      case ORR: {
2443
        // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2444
        // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2445
        alu_out = rn_val | shifter_operand;
2446
        set_register(rd, alu_out);
2447
        if (instr->HasS()) {
2448
          SetNZFlags(alu_out);
2449
          SetCFlag(shifter_carry_out);
2450
        }
2451
        break;
2452
      }
2453

    
2454
      case MOV: {
2455
        // Format(instr, "mov'cond's 'rd, 'shift_rm");
2456
        // Format(instr, "mov'cond's 'rd, 'imm");
2457
        alu_out = shifter_operand;
2458
        set_register(rd, alu_out);
2459
        if (instr->HasS()) {
2460
          SetNZFlags(alu_out);
2461
          SetCFlag(shifter_carry_out);
2462
        }
2463
        break;
2464
      }
2465

    
2466
      case BIC: {
2467
        // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
2468
        // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
2469
        alu_out = rn_val & ~shifter_operand;
2470
        set_register(rd, alu_out);
2471
        if (instr->HasS()) {
2472
          SetNZFlags(alu_out);
2473
          SetCFlag(shifter_carry_out);
2474
        }
2475
        break;
2476
      }
2477

    
2478
      case MVN: {
2479
        // Format(instr, "mvn'cond's 'rd, 'shift_rm");
2480
        // Format(instr, "mvn'cond's 'rd, 'imm");
2481
        alu_out = ~shifter_operand;
2482
        set_register(rd, alu_out);
2483
        if (instr->HasS()) {
2484
          SetNZFlags(alu_out);
2485
          SetCFlag(shifter_carry_out);
2486
        }
2487
        break;
2488
      }
2489

    
2490
      default: {
2491
        UNREACHABLE();
2492
        break;
2493
      }
2494
    }
2495
  }
2496
}
2497

    
2498

    
2499
void Simulator::DecodeType2(Instruction* instr) {
2500
  int rd = instr->RdValue();
2501
  int rn = instr->RnValue();
2502
  int32_t rn_val = get_register(rn);
2503
  int32_t im_val = instr->Offset12Value();
2504
  int32_t addr = 0;
2505
  switch (instr->PUField()) {
2506
    case da_x: {
2507
      // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
2508
      ASSERT(!instr->HasW());
2509
      addr = rn_val;
2510
      rn_val -= im_val;
2511
      set_register(rn, rn_val);
2512
      break;
2513
    }
2514
    case ia_x: {
2515
      // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
2516
      ASSERT(!instr->HasW());
2517
      addr = rn_val;
2518
      rn_val += im_val;
2519
      set_register(rn, rn_val);
2520
      break;
2521
    }
2522
    case db_x: {
2523
      // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
2524
      rn_val -= im_val;
2525
      addr = rn_val;
2526
      if (instr->HasW()) {
2527
        set_register(rn, rn_val);
2528
      }
2529
      break;
2530
    }
2531
    case ib_x: {
2532
      // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
2533
      rn_val += im_val;
2534
      addr = rn_val;
2535
      if (instr->HasW()) {
2536
        set_register(rn, rn_val);
2537
      }
2538
      break;
2539
    }
2540
    default: {
2541
      UNREACHABLE();
2542
      break;
2543
    }
2544
  }
2545
  if (instr->HasB()) {
2546
    if (instr->HasL()) {
2547
      byte val = ReadBU(addr);
2548
      set_register(rd, val);
2549
    } else {
2550
      byte val = get_register(rd);
2551
      WriteB(addr, val);
2552
    }
2553
  } else {
2554
    if (instr->HasL()) {
2555
      set_register(rd, ReadW(addr, instr));
2556
    } else {
2557
      WriteW(addr, get_register(rd), instr);
2558
    }
2559
  }
2560
}
2561

    
2562

    
2563
void Simulator::DecodeType3(Instruction* instr) {
2564
  int rd = instr->RdValue();
2565
  int rn = instr->RnValue();
2566
  int32_t rn_val = get_register(rn);
2567
  bool shifter_carry_out = 0;
2568
  int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2569
  int32_t addr = 0;
2570
  switch (instr->PUField()) {
2571
    case da_x: {
2572
      ASSERT(!instr->HasW());
2573
      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
2574
      UNIMPLEMENTED();
2575
      break;
2576
    }
2577
    case ia_x: {
2578
      if (instr->Bit(4) == 0) {
2579
        // Memop.
2580
      } else {
2581
        if (instr->Bit(5) == 0) {
2582
          switch (instr->Bits(22, 21)) {
2583
            case 0:
2584
              if (instr->Bit(20) == 0) {
2585
                if (instr->Bit(6) == 0) {
2586
                  // Pkhbt.
2587
                  uint32_t rn_val = get_register(rn);
2588
                  uint32_t rm_val = get_register(instr->RmValue());
2589
                  int32_t shift = instr->Bits(11, 7);
2590
                  rm_val <<= shift;
2591
                  set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
2592
                } else {
2593
                  // Pkhtb.
2594
                  uint32_t rn_val = get_register(rn);
2595
                  int32_t rm_val = get_register(instr->RmValue());
2596
                  int32_t shift = instr->Bits(11, 7);
2597
                  if (shift == 0) {
2598
                    shift = 32;
2599
                  }
2600
                  rm_val >>= shift;
2601
                  set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
2602
                }
2603
              } else {
2604
                UNIMPLEMENTED();
2605
              }
2606
              break;
2607
            case 1:
2608
              UNIMPLEMENTED();
2609
              break;
2610
            case 2:
2611
              UNIMPLEMENTED();
2612
              break;
2613
            case 3: {
2614
              // Usat.
2615
              int32_t sat_pos = instr->Bits(20, 16);
2616
              int32_t sat_val = (1 << sat_pos) - 1;
2617
              int32_t shift = instr->Bits(11, 7);
2618
              int32_t shift_type = instr->Bit(6);
2619
              int32_t rm_val = get_register(instr->RmValue());
2620
              if (shift_type == 0) {  // LSL
2621
                rm_val <<= shift;
2622
              } else {  // ASR
2623
                rm_val >>= shift;
2624
              }
2625
              // If saturation occurs, the Q flag should be set in the CPSR.
2626
              // There is no Q flag yet, and no instruction (MRS) to read the
2627
              // CPSR directly.
2628
              if (rm_val > sat_val) {
2629
                rm_val = sat_val;
2630
              } else if (rm_val < 0) {
2631
                rm_val = 0;
2632
              }
2633
              set_register(rd, rm_val);
2634
              break;
2635
            }
2636
          }
2637
        } else {
2638
          switch (instr->Bits(22, 21)) {
2639
            case 0:
2640
              UNIMPLEMENTED();
2641
              break;
2642
            case 1:
2643
              UNIMPLEMENTED();
2644
              break;
2645
            case 2:
2646
              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2647
                if (instr->Bits(19, 16) == 0xF) {
2648
                  // Uxtb16.
2649
                  uint32_t rm_val = get_register(instr->RmValue());
2650
                  int32_t rotate = instr->Bits(11, 10);
2651
                  switch (rotate) {
2652
                    case 0:
2653
                      break;
2654
                    case 1:
2655
                      rm_val = (rm_val >> 8) | (rm_val << 24);
2656
                      break;
2657
                    case 2:
2658
                      rm_val = (rm_val >> 16) | (rm_val << 16);
2659
                      break;
2660
                    case 3:
2661
                      rm_val = (rm_val >> 24) | (rm_val << 8);
2662
                      break;
2663
                  }
2664
                  set_register(rd,
2665
                               (rm_val & 0xFF) | (rm_val & 0xFF0000));
2666
                } else {
2667
                  UNIMPLEMENTED();
2668
                }
2669
              } else {
2670
                UNIMPLEMENTED();
2671
              }
2672
              break;
2673
            case 3:
2674
              if ((instr->Bit(20) == 0) && (instr->Bits(9, 6) == 1)) {
2675
                if (instr->Bits(19, 16) == 0xF) {
2676
                  // Uxtb.
2677
                  uint32_t rm_val = get_register(instr->RmValue());
2678
                  int32_t rotate = instr->Bits(11, 10);
2679
                  switch (rotate) {
2680
                    case 0:
2681
                      break;
2682
                    case 1:
2683
                      rm_val = (rm_val >> 8) | (rm_val << 24);
2684
                      break;
2685
                    case 2:
2686
                      rm_val = (rm_val >> 16) | (rm_val << 16);
2687
                      break;
2688
                    case 3:
2689
                      rm_val = (rm_val >> 24) | (rm_val << 8);
2690
                      break;
2691
                  }
2692
                  set_register(rd, (rm_val & 0xFF));
2693
                } else {
2694
                  // Uxtab.
2695
                  uint32_t rn_val = get_register(rn);
2696
                  uint32_t rm_val = get_register(instr->RmValue());
2697
                  int32_t rotate = instr->Bits(11, 10);
2698
                  switch (rotate) {
2699
                    case 0:
2700
                      break;
2701
                    case 1:
2702
                      rm_val = (rm_val >> 8) | (rm_val << 24);
2703
                      break;
2704
                    case 2:
2705
                      rm_val = (rm_val >> 16) | (rm_val << 16);
2706
                      break;
2707
                    case 3:
2708
                      rm_val = (rm_val >> 24) | (rm_val << 8);
2709
                      break;
2710
                  }
2711
                  set_register(rd, rn_val + (rm_val & 0xFF));
2712
                }
2713
              } else {
2714
                UNIMPLEMENTED();
2715
              }
2716
              break;
2717
          }
2718
        }
2719
        return;
2720
      }
2721
      break;
2722
    }
2723
    case db_x: {
2724
      if (FLAG_enable_sudiv) {
2725
        if (!instr->HasW()) {
2726
          if (instr->Bits(5, 4) == 0x1) {
2727
             if ((instr->Bit(22) == 0x0) && (instr->Bit(20) == 0x1)) {
2728
               // sdiv (in V8 notation matching ARM ISA format) rn = rm/rs
2729
               // Format(instr, "'sdiv'cond'b 'rn, 'rm, 'rs);
2730
               int rm = instr->RmValue();
2731
               int32_t rm_val = get_register(rm);
2732
               int rs = instr->RsValue();
2733
               int32_t rs_val = get_register(rs);
2734
               int32_t ret_val = 0;
2735
               ASSERT(rs_val != 0);
2736
               ret_val = rm_val/rs_val;
2737
               set_register(rn, ret_val);
2738
               return;
2739
             }
2740
           }
2741
         }
2742
       }
2743
      // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
2744
      addr = rn_val - shifter_operand;
2745
      if (instr->HasW()) {
2746
        set_register(rn, addr);
2747
      }
2748
      break;
2749
    }
2750
    case ib_x: {
2751
      if (instr->HasW() && (instr->Bits(6, 4) == 0x5)) {
2752
        uint32_t widthminus1 = static_cast<uint32_t>(instr->Bits(20, 16));
2753
        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2754
        uint32_t msbit = widthminus1 + lsbit;
2755
        if (msbit <= 31) {
2756
          if (instr->Bit(22)) {
2757
            // ubfx - unsigned bitfield extract.
2758
            uint32_t rm_val =
2759
                static_cast<uint32_t>(get_register(instr->RmValue()));
2760
            uint32_t extr_val = rm_val << (31 - msbit);
2761
            extr_val = extr_val >> (31 - widthminus1);
2762
            set_register(instr->RdValue(), extr_val);
2763
          } else {
2764
            // sbfx - signed bitfield extract.
2765
            int32_t rm_val = get_register(instr->RmValue());
2766
            int32_t extr_val = rm_val << (31 - msbit);
2767
            extr_val = extr_val >> (31 - widthminus1);
2768
            set_register(instr->RdValue(), extr_val);
2769
          }
2770
        } else {
2771
          UNREACHABLE();
2772
        }
2773
        return;
2774
      } else if (!instr->HasW() && (instr->Bits(6, 4) == 0x1)) {
2775
        uint32_t lsbit = static_cast<uint32_t>(instr->Bits(11, 7));
2776
        uint32_t msbit = static_cast<uint32_t>(instr->Bits(20, 16));
2777
        if (msbit >= lsbit) {
2778
          // bfc or bfi - bitfield clear/insert.
2779
          uint32_t rd_val =
2780
              static_cast<uint32_t>(get_register(instr->RdValue()));
2781
          uint32_t bitcount = msbit - lsbit + 1;
2782
          uint32_t mask = (1 << bitcount) - 1;
2783
          rd_val &= ~(mask << lsbit);
2784
          if (instr->RmValue() != 15) {
2785
            // bfi - bitfield insert.
2786
            uint32_t rm_val =
2787
                static_cast<uint32_t>(get_register(instr->RmValue()));
2788
            rm_val &= mask;
2789
            rd_val |= rm_val << lsbit;
2790
          }
2791
          set_register(instr->RdValue(), rd_val);
2792
        } else {
2793
          UNREACHABLE();
2794
        }
2795
        return;
2796
      } else {
2797
        // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
2798
        addr = rn_val + shifter_operand;
2799
        if (instr->HasW()) {
2800
          set_register(rn, addr);
2801
        }
2802
      }
2803
      break;
2804
    }
2805
    default: {
2806
      UNREACHABLE();
2807
      break;
2808
    }
2809
  }
2810
  if (instr->HasB()) {
2811
    if (instr->HasL()) {
2812
      uint8_t byte = ReadB(addr);
2813
      set_register(rd, byte);
2814
    } else {
2815
      uint8_t byte = get_register(rd);
2816
      WriteB(addr, byte);
2817
    }
2818
  } else {
2819
    if (instr->HasL()) {
2820
      set_register(rd, ReadW(addr, instr));
2821
    } else {
2822
      WriteW(addr, get_register(rd), instr);
2823
    }
2824
  }
2825
}
2826

    
2827

    
2828
void Simulator::DecodeType4(Instruction* instr) {
2829
  ASSERT(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
2830
  if (instr->HasL()) {
2831
    // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
2832
    HandleRList(instr, true);
2833
  } else {
2834
    // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
2835
    HandleRList(instr, false);
2836
  }
2837
}
2838

    
2839

    
2840
void Simulator::DecodeType5(Instruction* instr) {
2841
  // Format(instr, "b'l'cond 'target");
2842
  int off = (instr->SImmed24Value() << 2);
2843
  intptr_t pc_address = get_pc();
2844
  if (instr->HasLink()) {
2845
    set_register(lr, pc_address + Instruction::kInstrSize);
2846
  }
2847
  int pc_reg = get_register(pc);
2848
  set_pc(pc_reg + off);
2849
}
2850

    
2851

    
2852
void Simulator::DecodeType6(Instruction* instr) {
2853
  DecodeType6CoprocessorIns(instr);
2854
}
2855

    
2856

    
2857
void Simulator::DecodeType7(Instruction* instr) {
2858
  if (instr->Bit(24) == 1) {
2859
    SoftwareInterrupt(instr);
2860
  } else {
2861
    DecodeTypeVFP(instr);
2862
  }
2863
}
2864

    
2865

    
2866
// void Simulator::DecodeTypeVFP(Instruction* instr)
2867
// The Following ARMv7 VFPv instructions are currently supported.
2868
// vmov :Sn = Rt
2869
// vmov :Rt = Sn
2870
// vcvt: Dd = Sm
2871
// vcvt: Sd = Dm
2872
// vcvt.f64.s32 Dd, Dd, #<fbits>
2873
// Dd = vabs(Dm)
2874
// Dd = vneg(Dm)
2875
// Dd = vadd(Dn, Dm)
2876
// Dd = vsub(Dn, Dm)
2877
// Dd = vmul(Dn, Dm)
2878
// Dd = vdiv(Dn, Dm)
2879
// vcmp(Dd, Dm)
2880
// vmrs
2881
// Dd = vsqrt(Dm)
2882
void Simulator::DecodeTypeVFP(Instruction* instr) {
2883
  ASSERT((instr->TypeValue() == 7) && (instr->Bit(24) == 0x0) );
2884
  ASSERT(instr->Bits(11, 9) == 0x5);
2885

    
2886
  // Obtain double precision register codes.
2887
  int vm = instr->VFPMRegValue(kDoublePrecision);
2888
  int vd = instr->VFPDRegValue(kDoublePrecision);
2889
  int vn = instr->VFPNRegValue(kDoublePrecision);
2890

    
2891
  if (instr->Bit(4) == 0) {
2892
    if (instr->Opc1Value() == 0x7) {
2893
      // Other data processing instructions
2894
      if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x1)) {
2895
        // vmov register to register.
2896
        if (instr->SzValue() == 0x1) {
2897
          int m = instr->VFPMRegValue(kDoublePrecision);
2898
          int d = instr->VFPDRegValue(kDoublePrecision);
2899
          set_d_register_from_double(d, get_double_from_d_register(m));
2900
        } else {
2901
          int m = instr->VFPMRegValue(kSinglePrecision);
2902
          int d = instr->VFPDRegValue(kSinglePrecision);
2903
          set_s_register_from_float(d, get_float_from_s_register(m));
2904
        }
2905
      } else if ((instr->Opc2Value() == 0x0) && (instr->Opc3Value() == 0x3)) {
2906
        // vabs
2907
        double dm_value = get_double_from_d_register(vm);
2908
        double dd_value = fabs(dm_value);
2909
        dd_value = canonicalizeNaN(dd_value);
2910
        set_d_register_from_double(vd, dd_value);
2911
      } else if ((instr->Opc2Value() == 0x1) && (instr->Opc3Value() == 0x1)) {
2912
        // vneg
2913
        double dm_value = get_double_from_d_register(vm);
2914
        double dd_value = -dm_value;
2915
        dd_value = canonicalizeNaN(dd_value);
2916
        set_d_register_from_double(vd, dd_value);
2917
      } else if ((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3)) {
2918
        DecodeVCVTBetweenDoubleAndSingle(instr);
2919
      } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
2920
        DecodeVCVTBetweenFloatingPointAndInteger(instr);
2921
      } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
2922
                 (instr->Bit(8) == 1)) {
2923
        // vcvt.f64.s32 Dd, Dd, #<fbits>
2924
        int fraction_bits = 32 - ((instr->Bit(5) << 4) | instr->Bits(3, 0));
2925
        int fixed_value = get_sinteger_from_s_register(vd * 2);
2926
        double divide = 1 << fraction_bits;
2927
        set_d_register_from_double(vd, fixed_value / divide);
2928
      } else if (((instr->Opc2Value() >> 1) == 0x6) &&
2929
                 (instr->Opc3Value() & 0x1)) {
2930
        DecodeVCVTBetweenFloatingPointAndInteger(instr);
2931
      } else if (((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
2932
                 (instr->Opc3Value() & 0x1)) {
2933
        DecodeVCMP(instr);
2934
      } else if (((instr->Opc2Value() == 0x1)) && (instr->Opc3Value() == 0x3)) {
2935
        // vsqrt
2936
        double dm_value = get_double_from_d_register(vm);
2937
        double dd_value = sqrt(dm_value);
2938
        dd_value = canonicalizeNaN(dd_value);
2939
        set_d_register_from_double(vd, dd_value);
2940
      } else if (instr->Opc3Value() == 0x0) {
2941
        // vmov immediate.
2942
        if (instr->SzValue() == 0x1) {
2943
          set_d_register_from_double(vd, instr->DoubleImmedVmov());
2944
        } else {
2945
          UNREACHABLE();  // Not used by v8.
2946
        }
2947
      } else {
2948
        UNREACHABLE();  // Not used by V8.
2949
      }
2950
    } else if (instr->Opc1Value() == 0x3) {
2951
      if (instr->SzValue() != 0x1) {
2952
        UNREACHABLE();  // Not used by V8.
2953
      }
2954

    
2955
      if (instr->Opc3Value() & 0x1) {
2956
        // vsub
2957
        double dn_value = get_double_from_d_register(vn);
2958
        double dm_value = get_double_from_d_register(vm);
2959
        double dd_value = dn_value - dm_value;
2960
        dd_value = canonicalizeNaN(dd_value);
2961
        set_d_register_from_double(vd, dd_value);
2962
      } else {
2963
        // vadd
2964
        double dn_value = get_double_from_d_register(vn);
2965
        double dm_value = get_double_from_d_register(vm);
2966
        double dd_value = dn_value + dm_value;
2967
        dd_value = canonicalizeNaN(dd_value);
2968
        set_d_register_from_double(vd, dd_value);
2969
      }
2970
    } else if ((instr->Opc1Value() == 0x2) && !(instr->Opc3Value() & 0x1)) {
2971
      // vmul
2972
      if (instr->SzValue() != 0x1) {
2973
        UNREACHABLE();  // Not used by V8.
2974
      }
2975

    
2976
      double dn_value = get_double_from_d_register(vn);
2977
      double dm_value = get_double_from_d_register(vm);
2978
      double dd_value = dn_value * dm_value;
2979
      dd_value = canonicalizeNaN(dd_value);
2980
      set_d_register_from_double(vd, dd_value);
2981
    } else if ((instr->Opc1Value() == 0x0)) {
2982
      // vmla, vmls
2983
      const bool is_vmls = (instr->Opc3Value() & 0x1);
2984

    
2985
      if (instr->SzValue() != 0x1) {
2986
        UNREACHABLE();  // Not used by V8.
2987
      }
2988

    
2989
      const double dd_val = get_double_from_d_register(vd);
2990
      const double dn_val = get_double_from_d_register(vn);
2991
      const double dm_val = get_double_from_d_register(vm);
2992

    
2993
      // Note: we do the mul and add/sub in separate steps to avoid getting a
2994
      // result with too high precision.
2995
      set_d_register_from_double(vd, dn_val * dm_val);
2996
      if (is_vmls) {
2997
        set_d_register_from_double(
2998
          vd,
2999
          canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3000
      } else {
3001
        set_d_register_from_double(
3002
          vd,
3003
          canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3004
      }
3005
    } else if ((instr->Opc1Value() == 0x4) && !(instr->Opc3Value() & 0x1)) {
3006
      // vdiv
3007
      if (instr->SzValue() != 0x1) {
3008
        UNREACHABLE();  // Not used by V8.
3009
      }
3010

    
3011
      double dn_value = get_double_from_d_register(vn);
3012
      double dm_value = get_double_from_d_register(vm);
3013
      double dd_value = dn_value / dm_value;
3014
      div_zero_vfp_flag_ = (dm_value == 0);
3015
      dd_value = canonicalizeNaN(dd_value);
3016
      set_d_register_from_double(vd, dd_value);
3017
    } else {
3018
      UNIMPLEMENTED();  // Not used by V8.
3019
    }
3020
  } else {
3021
    if ((instr->VCValue() == 0x0) &&
3022
        (instr->VAValue() == 0x0)) {
3023
      DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3024
    } else if ((instr->VLValue() == 0x0) &&
3025
               (instr->VCValue() == 0x1) &&
3026
               (instr->Bit(23) == 0x0)) {
3027
      // vmov (ARM core register to scalar)
3028
      int vd = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3029
      double dd_value = get_double_from_d_register(vd);
3030
      int32_t data[2];
3031
      OS::MemCopy(data, &dd_value, 8);
3032
      data[instr->Bit(21)] = get_register(instr->RtValue());
3033
      OS::MemCopy(&dd_value, data, 8);
3034
      set_d_register_from_double(vd, dd_value);
3035
    } else if ((instr->VLValue() == 0x1) &&
3036
               (instr->VCValue() == 0x1) &&
3037
               (instr->Bit(23) == 0x0)) {
3038
      // vmov (scalar to ARM core register)
3039
      int vn = instr->Bits(19, 16) | (instr->Bit(7) << 4);
3040
      double dn_value = get_double_from_d_register(vn);
3041
      int32_t data[2];
3042
      OS::MemCopy(data, &dn_value, 8);
3043
      set_register(instr->RtValue(), data[instr->Bit(21)]);
3044
    } else if ((instr->VLValue() == 0x1) &&
3045
               (instr->VCValue() == 0x0) &&
3046
               (instr->VAValue() == 0x7) &&
3047
               (instr->Bits(19, 16) == 0x1)) {
3048
      // vmrs
3049
      uint32_t rt = instr->RtValue();
3050
      if (rt == 0xF) {
3051
        Copy_FPSCR_to_APSR();
3052
      } else {
3053
        // Emulate FPSCR from the Simulator flags.
3054
        uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3055
                         (z_flag_FPSCR_ << 30) |
3056
                         (c_flag_FPSCR_ << 29) |
3057
                         (v_flag_FPSCR_ << 28) |
3058
                         (FPSCR_default_NaN_mode_ << 25) |
3059
                         (inexact_vfp_flag_ << 4) |
3060
                         (underflow_vfp_flag_ << 3) |
3061
                         (overflow_vfp_flag_ << 2) |
3062
                         (div_zero_vfp_flag_ << 1) |
3063
                         (inv_op_vfp_flag_ << 0) |
3064
                         (FPSCR_rounding_mode_);
3065
        set_register(rt, fpscr);
3066
      }
3067
    } else if ((instr->VLValue() == 0x0) &&
3068
               (instr->VCValue() == 0x0) &&
3069
               (instr->VAValue() == 0x7) &&
3070
               (instr->Bits(19, 16) == 0x1)) {
3071
      // vmsr
3072
      uint32_t rt = instr->RtValue();
3073
      if (rt == pc) {
3074
        UNREACHABLE();
3075
      } else {
3076
        uint32_t rt_value = get_register(rt);
3077
        n_flag_FPSCR_ = (rt_value >> 31) & 1;
3078
        z_flag_FPSCR_ = (rt_value >> 30) & 1;
3079
        c_flag_FPSCR_ = (rt_value >> 29) & 1;
3080
        v_flag_FPSCR_ = (rt_value >> 28) & 1;
3081
        FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3082
        inexact_vfp_flag_ = (rt_value >> 4) & 1;
3083
        underflow_vfp_flag_ = (rt_value >> 3) & 1;
3084
        overflow_vfp_flag_ = (rt_value >> 2) & 1;
3085
        div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3086
        inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3087
        FPSCR_rounding_mode_ =
3088
            static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3089
      }
3090
    } else {
3091
      UNIMPLEMENTED();  // Not used by V8.
3092
    }
3093
  }
3094
}
3095

    
3096

    
3097
void Simulator::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(
3098
    Instruction* instr) {
3099
  ASSERT((instr->Bit(4) == 1) && (instr->VCValue() == 0x0) &&
3100
         (instr->VAValue() == 0x0));
3101

    
3102
  int t = instr->RtValue();
3103
  int n = instr->VFPNRegValue(kSinglePrecision);
3104
  bool to_arm_register = (instr->VLValue() == 0x1);
3105

    
3106
  if (to_arm_register) {
3107
    int32_t int_value = get_sinteger_from_s_register(n);
3108
    set_register(t, int_value);
3109
  } else {
3110
    int32_t rs_val = get_register(t);
3111
    set_s_register_from_sinteger(n, rs_val);
3112
  }
3113
}
3114

    
3115

    
3116
void Simulator::DecodeVCMP(Instruction* instr) {
3117
  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3118
  ASSERT(((instr->Opc2Value() == 0x4) || (instr->Opc2Value() == 0x5)) &&
3119
         (instr->Opc3Value() & 0x1));
3120
  // Comparison.
3121

    
3122
  VFPRegPrecision precision = kSinglePrecision;
3123
  if (instr->SzValue() == 1) {
3124
    precision = kDoublePrecision;
3125
  }
3126

    
3127
  int d = instr->VFPDRegValue(precision);
3128
  int m = 0;
3129
  if (instr->Opc2Value() == 0x4) {
3130
    m = instr->VFPMRegValue(precision);
3131
  }
3132

    
3133
  if (precision == kDoublePrecision) {
3134
    double dd_value = get_double_from_d_register(d);
3135
    double dm_value = 0.0;
3136
    if (instr->Opc2Value() == 0x4) {
3137
      dm_value = get_double_from_d_register(m);
3138
    }
3139

    
3140
    // Raise exceptions for quiet NaNs if necessary.
3141
    if (instr->Bit(7) == 1) {
3142
      if (std::isnan(dd_value)) {
3143
        inv_op_vfp_flag_ = true;
3144
      }
3145
    }
3146

    
3147
    Compute_FPSCR_Flags(dd_value, dm_value);
3148
  } else {
3149
    UNIMPLEMENTED();  // Not used by V8.
3150
  }
3151
}
3152

    
3153

    
3154
void Simulator::DecodeVCVTBetweenDoubleAndSingle(Instruction* instr) {
3155
  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
3156
  ASSERT((instr->Opc2Value() == 0x7) && (instr->Opc3Value() == 0x3));
3157

    
3158
  VFPRegPrecision dst_precision = kDoublePrecision;
3159
  VFPRegPrecision src_precision = kSinglePrecision;
3160
  if (instr->SzValue() == 1) {
3161
    dst_precision = kSinglePrecision;
3162
    src_precision = kDoublePrecision;
3163
  }
3164

    
3165
  int dst = instr->VFPDRegValue(dst_precision);
3166
  int src = instr->VFPMRegValue(src_precision);
3167

    
3168
  if (dst_precision == kSinglePrecision) {
3169
    double val = get_double_from_d_register(src);
3170
    set_s_register_from_float(dst, static_cast<float>(val));
3171
  } else {
3172
    float val = get_float_from_s_register(src);
3173
    set_d_register_from_double(dst, static_cast<double>(val));
3174
  }
3175
}
3176

    
3177
bool get_inv_op_vfp_flag(VFPRoundingMode mode,
3178
                         double val,
3179
                         bool unsigned_) {
3180
  ASSERT((mode == RN) || (mode == RM) || (mode == RZ));
3181
  double max_uint = static_cast<double>(0xffffffffu);
3182
  double max_int = static_cast<double>(kMaxInt);
3183
  double min_int = static_cast<double>(kMinInt);
3184

    
3185
  // Check for NaN.
3186
  if (val != val) {
3187
    return true;
3188
  }
3189

    
3190
  // Check for overflow. This code works because 32bit integers can be
3191
  // exactly represented by ieee-754 64bit floating-point values.
3192
  switch (mode) {
3193
    case RN:
3194
      return  unsigned_ ? (val >= (max_uint + 0.5)) ||
3195
                          (val < -0.5)
3196
                        : (val >= (max_int + 0.5)) ||
3197
                          (val < (min_int - 0.5));
3198

    
3199
    case RM:
3200
      return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3201
                          (val < 0)
3202
                        : (val >= (max_int + 1.0)) ||
3203
                          (val < min_int);
3204

    
3205
    case RZ:
3206
      return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3207
                          (val <= -1)
3208
                        : (val >= (max_int + 1.0)) ||
3209
                          (val <= (min_int - 1.0));
3210
    default:
3211
      UNREACHABLE();
3212
      return true;
3213
  }
3214
}
3215

    
3216

    
3217
// We call this function only if we had a vfp invalid exception.
3218
// It returns the correct saturated value.
3219
int VFPConversionSaturate(double val, bool unsigned_res) {
3220
  if (val != val) {
3221
    return 0;
3222
  } else {
3223
    if (unsigned_res) {
3224
      return (val < 0) ? 0 : 0xffffffffu;
3225
    } else {
3226
      return (val < 0) ? kMinInt : kMaxInt;
3227
    }
3228
  }
3229
}
3230

    
3231

    
3232
void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
3233
  ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7) &&
3234
         (instr->Bits(27, 23) == 0x1D));
3235
  ASSERT(((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) ||
3236
         (((instr->Opc2Value() >> 1) == 0x6) && (instr->Opc3Value() & 0x1)));
3237

    
3238
  // Conversion between floating-point and integer.
3239
  bool to_integer = (instr->Bit(18) == 1);
3240

    
3241
  VFPRegPrecision src_precision = (instr->SzValue() == 1) ? kDoublePrecision
3242
                                                          : kSinglePrecision;
3243

    
3244
  if (to_integer) {
3245
    // We are playing with code close to the C++ standard's limits below,
3246
    // hence the very simple code and heavy checks.
3247
    //
3248
    // Note:
3249
    // C++ defines default type casting from floating point to integer as
3250
    // (close to) rounding toward zero ("fractional part discarded").
3251

    
3252
    int dst = instr->VFPDRegValue(kSinglePrecision);
3253
    int src = instr->VFPMRegValue(src_precision);
3254

    
3255
    // Bit 7 in vcvt instructions indicates if we should use the FPSCR rounding
3256
    // mode or the default Round to Zero mode.
3257
    VFPRoundingMode mode = (instr->Bit(7) != 1) ? FPSCR_rounding_mode_
3258
                                                : RZ;
3259
    ASSERT((mode == RM) || (mode == RZ) || (mode == RN));
3260

    
3261
    bool unsigned_integer = (instr->Bit(16) == 0);
3262
    bool double_precision = (src_precision == kDoublePrecision);
3263

    
3264
    double val = double_precision ? get_double_from_d_register(src)
3265
                                  : get_float_from_s_register(src);
3266

    
3267
    int temp = unsigned_integer ? static_cast<uint32_t>(val)
3268
                                : static_cast<int32_t>(val);
3269

    
3270
    inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3271

    
3272
    double abs_diff =
3273
      unsigned_integer ? fabs(val - static_cast<uint32_t>(temp))
3274
                       : fabs(val - temp);
3275

    
3276
    inexact_vfp_flag_ = (abs_diff != 0);
3277

    
3278
    if (inv_op_vfp_flag_) {
3279
      temp = VFPConversionSaturate(val, unsigned_integer);
3280
    } else {
3281
      switch (mode) {
3282
        case RN: {
3283
          int val_sign = (val > 0) ? 1 : -1;
3284
          if (abs_diff > 0.5) {
3285
            temp += val_sign;
3286
          } else if (abs_diff == 0.5) {
3287
            // Round to even if exactly halfway.
3288
            temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3289
          }
3290
          break;
3291
        }
3292

    
3293
        case RM:
3294
          temp = temp > val ? temp - 1 : temp;
3295
          break;
3296

    
3297
        case RZ:
3298
          // Nothing to do.
3299
          break;
3300

    
3301
        default:
3302
          UNREACHABLE();
3303
      }
3304
    }
3305

    
3306
    // Update the destination register.
3307
    set_s_register_from_sinteger(dst, temp);
3308

    
3309
  } else {
3310
    bool unsigned_integer = (instr->Bit(7) == 0);
3311

    
3312
    int dst = instr->VFPDRegValue(src_precision);
3313
    int src = instr->VFPMRegValue(kSinglePrecision);
3314

    
3315
    int val = get_sinteger_from_s_register(src);
3316

    
3317
    if (src_precision == kDoublePrecision) {
3318
      if (unsigned_integer) {
3319
        set_d_register_from_double(
3320
            dst, static_cast<double>(static_cast<uint32_t>(val)));
3321
      } else {
3322
        set_d_register_from_double(dst, static_cast<double>(val));
3323
      }
3324
    } else {
3325
      if (unsigned_integer) {
3326
        set_s_register_from_float(
3327
            dst, static_cast<float>(static_cast<uint32_t>(val)));
3328
      } else {
3329
        set_s_register_from_float(dst, static_cast<float>(val));
3330
      }
3331
    }
3332
  }
3333
}
3334

    
3335

    
3336
// void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
3337
// Decode Type 6 coprocessor instructions.
3338
// Dm = vmov(Rt, Rt2)
3339
// <Rt, Rt2> = vmov(Dm)
3340
// Ddst = MEM(Rbase + 4*offset).
3341
// MEM(Rbase + 4*offset) = Dsrc.
3342
void Simulator::DecodeType6CoprocessorIns(Instruction* instr) {
3343
  ASSERT((instr->TypeValue() == 6));
3344

    
3345
  if (instr->CoprocessorValue() == 0xA) {
3346
    switch (instr->OpcodeValue()) {
3347
      case 0x8:
3348
      case 0xA:
3349
      case 0xC:
3350
      case 0xE: {  // Load and store single precision float to memory.
3351
        int rn = instr->RnValue();
3352
        int vd = instr->VFPDRegValue(kSinglePrecision);
3353
        int offset = instr->Immed8Value();
3354
        if (!instr->HasU()) {
3355
          offset = -offset;
3356
        }
3357

    
3358
        int32_t address = get_register(rn) + 4 * offset;
3359
        if (instr->HasL()) {
3360
          // Load double from memory: vldr.
3361
          set_s_register_from_sinteger(vd, ReadW(address, instr));
3362
        } else {
3363
          // Store double to memory: vstr.
3364
          WriteW(address, get_sinteger_from_s_register(vd), instr);
3365
        }
3366
        break;
3367
      }
3368
      case 0x4:
3369
      case 0x5:
3370
      case 0x6:
3371
      case 0x7:
3372
      case 0x9:
3373
      case 0xB:
3374
        // Load/store multiple single from memory: vldm/vstm.
3375
        HandleVList(instr);
3376
        break;
3377
      default:
3378
        UNIMPLEMENTED();  // Not used by V8.
3379
    }
3380
  } else if (instr->CoprocessorValue() == 0xB) {
3381
    switch (instr->OpcodeValue()) {
3382
      case 0x2:
3383
        // Load and store double to two GP registers
3384
        if (instr->Bits(7, 6) != 0 || instr->Bit(4) != 1) {
3385
          UNIMPLEMENTED();  // Not used by V8.
3386
        } else {
3387
          int rt = instr->RtValue();
3388
          int rn = instr->RnValue();
3389
          int vm = instr->VFPMRegValue(kDoublePrecision);
3390
          if (instr->HasL()) {
3391
            int32_t data[2];
3392
            double d = get_double_from_d_register(vm);
3393
            OS::MemCopy(data, &d, 8);
3394
            set_register(rt, data[0]);
3395
            set_register(rn, data[1]);
3396
          } else {
3397
            int32_t data[] = { get_register(rt), get_register(rn) };
3398
            double d;
3399
            OS::MemCopy(&d, data, 8);
3400
            set_d_register_from_double(vm, d);
3401
          }
3402
        }
3403
        break;
3404
      case 0x8:
3405
      case 0xA:
3406
      case 0xC:
3407
      case 0xE: {  // Load and store double to memory.
3408
        int rn = instr->RnValue();
3409
        int vd = instr->VFPDRegValue(kDoublePrecision);
3410
        int offset = instr->Immed8Value();
3411
        if (!instr->HasU()) {
3412
          offset = -offset;
3413
        }
3414
        int32_t address = get_register(rn) + 4 * offset;
3415
        if (instr->HasL()) {
3416
          // Load double from memory: vldr.
3417
          int32_t data[] = {
3418
            ReadW(address, instr),
3419
            ReadW(address + 4, instr)
3420
          };
3421
          double val;
3422
          OS::MemCopy(&val, data, 8);
3423
          set_d_register_from_double(vd, val);
3424
        } else {
3425
          // Store double to memory: vstr.
3426
          int32_t data[2];
3427
          double val = get_double_from_d_register(vd);
3428
          OS::MemCopy(data, &val, 8);
3429
          WriteW(address, data[0], instr);
3430
          WriteW(address + 4, data[1], instr);
3431
        }
3432
        break;
3433
      }
3434
      case 0x4:
3435
      case 0x5:
3436
      case 0x6:
3437
      case 0x7:
3438
      case 0x9:
3439
      case 0xB:
3440
        // Load/store multiple double from memory: vldm/vstm.
3441
        HandleVList(instr);
3442
        break;
3443
      default:
3444
        UNIMPLEMENTED();  // Not used by V8.
3445
    }
3446
  } else {
3447
    UNIMPLEMENTED();  // Not used by V8.
3448
  }
3449
}
3450

    
3451

    
3452
void Simulator::DecodeSpecialCondition(Instruction* instr) {
3453
  switch (instr->SpecialValue()) {
3454
    case 5:
3455
      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3456
          (instr->Bit(4) == 1)) {
3457
        // vmovl signed
3458
        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3459
        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3460
        int imm3 = instr->Bits(21, 19);
3461
        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3462
        int esize = 8 * imm3;
3463
        int elements = 64 / esize;
3464
        int8_t from[8];
3465
        get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3466
        int16_t to[8];
3467
        int e = 0;
3468
        while (e < elements) {
3469
          to[e] = from[e];
3470
          e++;
3471
        }
3472
        set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3473
      } else {
3474
        UNIMPLEMENTED();
3475
      }
3476
      break;
3477
    case 7:
3478
      if ((instr->Bits(18, 16) == 0) && (instr->Bits(11, 6) == 0x28) &&
3479
          (instr->Bit(4) == 1)) {
3480
        // vmovl unsigned
3481
        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3482
        int Vm = (instr->Bit(5) << 4) | instr->VmValue();
3483
        int imm3 = instr->Bits(21, 19);
3484
        if ((imm3 != 1) && (imm3 != 2) && (imm3 != 4)) UNIMPLEMENTED();
3485
        int esize = 8 * imm3;
3486
        int elements = 64 / esize;
3487
        uint8_t from[8];
3488
        get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
3489
        uint16_t to[8];
3490
        int e = 0;
3491
        while (e < elements) {
3492
          to[e] = from[e];
3493
          e++;
3494
        }
3495
        set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
3496
      } else {
3497
        UNIMPLEMENTED();
3498
      }
3499
      break;
3500
    case 8:
3501
      if (instr->Bits(21, 20) == 0) {
3502
        // vst1
3503
        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3504
        int Rn = instr->VnValue();
3505
        int type = instr->Bits(11, 8);
3506
        int Rm = instr->VmValue();
3507
        int32_t address = get_register(Rn);
3508
        int regs = 0;
3509
        switch (type) {
3510
          case nlt_1:
3511
            regs = 1;
3512
            break;
3513
          case nlt_2:
3514
            regs = 2;
3515
            break;
3516
          case nlt_3:
3517
            regs = 3;
3518
            break;
3519
          case nlt_4:
3520
            regs = 4;
3521
            break;
3522
          default:
3523
            UNIMPLEMENTED();
3524
            break;
3525
        }
3526
        int r = 0;
3527
        while (r < regs) {
3528
          uint32_t data[2];
3529
          get_d_register(Vd + r, data);
3530
          WriteW(address, data[0], instr);
3531
          WriteW(address + 4, data[1], instr);
3532
          address += 8;
3533
          r++;
3534
        }
3535
        if (Rm != 15) {
3536
          if (Rm == 13) {
3537
            set_register(Rn, address);
3538
          } else {
3539
            set_register(Rn, get_register(Rn) + get_register(Rm));
3540
          }
3541
        }
3542
      } else if (instr->Bits(21, 20) == 2) {
3543
        // vld1
3544
        int Vd = (instr->Bit(22) << 4) | instr->VdValue();
3545
        int Rn = instr->VnValue();
3546
        int type = instr->Bits(11, 8);
3547
        int Rm = instr->VmValue();
3548
        int32_t address = get_register(Rn);
3549
        int regs = 0;
3550
        switch (type) {
3551
          case nlt_1:
3552
            regs = 1;
3553
            break;
3554
          case nlt_2:
3555
            regs = 2;
3556
            break;
3557
          case nlt_3:
3558
            regs = 3;
3559
            break;
3560
          case nlt_4:
3561
            regs = 4;
3562
            break;
3563
          default:
3564
            UNIMPLEMENTED();
3565
            break;
3566
        }
3567
        int r = 0;
3568
        while (r < regs) {
3569
          uint32_t data[2];
3570
          data[0] = ReadW(address, instr);
3571
          data[1] = ReadW(address + 4, instr);
3572
          set_d_register(Vd + r, data);
3573
          address += 8;
3574
          r++;
3575
        }
3576
        if (Rm != 15) {
3577
          if (Rm == 13) {
3578
            set_register(Rn, address);
3579
          } else {
3580
            set_register(Rn, get_register(Rn) + get_register(Rm));
3581
          }
3582
        }
3583
      } else {
3584
        UNIMPLEMENTED();
3585
      }
3586
      break;
3587
    case 0xA:
3588
    case 0xB:
3589
      if ((instr->Bits(22, 20) == 5) && (instr->Bits(15, 12) == 0xf)) {
3590
        // pld: ignore instruction.
3591
      } else {
3592
        UNIMPLEMENTED();
3593
      }
3594
      break;
3595
    default:
3596
      UNIMPLEMENTED();
3597
      break;
3598
  }
3599
}
3600

    
3601

    
3602
// Executes the current instruction.
3603
void Simulator::InstructionDecode(Instruction* instr) {
3604
  if (v8::internal::FLAG_check_icache) {
3605
    CheckICache(isolate_->simulator_i_cache(), instr);
3606
  }
3607
  pc_modified_ = false;
3608
  if (::v8::internal::FLAG_trace_sim) {
3609
    disasm::NameConverter converter;
3610
    disasm::Disassembler dasm(converter);
3611
    // use a reasonably large buffer
3612
    v8::internal::EmbeddedVector<char, 256> buffer;
3613
    dasm.InstructionDecode(buffer,
3614
                           reinterpret_cast<byte*>(instr));
3615
    PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
3616
  }
3617
  if (instr->ConditionField() == kSpecialCondition) {
3618
    DecodeSpecialCondition(instr);
3619
  } else if (ConditionallyExecute(instr)) {
3620
    switch (instr->TypeValue()) {
3621
      case 0:
3622
      case 1: {
3623
        DecodeType01(instr);
3624
        break;
3625
      }
3626
      case 2: {
3627
        DecodeType2(instr);
3628
        break;
3629
      }
3630
      case 3: {
3631
        DecodeType3(instr);
3632
        break;
3633
      }
3634
      case 4: {
3635
        DecodeType4(instr);
3636
        break;
3637
      }
3638
      case 5: {
3639
        DecodeType5(instr);
3640
        break;
3641
      }
3642
      case 6: {
3643
        DecodeType6(instr);
3644
        break;
3645
      }
3646
      case 7: {
3647
        DecodeType7(instr);
3648
        break;
3649
      }
3650
      default: {
3651
        UNIMPLEMENTED();
3652
        break;
3653
      }
3654
    }
3655
  // If the instruction is a non taken conditional stop, we need to skip the
3656
  // inlined message address.
3657
  } else if (instr->IsStop()) {
3658
    set_pc(get_pc() + 2 * Instruction::kInstrSize);
3659
  }
3660
  if (!pc_modified_) {
3661
    set_register(pc, reinterpret_cast<int32_t>(instr)
3662
                         + Instruction::kInstrSize);
3663
  }
3664
}
3665

    
3666

    
3667
void Simulator::Execute() {
3668
  // Get the PC to simulate. Cannot use the accessor here as we need the
3669
  // raw PC value and not the one used as input to arithmetic instructions.
3670
  int program_counter = get_pc();
3671

    
3672
  if (::v8::internal::FLAG_stop_sim_at == 0) {
3673
    // Fast version of the dispatch loop without checking whether the simulator
3674
    // should be stopping at a particular executed instruction.
3675
    while (program_counter != end_sim_pc) {
3676
      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3677
      icount_++;
3678
      InstructionDecode(instr);
3679
      program_counter = get_pc();
3680
    }
3681
  } else {
3682
    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3683
    // we reach the particular instuction count.
3684
    while (program_counter != end_sim_pc) {
3685
      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3686
      icount_++;
3687
      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3688
        ArmDebugger dbg(this);
3689
        dbg.Debug();
3690
      } else {
3691
        InstructionDecode(instr);
3692
      }
3693
      program_counter = get_pc();
3694
    }
3695
  }
3696
}
3697

    
3698

    
3699
void Simulator::CallInternal(byte* entry) {
3700
  // Prepare to execute the code at entry
3701
  set_register(pc, reinterpret_cast<int32_t>(entry));
3702
  // Put down marker for end of simulation. The simulator will stop simulation
3703
  // when the PC reaches this value. By saving the "end simulation" value into
3704
  // the LR the simulation stops when returning to this call point.
3705
  set_register(lr, end_sim_pc);
3706

    
3707
  // Remember the values of callee-saved registers.
3708
  // The code below assumes that r9 is not used as sb (static base) in
3709
  // simulator code and therefore is regarded as a callee-saved register.
3710
  int32_t r4_val = get_register(r4);
3711
  int32_t r5_val = get_register(r5);
3712
  int32_t r6_val = get_register(r6);
3713
  int32_t r7_val = get_register(r7);
3714
  int32_t r8_val = get_register(r8);
3715
  int32_t r9_val = get_register(r9);
3716
  int32_t r10_val = get_register(r10);
3717
  int32_t r11_val = get_register(r11);
3718

    
3719
  // Set up the callee-saved registers with a known value. To be able to check
3720
  // that they are preserved properly across JS execution.
3721
  int32_t callee_saved_value = icount_;
3722
  set_register(r4, callee_saved_value);
3723
  set_register(r5, callee_saved_value);
3724
  set_register(r6, callee_saved_value);
3725
  set_register(r7, callee_saved_value);
3726
  set_register(r8, callee_saved_value);
3727
  set_register(r9, callee_saved_value);
3728
  set_register(r10, callee_saved_value);
3729
  set_register(r11, callee_saved_value);
3730

    
3731
  // Start the simulation
3732
  Execute();
3733

    
3734
  // Check that the callee-saved registers have been preserved.
3735
  CHECK_EQ(callee_saved_value, get_register(r4));
3736
  CHECK_EQ(callee_saved_value, get_register(r5));
3737
  CHECK_EQ(callee_saved_value, get_register(r6));
3738
  CHECK_EQ(callee_saved_value, get_register(r7));
3739
  CHECK_EQ(callee_saved_value, get_register(r8));
3740
  CHECK_EQ(callee_saved_value, get_register(r9));
3741
  CHECK_EQ(callee_saved_value, get_register(r10));
3742
  CHECK_EQ(callee_saved_value, get_register(r11));
3743

    
3744
  // Restore callee-saved registers with the original value.
3745
  set_register(r4, r4_val);
3746
  set_register(r5, r5_val);
3747
  set_register(r6, r6_val);
3748
  set_register(r7, r7_val);
3749
  set_register(r8, r8_val);
3750
  set_register(r9, r9_val);
3751
  set_register(r10, r10_val);
3752
  set_register(r11, r11_val);
3753
}
3754

    
3755

    
3756
int32_t Simulator::Call(byte* entry, int argument_count, ...) {
3757
  va_list parameters;
3758
  va_start(parameters, argument_count);
3759
  // Set up arguments
3760

    
3761
  // First four arguments passed in registers.
3762
  ASSERT(argument_count >= 4);
3763
  set_register(r0, va_arg(parameters, int32_t));
3764
  set_register(r1, va_arg(parameters, int32_t));
3765
  set_register(r2, va_arg(parameters, int32_t));
3766
  set_register(r3, va_arg(parameters, int32_t));
3767

    
3768
  // Remaining arguments passed on stack.
3769
  int original_stack = get_register(sp);
3770
  // Compute position of stack on entry to generated code.
3771
  int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t));
3772
  if (OS::ActivationFrameAlignment() != 0) {
3773
    entry_stack &= -OS::ActivationFrameAlignment();
3774
  }
3775
  // Store remaining arguments on stack, from low to high memory.
3776
  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
3777
  for (int i = 4; i < argument_count; i++) {
3778
    stack_argument[i - 4] = va_arg(parameters, int32_t);
3779
  }
3780
  va_end(parameters);
3781
  set_register(sp, entry_stack);
3782

    
3783
  CallInternal(entry);
3784

    
3785
  // Pop stack passed arguments.
3786
  CHECK_EQ(entry_stack, get_register(sp));
3787
  set_register(sp, original_stack);
3788

    
3789
  int32_t result = get_register(r0);
3790
  return result;
3791
}
3792

    
3793

    
3794
void Simulator::CallFP(byte* entry, double d0, double d1) {
3795
  if (use_eabi_hardfloat()) {
3796
    set_d_register_from_double(0, d0);
3797
    set_d_register_from_double(1, d1);
3798
  } else {
3799
    set_register_pair_from_double(0, &d0);
3800
    set_register_pair_from_double(2, &d1);
3801
  }
3802
  CallInternal(entry);
3803
}
3804

    
3805

    
3806
int32_t Simulator::CallFPReturnsInt(byte* entry, double d0, double d1) {
3807
  CallFP(entry, d0, d1);
3808
  int32_t result = get_register(r0);
3809
  return result;
3810
}
3811

    
3812

    
3813
double Simulator::CallFPReturnsDouble(byte* entry, double d0, double d1) {
3814
  CallFP(entry, d0, d1);
3815
  if (use_eabi_hardfloat()) {
3816
    return get_double_from_d_register(0);
3817
  } else {
3818
    return get_double_from_register_pair(0);
3819
  }
3820
}
3821

    
3822

    
3823
uintptr_t Simulator::PushAddress(uintptr_t address) {
3824
  int new_sp = get_register(sp) - sizeof(uintptr_t);
3825
  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
3826
  *stack_slot = address;
3827
  set_register(sp, new_sp);
3828
  return new_sp;
3829
}
3830

    
3831

    
3832
uintptr_t Simulator::PopAddress() {
3833
  int current_sp = get_register(sp);
3834
  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
3835
  uintptr_t address = *stack_slot;
3836
  set_register(sp, current_sp + sizeof(uintptr_t));
3837
  return address;
3838
}
3839

    
3840
} }  // namespace v8::internal
3841

    
3842
#endif  // USE_SIMULATOR
3843

    
3844
#endif  // V8_TARGET_ARCH_ARM