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 / simulator-arm.cc @ 40c0f755

History | View | Annotate | Download (44.7 KB)

1 40c0f755 Ryan
// Copyright 2008 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
30
#include "v8.h"
31
32
#include "disasm.h"
33
#include "constants-arm.h"
34
#include "simulator-arm.h"
35
36
#if !defined(__arm__)
37
38
// Only build the simulator if not compiling for real ARM hardware.
39
namespace assembler { namespace arm {
40
41
using ::v8::internal::Object;
42
using ::v8::internal::PrintF;
43
using ::v8::internal::OS;
44
using ::v8::internal::ReadLine;
45
using ::v8::internal::DeleteArray;
46
47
// This macro provides a platform independent use of sscanf. The reason for
48
// SScanF not being implemented in a platform independent was through
49
// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
50
// Library does not provide vsscanf.
51
#define SScanF sscanf  // NOLINT
52
53
// The Debugger class is used by the simulator while debugging simulated ARM
54
// code.
55
class Debugger {
56
 public:
57
  explicit Debugger(Simulator* sim);
58
  ~Debugger();
59
60
  void Stop(Instr* instr);
61
  void Debug();
62
63
 private:
64
  static const instr_t kBreakpointInstr =
65
      ((AL << 28) | (7 << 25) | (1 << 24) | break_point);
66
  static const instr_t kNopInstr =
67
      ((AL << 28) | (13 << 21));
68
69
  Simulator* sim_;
70
71
  bool GetValue(char* desc, int32_t* value);
72
73
  // Set or delete a breakpoint. Returns true if successful.
74
  bool SetBreakpoint(Instr* breakpc);
75
  bool DeleteBreakpoint(Instr* breakpc);
76
77
  // Undo and redo all breakpoints. This is needed to bracket disassembly and
78
  // execution to skip past breakpoints when run from the debugger.
79
  void UndoBreakpoints();
80
  void RedoBreakpoints();
81
};
82
83
84
Debugger::Debugger(Simulator* sim) {
85
  sim_ = sim;
86
}
87
88
89
Debugger::~Debugger() {
90
}
91
92
93
void Debugger::Stop(Instr* instr) {
94
  const char* str = (const char*)(instr->InstructionBits() & 0x0fffffff);
95
  PrintF("Simulator hit %s\n", str);
96
  sim_->set_pc(sim_->get_pc() + Instr::kInstrSize);
97
  Debug();
98
}
99
100
101
static const char* reg_names[] = {  "r0",  "r1",  "r2",  "r3",
102
                                    "r4",  "r5",  "r6",  "r7",
103
                                    "r8",  "r9", "r10", "r11",
104
                                   "r12", "r13", "r14", "r15",
105
                                    "pc",  "lr",  "sp",  "ip",
106
                                    "fp",  "sl", ""};
107
108
static int   reg_nums[]  = {           0,     1,     2,     3,
109
                                       4,     5,     6,     7,
110
                                       8,     9,    10,    11,
111
                                      12,    13,    14,    15,
112
                                      15,    14,    13,    12,
113
                                      11,    10};
114
115
116
static int RegNameToRegNum(char* name) {
117
  int reg = 0;
118
  while (*reg_names[reg] != 0) {
119
    if (strcmp(reg_names[reg], name) == 0) {
120
      return reg_nums[reg];
121
    }
122
    reg++;
123
  }
124
  return -1;
125
}
126
127
128
bool Debugger::GetValue(char* desc, int32_t* value) {
129
  int regnum = RegNameToRegNum(desc);
130
  if (regnum >= 0) {
131
    if (regnum == 15) {
132
      *value = sim_->get_pc();
133
    } else {
134
      *value = sim_->get_register(regnum);
135
    }
136
    return true;
137
  } else {
138
    return SScanF(desc, "%i", value) == 1;
139
  }
140
  return false;
141
}
142
143
144
bool Debugger::SetBreakpoint(Instr* breakpc) {
145
  // Check if a breakpoint can be set. If not return without any side-effects.
146
  if (sim_->break_pc_ != NULL) {
147
    return false;
148
  }
149
150
  // Set the breakpoint.
151
  sim_->break_pc_ = breakpc;
152
  sim_->break_instr_ = breakpc->InstructionBits();
153
  // Not setting the breakpoint instruction in the code itself. It will be set
154
  // when the debugger shell continues.
155
  return true;
156
}
157
158
159
bool Debugger::DeleteBreakpoint(Instr* breakpc) {
160
  if (sim_->break_pc_ != NULL) {
161
    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
162
  }
163
164
  sim_->break_pc_ = NULL;
165
  sim_->break_instr_ = 0;
166
  return true;
167
}
168
169
170
void Debugger::UndoBreakpoints() {
171
  if (sim_->break_pc_ != NULL) {
172
    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
173
  }
174
}
175
176
177
void Debugger::RedoBreakpoints() {
178
  if (sim_->break_pc_ != NULL) {
179
    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
180
  }
181
}
182
183
184
void Debugger::Debug() {
185
  intptr_t last_pc = -1;
186
  bool done = false;
187
188
#define COMMAND_SIZE 63
189
#define ARG_SIZE 255
190
191
#define STR(a) #a
192
#define XSTR(a) STR(a)
193
194
  char cmd[COMMAND_SIZE + 1];
195
  char arg1[ARG_SIZE + 1];
196
  char arg2[ARG_SIZE + 1];
197
198
  // make sure to have a proper terminating character if reaching the limit
199
  cmd[COMMAND_SIZE] = 0;
200
  arg1[ARG_SIZE] = 0;
201
  arg2[ARG_SIZE] = 0;
202
203
  // Undo all set breakpoints while running in the debugger shell. This will
204
  // make them invisible to all commands.
205
  UndoBreakpoints();
206
207
  while (!done) {
208
    if (last_pc != sim_->get_pc()) {
209
      disasm::NameConverter converter;
210
      disasm::Disassembler dasm(converter);
211
      // use a reasonably large buffer
212
      v8::internal::EmbeddedVector<char, 256> buffer;
213
      dasm.InstructionDecode(buffer,
214
                             reinterpret_cast<byte*>(sim_->get_pc()));
215
      PrintF("  0x%x  %s\n", sim_->get_pc(), buffer.start());
216
      last_pc = sim_->get_pc();
217
    }
218
    char* line = ReadLine("sim> ");
219
    if (line == NULL) {
220
      break;
221
    } else {
222
      // Use sscanf to parse the individual parts of the command line. At the
223
      // moment no command expects more than two parameters.
224
      int args = SScanF(line,
225
                        "%" XSTR(COMMAND_SIZE) "s "
226
                        "%" XSTR(ARG_SIZE) "s "
227
                        "%" XSTR(ARG_SIZE) "s",
228
                        cmd, arg1, arg2);
229
      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
230
        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
231
      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
232
        // Execute the one instruction we broke at with breakpoints disabled.
233
        sim_->InstructionDecode(reinterpret_cast<Instr*>(sim_->get_pc()));
234
        // Leave the debugger shell.
235
        done = true;
236
      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
237
        if (args == 2) {
238
          int32_t value;
239
          if (GetValue(arg1, &value)) {
240
            PrintF("%s: %d 0x%x\n", arg1, value, value);
241
          } else {
242
            PrintF("%s unrecognized\n", arg1);
243
          }
244
        } else {
245
          PrintF("print value\n");
246
        }
247
      } else if ((strcmp(cmd, "po") == 0)
248
                 || (strcmp(cmd, "printobject") == 0)) {
249
        if (args == 2) {
250
          int32_t value;
251
          if (GetValue(arg1, &value)) {
252
            Object* obj = reinterpret_cast<Object*>(value);
253
            USE(obj);
254
            PrintF("%s: \n", arg1);
255
#if defined(DEBUG)
256
            obj->PrintLn();
257
#endif  // defined(DEBUG)
258
          } else {
259
            PrintF("%s unrecognized\n", arg1);
260
          }
261
        } else {
262
          PrintF("printobject value\n");
263
        }
264
      } else if (strcmp(cmd, "disasm") == 0) {
265
        disasm::NameConverter converter;
266
        disasm::Disassembler dasm(converter);
267
        // use a reasonably large buffer
268
        v8::internal::EmbeddedVector<char, 256> buffer;
269
270
        byte* cur = NULL;
271
        byte* end = NULL;
272
273
        if (args == 1) {
274
          cur = reinterpret_cast<byte*>(sim_->get_pc());
275
          end = cur + (10 * Instr::kInstrSize);
276
        } else if (args == 2) {
277
          int32_t value;
278
          if (GetValue(arg1, &value)) {
279
            cur = reinterpret_cast<byte*>(value);
280
            // no length parameter passed, assume 10 instructions
281
            end = cur + (10 * Instr::kInstrSize);
282
          }
283
        } else {
284
          int32_t value1;
285
          int32_t value2;
286
          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
287
            cur = reinterpret_cast<byte*>(value1);
288
            end = cur + (value2 * Instr::kInstrSize);
289
          }
290
        }
291
292
        while (cur < end) {
293
          dasm.InstructionDecode(buffer, cur);
294
          PrintF("  0x%x  %s\n", cur, buffer.start());
295
          cur += Instr::kInstrSize;
296
        }
297
      } else if (strcmp(cmd, "gdb") == 0) {
298
        PrintF("relinquishing control to gdb\n");
299
        v8::internal::OS::DebugBreak();
300
        PrintF("regaining control from gdb\n");
301
      } else if (strcmp(cmd, "break") == 0) {
302
        if (args == 2) {
303
          int32_t value;
304
          if (GetValue(arg1, &value)) {
305
            if (!SetBreakpoint(reinterpret_cast<Instr*>(value))) {
306
              PrintF("setting breakpoint failed\n");
307
            }
308
          } else {
309
            PrintF("%s unrecognized\n", arg1);
310
          }
311
        } else {
312
          PrintF("break addr\n");
313
        }
314
      } else if (strcmp(cmd, "del") == 0) {
315
        if (!DeleteBreakpoint(NULL)) {
316
          PrintF("deleting breakpoint failed\n");
317
        }
318
      } else if (strcmp(cmd, "flags") == 0) {
319
        PrintF("N flag: %d; ", sim_->n_flag_);
320
        PrintF("Z flag: %d; ", sim_->z_flag_);
321
        PrintF("C flag: %d; ", sim_->c_flag_);
322
        PrintF("V flag: %d\n", sim_->v_flag_);
323
      } else if (strcmp(cmd, "unstop") == 0) {
324
        intptr_t stop_pc = sim_->get_pc() - Instr::kInstrSize;
325
        Instr* stop_instr = reinterpret_cast<Instr*>(stop_pc);
326
        if (stop_instr->ConditionField() == special_condition) {
327
          stop_instr->SetInstructionBits(kNopInstr);
328
        } else {
329
          PrintF("Not at debugger stop.");
330
        }
331
      } else {
332
        PrintF("Unknown command: %s\n", cmd);
333
      }
334
    }
335
    DeleteArray(line);
336
  }
337
338
  // Add all the breakpoints back to stop execution and enter the debugger
339
  // shell when hit.
340
  RedoBreakpoints();
341
342
#undef COMMAND_SIZE
343
#undef ARG_SIZE
344
345
#undef STR
346
#undef XSTR
347
}
348
349
350
Simulator::Simulator() {
351
  // Setup simulator support first. Some of this information is needed to
352
  // setup the architecture state.
353
  size_t stack_size = 1 * 1024*1024;  // allocate 1MB for stack
354
  stack_ = reinterpret_cast<char*>(malloc(stack_size));
355
  pc_modified_ = false;
356
  icount_ = 0;
357
  break_pc_ = NULL;
358
  break_instr_ = 0;
359
360
  // Setup architecture state.
361
  // All registers are initialized to zero to start with.
362
  for (int i = 0; i < num_registers; i++) {
363
    registers_[i] = 0;
364
  }
365
  n_flag_ = false;
366
  z_flag_ = false;
367
  c_flag_ = false;
368
  v_flag_ = false;
369
370
  // The sp is initialized to point to the bottom (high address) of the
371
  // allocated stack area. To be safe in potential stack underflows we leave
372
  // some buffer below.
373
  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64;
374
  // The lr and pc are initialized to a known bad value that will cause an
375
  // access violation if the simulator ever tries to execute it.
376
  registers_[pc] = bad_lr;
377
  registers_[lr] = bad_lr;
378
}
379
380
381
// Create one simulator per thread and keep it in thread local storage.
382
static v8::internal::Thread::LocalStorageKey simulator_key =
383
    v8::internal::Thread::CreateThreadLocalKey();
384
385
// Get the active Simulator for the current thread.
386
Simulator* Simulator::current() {
387
  Simulator* sim = reinterpret_cast<Simulator*>(
388
      v8::internal::Thread::GetThreadLocal(simulator_key));
389
  if (sim == NULL) {
390
    // TODO(146): delete the simulator object when a thread goes away.
391
    sim = new Simulator();
392
    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
393
  }
394
  return sim;
395
}
396
397
398
// Sets the register in the architecture state. It will also deal with updating
399
// Simulator internal state for special registers such as PC.
400
void Simulator::set_register(int reg, int32_t value) {
401
  ASSERT((reg >= 0) && (reg < num_registers));
402
  if (reg == pc) {
403
    pc_modified_ = true;
404
  }
405
  registers_[reg] = value;
406
}
407
408
409
// Get the register from the architecture state. This function does handle
410
// the special case of accessing the PC register.
411
int32_t Simulator::get_register(int reg) const {
412
  ASSERT((reg >= 0) && (reg < num_registers));
413
  return registers_[reg] + ((reg == pc) ? Instr::kPCReadOffset : 0);
414
}
415
416
417
// Raw access to the PC register.
418
void Simulator::set_pc(int32_t value) {
419
  pc_modified_ = true;
420
  registers_[pc] = value;
421
}
422
423
424
// Raw access to the PC register without the special adjustment when reading.
425
int32_t Simulator::get_pc() const {
426
  return registers_[pc];
427
}
428
429
430
// The ARM cannot do unaligned reads and writes.  On some ARM platforms an
431
// interrupt is caused.  On others it does a funky rotation thing.  For now we
432
// simply disallow unaligned reads, but at some point we may want to move to
433
// emulating the rotate behaviour.  Note that simulator runs have the runtime
434
// system running directly on the host system and only generated code is
435
// executed in the simulator.  Since the host is typically IA32 we will not
436
// get the correct ARM-like behaviour on unaligned accesses.
437
438
int Simulator::ReadW(int32_t addr, Instr* instr) {
439
  if ((addr & 3) == 0) {
440
    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
441
    return *ptr;
442
  }
443
  PrintF("Unaligned read at %x\n", addr);
444
  UNIMPLEMENTED();
445
  return 0;
446
}
447
448
449
void Simulator::WriteW(int32_t addr, int value, Instr* instr) {
450
  if ((addr & 3) == 0) {
451
    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
452
    *ptr = value;
453
    return;
454
  }
455
  PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
456
  UNIMPLEMENTED();
457
}
458
459
460
uint16_t Simulator::ReadHU(int32_t addr, Instr* instr) {
461
  if ((addr & 1) == 0) {
462
    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
463
    return *ptr;
464
  }
465
  PrintF("Unaligned read at %x, pc=%p\n", addr, instr);
466
  UNIMPLEMENTED();
467
  return 0;
468
}
469
470
471
int16_t Simulator::ReadH(int32_t addr, Instr* instr) {
472
  if ((addr & 1) == 0) {
473
    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
474
    return *ptr;
475
  }
476
  PrintF("Unaligned read at %x\n", addr);
477
  UNIMPLEMENTED();
478
  return 0;
479
}
480
481
482
void Simulator::WriteH(int32_t addr, uint16_t value, Instr* instr) {
483
  if ((addr & 1) == 0) {
484
    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
485
    *ptr = value;
486
    return;
487
  }
488
  PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
489
  UNIMPLEMENTED();
490
}
491
492
493
void Simulator::WriteH(int32_t addr, int16_t value, Instr* instr) {
494
  if ((addr & 1) == 0) {
495
    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
496
    *ptr = value;
497
    return;
498
  }
499
  PrintF("Unaligned write at %x, pc=%p\n", addr, instr);
500
  UNIMPLEMENTED();
501
}
502
503
504
uint8_t Simulator::ReadBU(int32_t addr) {
505
  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
506
  return *ptr;
507
}
508
509
510
int8_t Simulator::ReadB(int32_t addr) {
511
  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
512
  return *ptr;
513
}
514
515
516
void Simulator::WriteB(int32_t addr, uint8_t value) {
517
  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
518
  *ptr = value;
519
}
520
521
522
void Simulator::WriteB(int32_t addr, int8_t value) {
523
  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
524
  *ptr = value;
525
}
526
527
528
// Returns the limit of the stack area to enable checking for stack overflows.
529
uintptr_t Simulator::StackLimit() const {
530
  // Leave a safety margin of 256 bytes to prevent overrunning the stack when
531
  // pushing values.
532
  return reinterpret_cast<uintptr_t>(stack_) + 256;
533
}
534
535
536
// Unsupported instructions use Format to print an error and stop execution.
537
void Simulator::Format(Instr* instr, const char* format) {
538
  PrintF("Simulator found unsupported instruction:\n 0x%x: %s\n",
539
         instr, format);
540
  UNIMPLEMENTED();
541
}
542
543
544
// Checks if the current instruction should be executed based on its
545
// condition bits.
546
bool Simulator::ConditionallyExecute(Instr* instr) {
547
  switch (instr->ConditionField()) {
548
    case EQ: return z_flag_;
549
    case NE: return !z_flag_;
550
    case CS: return c_flag_;
551
    case CC: return !c_flag_;
552
    case MI: return n_flag_;
553
    case PL: return !n_flag_;
554
    case VS: return v_flag_;
555
    case VC: return !v_flag_;
556
    case HI: return c_flag_ && !z_flag_;
557
    case LS: return !c_flag_ || z_flag_;
558
    case GE: return n_flag_ == v_flag_;
559
    case LT: return n_flag_ != v_flag_;
560
    case GT: return !z_flag_ && (n_flag_ == v_flag_);
561
    case LE: return z_flag_ || (n_flag_ != v_flag_);
562
    case AL: return true;
563
    default: UNREACHABLE();
564
  }
565
  return false;
566
}
567
568
569
// Calculate and set the Negative and Zero flags.
570
void Simulator::SetNZFlags(int32_t val) {
571
  n_flag_ = (val < 0);
572
  z_flag_ = (val == 0);
573
}
574
575
576
// Set the Carry flag.
577
void Simulator::SetCFlag(bool val) {
578
  c_flag_ = val;
579
}
580
581
582
// Set the oVerflow flag.
583
void Simulator::SetVFlag(bool val) {
584
  v_flag_ = val;
585
}
586
587
588
// Calculate C flag value for additions.
589
bool Simulator::CarryFrom(int32_t left, int32_t right) {
590
  uint32_t uleft = static_cast<uint32_t>(left);
591
  uint32_t uright = static_cast<uint32_t>(right);
592
  uint32_t urest  = 0xffffffffU - uleft;
593
594
  return (uright > urest);
595
}
596
597
598
// Calculate C flag value for subtractions.
599
bool Simulator::BorrowFrom(int32_t left, int32_t right) {
600
  uint32_t uleft = static_cast<uint32_t>(left);
601
  uint32_t uright = static_cast<uint32_t>(right);
602
603
  return (uright > uleft);
604
}
605
606
607
// Calculate V flag value for additions and subtractions.
608
bool Simulator::OverflowFrom(int32_t alu_out,
609
                             int32_t left, int32_t right, bool addition) {
610
  bool overflow;
611
  if (addition) {
612
               // operands have the same sign
613
    overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
614
               // and operands and result have different sign
615
               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
616
  } else {
617
               // operands have different signs
618
    overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
619
               // and first operand and result have different signs
620
               && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
621
  }
622
  return overflow;
623
}
624
625
626
// Addressing Mode 1 - Data-processing operands:
627
// Get the value based on the shifter_operand with register.
628
int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
629
  Shift shift = instr->ShiftField();
630
  int shift_amount = instr->ShiftAmountField();
631
  int32_t result = get_register(instr->RmField());
632
  if (instr->Bit(4) == 0) {
633
    // by immediate
634
    if ((shift == ROR) && (shift_amount == 0)) {
635
      UNIMPLEMENTED();
636
      return result;
637
    } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) {
638
      shift_amount = 32;
639
    }
640
    switch (shift) {
641
      case ASR: {
642
        if (shift_amount == 0) {
643
          if (result < 0) {
644
            result = 0xffffffff;
645
            *carry_out = true;
646
          } else {
647
            result = 0;
648
            *carry_out = false;
649
          }
650
        } else {
651
          result >>= (shift_amount - 1);
652
          *carry_out = (result & 1) == 1;
653
          result >>= 1;
654
        }
655
        break;
656
      }
657
658
      case LSL: {
659
        if (shift_amount == 0) {
660
          *carry_out = c_flag_;
661
        } else {
662
          result <<= (shift_amount - 1);
663
          *carry_out = (result < 0);
664
          result <<= 1;
665
        }
666
        break;
667
      }
668
669
      case LSR: {
670
        if (shift_amount == 0) {
671
          result = 0;
672
          *carry_out = c_flag_;
673
        } else {
674
          uint32_t uresult = static_cast<uint32_t>(result);
675
          uresult >>= (shift_amount - 1);
676
          *carry_out = (uresult & 1) == 1;
677
          uresult >>= 1;
678
          result = static_cast<int32_t>(uresult);
679
        }
680
        break;
681
      }
682
683
      case ROR: {
684
        UNIMPLEMENTED();
685
        break;
686
      }
687
688
      default: {
689
        UNREACHABLE();
690
        break;
691
      }
692
    }
693
  } else {
694
    // by register
695
    int rs = instr->RsField();
696
    shift_amount = get_register(rs) &0xff;
697
    switch (shift) {
698
      case ASR: {
699
        if (shift_amount == 0) {
700
          *carry_out = c_flag_;
701
        } else if (shift_amount < 32) {
702
          result >>= (shift_amount - 1);
703
          *carry_out = (result & 1) == 1;
704
          result >>= 1;
705
        } else {
706
          ASSERT(shift_amount >= 32);
707
          if (result < 0) {
708
            *carry_out = true;
709
            result = 0xffffffff;
710
          } else {
711
            *carry_out = false;
712
            result = 0;
713
          }
714
        }
715
        break;
716
      }
717
718
      case LSL: {
719
        if (shift_amount == 0) {
720
          *carry_out = c_flag_;
721
        } else if (shift_amount < 32) {
722
          result <<= (shift_amount - 1);
723
          *carry_out = (result < 0);
724
          result <<= 1;
725
        } else if (shift_amount == 32) {
726
          *carry_out = (result & 1) == 1;
727
          result = 0;
728
        } else {
729
          ASSERT(shift_amount > 32);
730
          *carry_out = false;
731
          result = 0;
732
        }
733
        break;
734
      }
735
736
      case LSR: {
737
        if (shift_amount == 0) {
738
          *carry_out = c_flag_;
739
        } else if (shift_amount < 32) {
740
          uint32_t uresult = static_cast<uint32_t>(result);
741
          uresult >>= (shift_amount - 1);
742
          *carry_out = (uresult & 1) == 1;
743
          uresult >>= 1;
744
          result = static_cast<int32_t>(uresult);
745
        } else if (shift_amount == 32) {
746
          *carry_out = (result < 0);
747
          result = 0;
748
        } else {
749
          *carry_out = false;
750
          result = 0;
751
        }
752
        break;
753
      }
754
755
      case ROR: {
756
        UNIMPLEMENTED();
757
        break;
758
      }
759
760
      default: {
761
        UNREACHABLE();
762
        break;
763
      }
764
    }
765
  }
766
  return result;
767
}
768
769
770
// Addressing Mode 1 - Data-processing operands:
771
// Get the value based on the shifter_operand with immediate.
772
int32_t Simulator::GetImm(Instr* instr, bool* carry_out) {
773
  int rotate = instr->RotateField() * 2;
774
  int immed8 = instr->Immed8Field();
775
  int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
776
  *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
777
  return imm;
778
}
779
780
781
static int count_bits(int bit_vector) {
782
  int count = 0;
783
  while (bit_vector != 0) {
784
    if ((bit_vector & 1) != 0) {
785
      count++;
786
    }
787
    bit_vector >>= 1;
788
  }
789
  return count;
790
}
791
792
793
// Addressing Mode 4 - Load and Store Multiple
794
void Simulator::HandleRList(Instr* instr, bool load) {
795
  int rn = instr->RnField();
796
  int32_t rn_val = get_register(rn);
797
  int rlist = instr->RlistField();
798
  int num_regs = count_bits(rlist);
799
800
  intptr_t start_address = 0;
801
  intptr_t end_address = 0;
802
  switch (instr->PUField()) {
803
    case 0: {
804
      // Print("da");
805
      UNIMPLEMENTED();
806
      break;
807
    }
808
    case 1: {
809
      // Print("ia");
810
      start_address = rn_val;
811
      end_address = rn_val + (num_regs * 4) - 4;
812
      rn_val = rn_val + (num_regs * 4);
813
      break;
814
    }
815
    case 2: {
816
      // Print("db");
817
      start_address = rn_val - (num_regs * 4);
818
      end_address = rn_val - 4;
819
      rn_val = start_address;
820
      break;
821
    }
822
    case 3: {
823
      // Print("ib");
824
      UNIMPLEMENTED();
825
      break;
826
    }
827
    default: {
828
      UNREACHABLE();
829
      break;
830
    }
831
  }
832
  if (instr->HasW()) {
833
    set_register(rn, rn_val);
834
  }
835
  intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
836
  int reg = 0;
837
  while (rlist != 0) {
838
    if ((rlist & 1) != 0) {
839
      if (load) {
840
        set_register(reg, *address);
841
      } else {
842
        *address = get_register(reg);
843
      }
844
      address += 1;
845
    }
846
    reg++;
847
    rlist >>= 1;
848
  }
849
  ASSERT(end_address == ((intptr_t)address) - 4);
850
}
851
852
853
// Calls into the V8 runtime are based on this very simple interface.
854
// Note: To be able to return two values from some calls the code in runtime.cc
855
// uses the ObjectPair which is essentially two 32-bit values stuffed into a
856
// 64-bit value. With the code below we assume that all runtime calls return
857
// 64 bits of result. If they don't, the r1 result register contains a bogus
858
// value, which is fine because it is caller-saved.
859
typedef int64_t (*SimulatorRuntimeCall)(intptr_t arg0, intptr_t arg1);
860
861
862
// Software interrupt instructions are used by the simulator to call into the
863
// C-based V8 runtime.
864
void Simulator::SoftwareInterrupt(Instr* instr) {
865
  switch (instr->SwiField()) {
866
    case call_rt_r5: {
867
      SimulatorRuntimeCall target =
868
          reinterpret_cast<SimulatorRuntimeCall>(get_register(r5));
869
      intptr_t arg0 = get_register(r0);
870
      intptr_t arg1 = get_register(r1);
871
      int64_t result = target(arg0, arg1);
872
      int32_t lo_res = static_cast<int32_t>(result);
873
      int32_t hi_res = static_cast<int32_t>(result >> 32);
874
      set_register(r0, lo_res);
875
      set_register(r1, hi_res);
876
      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
877
      break;
878
    }
879
    case call_rt_r2: {
880
      SimulatorRuntimeCall target =
881
          reinterpret_cast<SimulatorRuntimeCall>(get_register(r2));
882
      intptr_t arg0 = get_register(r0);
883
      intptr_t arg1 = get_register(r1);
884
      int64_t result = target(arg0, arg1);
885
      int32_t lo_res = static_cast<int32_t>(result);
886
      int32_t hi_res = static_cast<int32_t>(result >> 32);
887
      set_register(r0, lo_res);
888
      set_register(r1, hi_res);
889
      set_pc(reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
890
      break;
891
    }
892
    case break_point: {
893
      Debugger dbg(this);
894
      dbg.Debug();
895
      break;
896
    }
897
    default: {
898
      UNREACHABLE();
899
      break;
900
    }
901
  }
902
}
903
904
905
// Handle execution based on instruction types.
906
907
// Instruction types 0 and 1 are both rolled into one function because they
908
// only differ in the handling of the shifter_operand.
909
void Simulator::DecodeType01(Instr* instr) {
910
  int type = instr->TypeField();
911
  if ((type == 0) && instr->IsSpecialType0()) {
912
    // multiply instruction or extra loads and stores
913
    if (instr->Bits(7, 4) == 9) {
914
      if (instr->Bit(24) == 0) {
915
        // multiply instructions
916
        int rd = instr->RdField();
917
        int rm = instr->RmField();
918
        int rs = instr->RsField();
919
        int32_t rs_val = get_register(rs);
920
        int32_t rm_val = get_register(rm);
921
        if (instr->Bit(23) == 0) {
922
          if (instr->Bit(21) == 0) {
923
            // Format(instr, "mul'cond's 'rd, 'rm, 'rs");
924
            int32_t alu_out = rm_val * rs_val;
925
            set_register(rd, alu_out);
926
            if (instr->HasS()) {
927
              SetNZFlags(alu_out);
928
            }
929
          } else {
930
            Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn");
931
          }
932
        } else {
933
          // Format(instr, "'um'al'cond's 'rn, 'rd, 'rs, 'rm");
934
          int rn = instr->RnField();
935
          int32_t hi_res = 0;
936
          int32_t lo_res = 0;
937
          if (instr->Bit(22) == 0) {
938
            // signed multiply
939
            UNIMPLEMENTED();
940
          } else {
941
            // unsigned multiply
942
            uint64_t left_op  = rm_val;
943
            uint64_t right_op = rs_val;
944
            uint64_t result = left_op * right_op;
945
            hi_res = static_cast<int32_t>(result >> 32);
946
            lo_res = static_cast<int32_t>(result & 0xffffffff);
947
          }
948
          set_register(rn, hi_res);
949
          set_register(rd, lo_res);
950
          if (instr->HasS()) {
951
            UNIMPLEMENTED();
952
          }
953
        }
954
      } else {
955
        UNIMPLEMENTED();  // not used by V8
956
      }
957
    } else {
958
      // extra load/store instructions
959
      int rd = instr->RdField();
960
      int rn = instr->RnField();
961
      int32_t rn_val = get_register(rn);
962
      int32_t addr = 0;
963
      if (instr->Bit(22) == 0) {
964
        int rm = instr->RmField();
965
        int32_t rm_val = get_register(rm);
966
        switch (instr->PUField()) {
967
          case 0: {
968
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], -'rm");
969
            ASSERT(!instr->HasW());
970
            addr = rn_val;
971
            rn_val -= rm_val;
972
            set_register(rn, rn_val);
973
            break;
974
          }
975
          case 1: {
976
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], +'rm");
977
            ASSERT(!instr->HasW());
978
            addr = rn_val;
979
            rn_val += rm_val;
980
            set_register(rn, rn_val);
981
            break;
982
          }
983
          case 2: {
984
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, -'rm]'w");
985
            rn_val -= rm_val;
986
            addr = rn_val;
987
            if (instr->HasW()) {
988
              set_register(rn, rn_val);
989
            }
990
            break;
991
          }
992
          case 3: {
993
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, +'rm]'w");
994
            rn_val += rm_val;
995
            addr = rn_val;
996
            if (instr->HasW()) {
997
              set_register(rn, rn_val);
998
            }
999
            break;
1000
          }
1001
          default: {
1002
            // The PU field is a 2-bit field.
1003
            UNREACHABLE();
1004
            break;
1005
          }
1006
        }
1007
      } else {
1008
        int32_t imm_val = (instr->ImmedHField() << 4) | instr->ImmedLField();
1009
        switch (instr->PUField()) {
1010
          case 0: {
1011
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #-'off8");
1012
            ASSERT(!instr->HasW());
1013
            addr = rn_val;
1014
            rn_val -= imm_val;
1015
            set_register(rn, rn_val);
1016
            break;
1017
          }
1018
          case 1: {
1019
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn], #+'off8");
1020
            ASSERT(!instr->HasW());
1021
            addr = rn_val;
1022
            rn_val += imm_val;
1023
            set_register(rn, rn_val);
1024
            break;
1025
          }
1026
          case 2: {
1027
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #-'off8]'w");
1028
            rn_val -= imm_val;
1029
            addr = rn_val;
1030
            if (instr->HasW()) {
1031
              set_register(rn, rn_val);
1032
            }
1033
            break;
1034
          }
1035
          case 3: {
1036
            // Format(instr, "'memop'cond'sign'h 'rd, ['rn, #+'off8]'w");
1037
            rn_val += imm_val;
1038
            addr = rn_val;
1039
            if (instr->HasW()) {
1040
              set_register(rn, rn_val);
1041
            }
1042
            break;
1043
          }
1044
          default: {
1045
            // The PU field is a 2-bit field.
1046
            UNREACHABLE();
1047
            break;
1048
          }
1049
        }
1050
      }
1051
      if (instr->HasH()) {
1052
        if (instr->HasSign()) {
1053
          if (instr->HasL()) {
1054
            int16_t val = ReadH(addr, instr);
1055
            set_register(rd, val);
1056
          } else {
1057
            int16_t val = get_register(rd);
1058
            WriteH(addr, val, instr);
1059
          }
1060
        } else {
1061
          if (instr->HasL()) {
1062
            uint16_t val = ReadHU(addr, instr);
1063
            set_register(rd, val);
1064
          } else {
1065
            uint16_t val = get_register(rd);
1066
            WriteH(addr, val, instr);
1067
          }
1068
        }
1069
      } else {
1070
        // signed byte loads
1071
        ASSERT(instr->HasSign());
1072
        ASSERT(instr->HasL());
1073
        int8_t val = ReadB(addr);
1074
        set_register(rd, val);
1075
      }
1076
      return;
1077
    }
1078
  } else {
1079
    int rd = instr->RdField();
1080
    int rn = instr->RnField();
1081
    int32_t rn_val = get_register(rn);
1082
    int32_t shifter_operand = 0;
1083
    bool shifter_carry_out = 0;
1084
    if (type == 0) {
1085
      shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1086
    } else {
1087
      ASSERT(instr->TypeField() == 1);
1088
      shifter_operand = GetImm(instr, &shifter_carry_out);
1089
    }
1090
    int32_t alu_out;
1091
1092
    switch (instr->OpcodeField()) {
1093
      case AND: {
1094
        // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
1095
        // Format(instr, "and'cond's 'rd, 'rn, 'imm");
1096
        alu_out = rn_val & shifter_operand;
1097
        set_register(rd, alu_out);
1098
        if (instr->HasS()) {
1099
          SetNZFlags(alu_out);
1100
          SetCFlag(shifter_carry_out);
1101
        }
1102
        break;
1103
      }
1104
1105
      case EOR: {
1106
        // Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm");
1107
        // Format(instr, "eor'cond's 'rd, 'rn, 'imm");
1108
        alu_out = rn_val ^ shifter_operand;
1109
        set_register(rd, alu_out);
1110
        if (instr->HasS()) {
1111
          SetNZFlags(alu_out);
1112
          SetCFlag(shifter_carry_out);
1113
        }
1114
        break;
1115
      }
1116
1117
      case SUB: {
1118
        // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
1119
        // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
1120
        alu_out = rn_val - shifter_operand;
1121
        set_register(rd, alu_out);
1122
        if (instr->HasS()) {
1123
          SetNZFlags(alu_out);
1124
          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1125
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1126
        }
1127
        break;
1128
      }
1129
1130
      case RSB: {
1131
        // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
1132
        // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
1133
        alu_out = shifter_operand - rn_val;
1134
        set_register(rd, alu_out);
1135
        if (instr->HasS()) {
1136
          SetNZFlags(alu_out);
1137
          SetCFlag(!BorrowFrom(shifter_operand, rn_val));
1138
          SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false));
1139
        }
1140
        break;
1141
      }
1142
1143
      case ADD: {
1144
        // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
1145
        // Format(instr, "add'cond's 'rd, 'rn, 'imm");
1146
        alu_out = rn_val + shifter_operand;
1147
        set_register(rd, alu_out);
1148
        if (instr->HasS()) {
1149
          SetNZFlags(alu_out);
1150
          SetCFlag(CarryFrom(rn_val, shifter_operand));
1151
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true));
1152
        }
1153
        break;
1154
      }
1155
1156
      case ADC: {
1157
        Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
1158
        Format(instr, "adc'cond's 'rd, 'rn, 'imm");
1159
        break;
1160
      }
1161
1162
      case SBC: {
1163
        Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
1164
        Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
1165
        break;
1166
      }
1167
1168
      case RSC: {
1169
        Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
1170
        Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
1171
        break;
1172
      }
1173
1174
      case TST: {
1175
        if (instr->HasS()) {
1176
          // Format(instr, "tst'cond 'rn, 'shift_rm");
1177
          // Format(instr, "tst'cond 'rn, 'imm");
1178
          alu_out = rn_val & shifter_operand;
1179
          SetNZFlags(alu_out);
1180
          SetCFlag(shifter_carry_out);
1181
        } else {
1182
          UNIMPLEMENTED();
1183
        }
1184
        break;
1185
      }
1186
1187
      case TEQ: {
1188
        if (instr->HasS()) {
1189
          // Format(instr, "teq'cond 'rn, 'shift_rm");
1190
          // Format(instr, "teq'cond 'rn, 'imm");
1191
          alu_out = rn_val ^ shifter_operand;
1192
          SetNZFlags(alu_out);
1193
          SetCFlag(shifter_carry_out);
1194
        } else {
1195
          UNIMPLEMENTED();
1196
        }
1197
        break;
1198
      }
1199
1200
      case CMP: {
1201
        if (instr->HasS()) {
1202
          // Format(instr, "cmp'cond 'rn, 'shift_rm");
1203
          // Format(instr, "cmp'cond 'rn, 'imm");
1204
          alu_out = rn_val - shifter_operand;
1205
          SetNZFlags(alu_out);
1206
          SetCFlag(!BorrowFrom(rn_val, shifter_operand));
1207
          SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false));
1208
        } else {
1209
          UNIMPLEMENTED();
1210
        }
1211
        break;
1212
      }
1213
1214
      case CMN: {
1215
        if (instr->HasS()) {
1216
          Format(instr, "cmn'cond 'rn, 'shift_rm");
1217
          Format(instr, "cmn'cond 'rn, 'imm");
1218
        } else {
1219
          UNIMPLEMENTED();
1220
        }
1221
        break;
1222
      }
1223
1224
      case ORR: {
1225
        // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
1226
        // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
1227
        alu_out = rn_val | shifter_operand;
1228
        set_register(rd, alu_out);
1229
        if (instr->HasS()) {
1230
          SetNZFlags(alu_out);
1231
          SetCFlag(shifter_carry_out);
1232
        }
1233
        break;
1234
      }
1235
1236
      case MOV: {
1237
        // Format(instr, "mov'cond's 'rd, 'shift_rm");
1238
        // Format(instr, "mov'cond's 'rd, 'imm");
1239
        alu_out = shifter_operand;
1240
        set_register(rd, alu_out);
1241
        if (instr->HasS()) {
1242
          SetNZFlags(alu_out);
1243
          SetCFlag(shifter_carry_out);
1244
        }
1245
        break;
1246
      }
1247
1248
      case BIC: {
1249
        // Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm");
1250
        // Format(instr, "bic'cond's 'rd, 'rn, 'imm");
1251
        alu_out = rn_val & ~shifter_operand;
1252
        set_register(rd, alu_out);
1253
        if (instr->HasS()) {
1254
          SetNZFlags(alu_out);
1255
          SetCFlag(shifter_carry_out);
1256
        }
1257
        break;
1258
      }
1259
1260
      case MVN: {
1261
        // Format(instr, "mvn'cond's 'rd, 'shift_rm");
1262
        // Format(instr, "mvn'cond's 'rd, 'imm");
1263
        alu_out = ~shifter_operand;
1264
        set_register(rd, alu_out);
1265
        if (instr->HasS()) {
1266
          SetNZFlags(alu_out);
1267
          SetCFlag(shifter_carry_out);
1268
        }
1269
        break;
1270
      }
1271
1272
      default: {
1273
        UNREACHABLE();
1274
        break;
1275
      }
1276
    }
1277
  }
1278
}
1279
1280
1281
void Simulator::DecodeType2(Instr* instr) {
1282
  int rd = instr->RdField();
1283
  int rn = instr->RnField();
1284
  int32_t rn_val = get_register(rn);
1285
  int32_t im_val = instr->Offset12Field();
1286
  int32_t addr = 0;
1287
  switch (instr->PUField()) {
1288
    case 0: {
1289
      // Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
1290
      ASSERT(!instr->HasW());
1291
      addr = rn_val;
1292
      rn_val -= im_val;
1293
      set_register(rn, rn_val);
1294
      break;
1295
    }
1296
    case 1: {
1297
      // Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
1298
      ASSERT(!instr->HasW());
1299
      addr = rn_val;
1300
      rn_val += im_val;
1301
      set_register(rn, rn_val);
1302
      break;
1303
    }
1304
    case 2: {
1305
      // Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
1306
      rn_val -= im_val;
1307
      addr = rn_val;
1308
      if (instr->HasW()) {
1309
        set_register(rn, rn_val);
1310
      }
1311
      break;
1312
    }
1313
    case 3: {
1314
      // Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
1315
      rn_val += im_val;
1316
      addr = rn_val;
1317
      if (instr->HasW()) {
1318
        set_register(rn, rn_val);
1319
      }
1320
      break;
1321
    }
1322
    default: {
1323
      UNREACHABLE();
1324
      break;
1325
    }
1326
  }
1327
  if (instr->HasB()) {
1328
    if (instr->HasL()) {
1329
      byte val = ReadBU(addr);
1330
      set_register(rd, val);
1331
    } else {
1332
      byte val = get_register(rd);
1333
      WriteB(addr, val);
1334
    }
1335
  } else {
1336
    if (instr->HasL()) {
1337
      set_register(rd, ReadW(addr, instr));
1338
    } else {
1339
      WriteW(addr, get_register(rd), instr);
1340
    }
1341
  }
1342
}
1343
1344
1345
void Simulator::DecodeType3(Instr* instr) {
1346
  int rd = instr->RdField();
1347
  int rn = instr->RnField();
1348
  int32_t rn_val = get_register(rn);
1349
  bool shifter_carry_out = 0;
1350
  int32_t shifter_operand = GetShiftRm(instr, &shifter_carry_out);
1351
  int32_t addr = 0;
1352
  switch (instr->PUField()) {
1353
    case 0: {
1354
      ASSERT(!instr->HasW());
1355
      Format(instr, "'memop'cond'b 'rd, ['rn], -'shift_rm");
1356
      break;
1357
    }
1358
    case 1: {
1359
      ASSERT(!instr->HasW());
1360
      Format(instr, "'memop'cond'b 'rd, ['rn], +'shift_rm");
1361
      break;
1362
    }
1363
    case 2: {
1364
      // Format(instr, "'memop'cond'b 'rd, ['rn, -'shift_rm]'w");
1365
      addr = rn_val - shifter_operand;
1366
      if (instr->HasW()) {
1367
        set_register(rn, addr);
1368
      }
1369
      break;
1370
    }
1371
    case 3: {
1372
      // Format(instr, "'memop'cond'b 'rd, ['rn, +'shift_rm]'w");
1373
      addr = rn_val + shifter_operand;
1374
      if (instr->HasW()) {
1375
        set_register(rn, addr);
1376
      }
1377
      break;
1378
    }
1379
    default: {
1380
      UNREACHABLE();
1381
      break;
1382
    }
1383
  }
1384
  if (instr->HasB()) {
1385
    UNIMPLEMENTED();
1386
  } else {
1387
    if (instr->HasL()) {
1388
      set_register(rd, ReadW(addr, instr));
1389
    } else {
1390
      WriteW(addr, get_register(rd), instr);
1391
    }
1392
  }
1393
}
1394
1395
1396
void Simulator::DecodeType4(Instr* instr) {
1397
  ASSERT(instr->Bit(22) == 0);  // only allowed to be set in privileged mode
1398
  if (instr->HasL()) {
1399
    // Format(instr, "ldm'cond'pu 'rn'w, 'rlist");
1400
    HandleRList(instr, true);
1401
  } else {
1402
    // Format(instr, "stm'cond'pu 'rn'w, 'rlist");
1403
    HandleRList(instr, false);
1404
  }
1405
}
1406
1407
1408
void Simulator::DecodeType5(Instr* instr) {
1409
  // Format(instr, "b'l'cond 'target");
1410
  int off = (instr->SImmed24Field() << 2) + 8;
1411
  intptr_t pc = get_pc();
1412
  if (instr->HasLink()) {
1413
    set_register(lr, pc + Instr::kInstrSize);
1414
  }
1415
  set_pc(pc+off);
1416
}
1417
1418
1419
void Simulator::DecodeType6(Instr* instr) {
1420
  UNIMPLEMENTED();
1421
}
1422
1423
1424
void Simulator::DecodeType7(Instr* instr) {
1425
  if (instr->Bit(24) == 1) {
1426
    // Format(instr, "swi 'swi");
1427
    SoftwareInterrupt(instr);
1428
  } else {
1429
    UNIMPLEMENTED();
1430
  }
1431
}
1432
1433
1434
// Executes the current instruction.
1435
void Simulator::InstructionDecode(Instr* instr) {
1436
  pc_modified_ = false;
1437
  if (instr->ConditionField() == special_condition) {
1438
    Debugger dbg(this);
1439
    dbg.Stop(instr);
1440
    return;
1441
  }
1442
  if (::v8::internal::FLAG_trace_sim) {
1443
    disasm::NameConverter converter;
1444
    disasm::Disassembler dasm(converter);
1445
    // use a reasonably large buffer
1446
    v8::internal::EmbeddedVector<char, 256> buffer;
1447
    dasm.InstructionDecode(buffer,
1448
                           reinterpret_cast<byte*>(instr));
1449
    PrintF("  0x%x  %s\n", instr, buffer.start());
1450
  }
1451
  if (ConditionallyExecute(instr)) {
1452
    switch (instr->TypeField()) {
1453
      case 0:
1454
      case 1: {
1455
        DecodeType01(instr);
1456
        break;
1457
      }
1458
      case 2: {
1459
        DecodeType2(instr);
1460
        break;
1461
      }
1462
      case 3: {
1463
        DecodeType3(instr);
1464
        break;
1465
      }
1466
      case 4: {
1467
        DecodeType4(instr);
1468
        break;
1469
      }
1470
      case 5: {
1471
        DecodeType5(instr);
1472
        break;
1473
      }
1474
      case 6: {
1475
        DecodeType6(instr);
1476
        break;
1477
      }
1478
      case 7: {
1479
        DecodeType7(instr);
1480
        break;
1481
      }
1482
      default: {
1483
        UNIMPLEMENTED();
1484
        break;
1485
      }
1486
    }
1487
  }
1488
  if (!pc_modified_) {
1489
    set_register(pc, reinterpret_cast<int32_t>(instr) + Instr::kInstrSize);
1490
  }
1491
}
1492
1493
1494
//
1495
void Simulator::Execute() {
1496
  // Get the PC to simulate. Cannot use the accessor here as we need the
1497
  // raw PC value and not the one used as input to arithmetic instructions.
1498
  int program_counter = get_pc();
1499
1500
  if (::v8::internal::FLAG_stop_sim_at == 0) {
1501
    // Fast version of the dispatch loop without checking whether the simulator
1502
    // should be stopping at a particular executed instruction.
1503
    while (program_counter != end_sim_pc) {
1504
      Instr* instr = reinterpret_cast<Instr*>(program_counter);
1505
      icount_++;
1506
      InstructionDecode(instr);
1507
      program_counter = get_pc();
1508
    }
1509
  } else {
1510
    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
1511
    // we reach the particular instuction count.
1512
    while (program_counter != end_sim_pc) {
1513
      Instr* instr = reinterpret_cast<Instr*>(program_counter);
1514
      icount_++;
1515
      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
1516
        Debugger dbg(this);
1517
        dbg.Debug();
1518
      } else {
1519
        InstructionDecode(instr);
1520
      }
1521
      program_counter = get_pc();
1522
    }
1523
  }
1524
}
1525
1526
1527
Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
1528
                        int32_t p3, int32_t p4) {
1529
  // Setup parameters
1530
  set_register(r0, p0);
1531
  set_register(r1, p1);
1532
  set_register(r2, p2);
1533
  set_register(r3, p3);
1534
  intptr_t* stack_pointer = reinterpret_cast<intptr_t*>(get_register(sp));
1535
  *(--stack_pointer) = p4;
1536
  set_register(sp, reinterpret_cast<int32_t>(stack_pointer));
1537
1538
  // Prepare to execute the code at entry
1539
  set_register(pc, entry);
1540
  // Put down marker for end of simulation. The simulator will stop simulation
1541
  // when the PC reaches this value. By saving the "end simulation" value into
1542
  // the LR the simulation stops when returning to this call point.
1543
  set_register(lr, end_sim_pc);
1544
1545
  // Remember the values of callee-saved registers.
1546
  // The code below assumes that r9 is not used as sb (static base) in
1547
  // simulator code and therefore is regarded as a callee-saved register.
1548
  int32_t r4_val = get_register(r4);
1549
  int32_t r5_val = get_register(r5);
1550
  int32_t r6_val = get_register(r6);
1551
  int32_t r7_val = get_register(r7);
1552
  int32_t r8_val = get_register(r8);
1553
  int32_t r9_val = get_register(r9);
1554
  int32_t r10_val = get_register(r10);
1555
  int32_t r11_val = get_register(r11);
1556
1557
  // Setup the callee-saved registers with a known value. To be able to check
1558
  // that they are preserved properly across JS execution.
1559
  int32_t callee_saved_value = icount_;
1560
  set_register(r4, callee_saved_value);
1561
  set_register(r5, callee_saved_value);
1562
  set_register(r6, callee_saved_value);
1563
  set_register(r7, callee_saved_value);
1564
  set_register(r8, callee_saved_value);
1565
  set_register(r9, callee_saved_value);
1566
  set_register(r10, callee_saved_value);
1567
  set_register(r11, callee_saved_value);
1568
1569
  // Start the simulation
1570
  Execute();
1571
1572
  // Check that the callee-saved registers have been preserved.
1573
  CHECK_EQ(get_register(r4), callee_saved_value);
1574
  CHECK_EQ(get_register(r5), callee_saved_value);
1575
  CHECK_EQ(get_register(r6), callee_saved_value);
1576
  CHECK_EQ(get_register(r7), callee_saved_value);
1577
  CHECK_EQ(get_register(r8), callee_saved_value);
1578
  CHECK_EQ(get_register(r9), callee_saved_value);
1579
  CHECK_EQ(get_register(r10), callee_saved_value);
1580
  CHECK_EQ(get_register(r11), callee_saved_value);
1581
1582
  // Restore callee-saved registers with the original value.
1583
  set_register(r4, r4_val);
1584
  set_register(r5, r5_val);
1585
  set_register(r6, r6_val);
1586
  set_register(r7, r7_val);
1587
  set_register(r8, r8_val);
1588
  set_register(r9, r9_val);
1589
  set_register(r10, r10_val);
1590
  set_register(r11, r11_val);
1591
1592
  int result = get_register(r0);
1593
  return reinterpret_cast<Object*>(result);
1594
}
1595
1596
} }  // namespace assembler::arm
1597
1598
#endif  // !defined(__arm__)