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 / mips / simulator-mips.cc @ f230a1cf

History | View | Annotate | Download (94.1 KB)

1
// Copyright 2011 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 <limits.h>
30
#include <cmath>
31
#include <cstdarg>
32
#include "v8.h"
33

    
34
#if V8_TARGET_ARCH_MIPS
35

    
36
#include "cpu.h"
37
#include "disasm.h"
38
#include "assembler.h"
39
#include "globals.h"    // Need the BitCast.
40
#include "mips/constants-mips.h"
41
#include "mips/simulator-mips.h"
42

    
43

    
44
// Only build the simulator if not compiling for real MIPS hardware.
45
#if defined(USE_SIMULATOR)
46

    
47
namespace v8 {
48
namespace internal {
49

    
50
// Utils functions.
51
bool HaveSameSign(int32_t a, int32_t b) {
52
  return ((a ^ b) >= 0);
53
}
54

    
55

    
56
uint32_t get_fcsr_condition_bit(uint32_t cc) {
57
  if (cc == 0) {
58
    return 23;
59
  } else {
60
    return 24 + cc;
61
  }
62
}
63

    
64

    
65
// This macro provides a platform independent use of sscanf. The reason for
66
// SScanF not being implemented in a platform independent was through
67
// ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
68
// Library does not provide vsscanf.
69
#define SScanF sscanf  // NOLINT
70

    
71
// The MipsDebugger class is used by the simulator while debugging simulated
72
// code.
73
class MipsDebugger {
74
 public:
75
  explicit MipsDebugger(Simulator* sim) : sim_(sim) { }
76
  ~MipsDebugger();
77

    
78
  void Stop(Instruction* instr);
79
  void Debug();
80
  // Print all registers with a nice formatting.
81
  void PrintAllRegs();
82
  void PrintAllRegsIncludingFPU();
83

    
84
 private:
85
  // We set the breakpoint code to 0xfffff to easily recognize it.
86
  static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
87
  static const Instr kNopInstr =  0x0;
88

    
89
  Simulator* sim_;
90

    
91
  int32_t GetRegisterValue(int regnum);
92
  int32_t GetFPURegisterValueInt(int regnum);
93
  int64_t GetFPURegisterValueLong(int regnum);
94
  float GetFPURegisterValueFloat(int regnum);
95
  double GetFPURegisterValueDouble(int regnum);
96
  bool GetValue(const char* desc, int32_t* value);
97

    
98
  // Set or delete a breakpoint. Returns true if successful.
99
  bool SetBreakpoint(Instruction* breakpc);
100
  bool DeleteBreakpoint(Instruction* breakpc);
101

    
102
  // Undo and redo all breakpoints. This is needed to bracket disassembly and
103
  // execution to skip past breakpoints when run from the debugger.
104
  void UndoBreakpoints();
105
  void RedoBreakpoints();
106
};
107

    
108

    
109
MipsDebugger::~MipsDebugger() {
110
}
111

    
112

    
113
#ifdef GENERATED_CODE_COVERAGE
114
static FILE* coverage_log = NULL;
115

    
116

    
117
static void InitializeCoverage() {
118
  char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
119
  if (file_name != NULL) {
120
    coverage_log = fopen(file_name, "aw+");
121
  }
122
}
123

    
124

    
125
void MipsDebugger::Stop(Instruction* instr) {
126
  // Get the stop code.
127
  uint32_t code = instr->Bits(25, 6);
128
  // Retrieve the encoded address, which comes just after this stop.
129
  char** msg_address =
130
    reinterpret_cast<char**>(sim_->get_pc() + Instr::kInstrSize);
131
  char* msg = *msg_address;
132
  ASSERT(msg != NULL);
133

    
134
  // Update this stop description.
135
  if (!watched_stops_[code].desc) {
136
    watched_stops_[code].desc = msg;
137
  }
138

    
139
  if (strlen(msg) > 0) {
140
    if (coverage_log != NULL) {
141
      fprintf(coverage_log, "%s\n", str);
142
      fflush(coverage_log);
143
    }
144
    // Overwrite the instruction and address with nops.
145
    instr->SetInstructionBits(kNopInstr);
146
    reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr);
147
  }
148
  sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstructionSize);
149
}
150

    
151

    
152
#else  // GENERATED_CODE_COVERAGE
153

    
154
#define UNSUPPORTED() printf("Unsupported instruction.\n");
155

    
156
static void InitializeCoverage() {}
157

    
158

    
159
void MipsDebugger::Stop(Instruction* instr) {
160
  // Get the stop code.
161
  uint32_t code = instr->Bits(25, 6);
162
  // Retrieve the encoded address, which comes just after this stop.
163
  char* msg = *reinterpret_cast<char**>(sim_->get_pc() +
164
      Instruction::kInstrSize);
165
  // Update this stop description.
166
  if (!sim_->watched_stops_[code].desc) {
167
    sim_->watched_stops_[code].desc = msg;
168
  }
169
  PrintF("Simulator hit %s (%u)\n", msg, code);
170
  sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
171
  Debug();
172
}
173
#endif  // GENERATED_CODE_COVERAGE
174

    
175

    
176
int32_t MipsDebugger::GetRegisterValue(int regnum) {
177
  if (regnum == kNumSimuRegisters) {
178
    return sim_->get_pc();
179
  } else {
180
    return sim_->get_register(regnum);
181
  }
182
}
183

    
184

    
185
int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) {
186
  if (regnum == kNumFPURegisters) {
187
    return sim_->get_pc();
188
  } else {
189
    return sim_->get_fpu_register(regnum);
190
  }
191
}
192

    
193

    
194
int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) {
195
  if (regnum == kNumFPURegisters) {
196
    return sim_->get_pc();
197
  } else {
198
    return sim_->get_fpu_register_long(regnum);
199
  }
200
}
201

    
202

    
203
float MipsDebugger::GetFPURegisterValueFloat(int regnum) {
204
  if (regnum == kNumFPURegisters) {
205
    return sim_->get_pc();
206
  } else {
207
    return sim_->get_fpu_register_float(regnum);
208
  }
209
}
210

    
211

    
212
double MipsDebugger::GetFPURegisterValueDouble(int regnum) {
213
  if (regnum == kNumFPURegisters) {
214
    return sim_->get_pc();
215
  } else {
216
    return sim_->get_fpu_register_double(regnum);
217
  }
218
}
219

    
220

    
221
bool MipsDebugger::GetValue(const char* desc, int32_t* value) {
222
  int regnum = Registers::Number(desc);
223
  int fpuregnum = FPURegisters::Number(desc);
224

    
225
  if (regnum != kInvalidRegister) {
226
    *value = GetRegisterValue(regnum);
227
    return true;
228
  } else if (fpuregnum != kInvalidFPURegister) {
229
    *value = GetFPURegisterValueInt(fpuregnum);
230
    return true;
231
  } else if (strncmp(desc, "0x", 2) == 0) {
232
    return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
233
  } else {
234
    return SScanF(desc, "%i", value) == 1;
235
  }
236
  return false;
237
}
238

    
239

    
240
bool MipsDebugger::SetBreakpoint(Instruction* breakpc) {
241
  // Check if a breakpoint can be set. If not return without any side-effects.
242
  if (sim_->break_pc_ != NULL) {
243
    return false;
244
  }
245

    
246
  // Set the breakpoint.
247
  sim_->break_pc_ = breakpc;
248
  sim_->break_instr_ = breakpc->InstructionBits();
249
  // Not setting the breakpoint instruction in the code itself. It will be set
250
  // when the debugger shell continues.
251
  return true;
252
}
253

    
254

    
255
bool MipsDebugger::DeleteBreakpoint(Instruction* breakpc) {
256
  if (sim_->break_pc_ != NULL) {
257
    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
258
  }
259

    
260
  sim_->break_pc_ = NULL;
261
  sim_->break_instr_ = 0;
262
  return true;
263
}
264

    
265

    
266
void MipsDebugger::UndoBreakpoints() {
267
  if (sim_->break_pc_ != NULL) {
268
    sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
269
  }
270
}
271

    
272

    
273
void MipsDebugger::RedoBreakpoints() {
274
  if (sim_->break_pc_ != NULL) {
275
    sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
276
  }
277
}
278

    
279

    
280
void MipsDebugger::PrintAllRegs() {
281
#define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
282

    
283
  PrintF("\n");
284
  // at, v0, a0.
285
  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
286
         REG_INFO(1), REG_INFO(2), REG_INFO(4));
287
  // v1, a1.
288
  PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
289
         "", REG_INFO(3), REG_INFO(5));
290
  // a2.
291
  PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(6));
292
  // a3.
293
  PrintF("%26s\t%26s\t%3s: 0x%08x %10d\n", "", "", REG_INFO(7));
294
  PrintF("\n");
295
  // t0-t7, s0-s7
296
  for (int i = 0; i < 8; i++) {
297
    PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
298
           REG_INFO(8+i), REG_INFO(16+i));
299
  }
300
  PrintF("\n");
301
  // t8, k0, LO.
302
  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
303
         REG_INFO(24), REG_INFO(26), REG_INFO(32));
304
  // t9, k1, HI.
305
  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
306
         REG_INFO(25), REG_INFO(27), REG_INFO(33));
307
  // sp, fp, gp.
308
  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
309
         REG_INFO(29), REG_INFO(30), REG_INFO(28));
310
  // pc.
311
  PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
312
         REG_INFO(31), REG_INFO(34));
313

    
314
#undef REG_INFO
315
#undef FPU_REG_INFO
316
}
317

    
318

    
319
void MipsDebugger::PrintAllRegsIncludingFPU() {
320
#define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
321
        GetFPURegisterValueInt(n+1), \
322
        GetFPURegisterValueInt(n), \
323
                        GetFPURegisterValueDouble(n)
324

    
325
  PrintAllRegs();
326

    
327
  PrintF("\n\n");
328
  // f0, f1, f2, ... f31.
329
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
330
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
331
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
332
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
333
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
334
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
335
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
336
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
337
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
338
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
339
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
340
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
341
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
342
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
343
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
344
  PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
345

    
346
#undef REG_INFO
347
#undef FPU_REG_INFO
348
}
349

    
350

    
351
void MipsDebugger::Debug() {
352
  intptr_t last_pc = -1;
353
  bool done = false;
354

    
355
#define COMMAND_SIZE 63
356
#define ARG_SIZE 255
357

    
358
#define STR(a) #a
359
#define XSTR(a) STR(a)
360

    
361
  char cmd[COMMAND_SIZE + 1];
362
  char arg1[ARG_SIZE + 1];
363
  char arg2[ARG_SIZE + 1];
364
  char* argv[3] = { cmd, arg1, arg2 };
365

    
366
  // Make sure to have a proper terminating character if reaching the limit.
367
  cmd[COMMAND_SIZE] = 0;
368
  arg1[ARG_SIZE] = 0;
369
  arg2[ARG_SIZE] = 0;
370

    
371
  // Undo all set breakpoints while running in the debugger shell. This will
372
  // make them invisible to all commands.
373
  UndoBreakpoints();
374

    
375
  while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
376
    if (last_pc != sim_->get_pc()) {
377
      disasm::NameConverter converter;
378
      disasm::Disassembler dasm(converter);
379
      // Use a reasonably large buffer.
380
      v8::internal::EmbeddedVector<char, 256> buffer;
381
      dasm.InstructionDecode(buffer,
382
                             reinterpret_cast<byte*>(sim_->get_pc()));
383
      PrintF("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
384
      last_pc = sim_->get_pc();
385
    }
386
    char* line = ReadLine("sim> ");
387
    if (line == NULL) {
388
      break;
389
    } else {
390
      char* last_input = sim_->last_debugger_input();
391
      if (strcmp(line, "\n") == 0 && last_input != NULL) {
392
        line = last_input;
393
      } else {
394
        // Ownership is transferred to sim_;
395
        sim_->set_last_debugger_input(line);
396
      }
397
      // Use sscanf to parse the individual parts of the command line. At the
398
      // moment no command expects more than two parameters.
399
      int argc = SScanF(line,
400
                        "%" XSTR(COMMAND_SIZE) "s "
401
                        "%" XSTR(ARG_SIZE) "s "
402
                        "%" XSTR(ARG_SIZE) "s",
403
                        cmd, arg1, arg2);
404
      if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
405
        Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
406
        if (!(instr->IsTrap()) ||
407
            instr->InstructionBits() == rtCallRedirInstr) {
408
          sim_->InstructionDecode(
409
              reinterpret_cast<Instruction*>(sim_->get_pc()));
410
        } else {
411
          // Allow si to jump over generated breakpoints.
412
          PrintF("/!\\ Jumping over generated breakpoint.\n");
413
          sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize);
414
        }
415
      } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
416
        // Execute the one instruction we broke at with breakpoints disabled.
417
        sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
418
        // Leave the debugger shell.
419
        done = true;
420
      } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
421
        if (argc == 2) {
422
          int32_t value;
423
          float fvalue;
424
          if (strcmp(arg1, "all") == 0) {
425
            PrintAllRegs();
426
          } else if (strcmp(arg1, "allf") == 0) {
427
            PrintAllRegsIncludingFPU();
428
          } else {
429
            int regnum = Registers::Number(arg1);
430
            int fpuregnum = FPURegisters::Number(arg1);
431

    
432
            if (regnum != kInvalidRegister) {
433
              value = GetRegisterValue(regnum);
434
              PrintF("%s: 0x%08x %d \n", arg1, value, value);
435
            } else if (fpuregnum != kInvalidFPURegister) {
436
              if (fpuregnum % 2 == 1) {
437
                value = GetFPURegisterValueInt(fpuregnum);
438
                fvalue = GetFPURegisterValueFloat(fpuregnum);
439
                PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
440
              } else {
441
                double dfvalue;
442
                int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
443
                int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
444
                dfvalue = GetFPURegisterValueDouble(fpuregnum);
445
                PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
446
                       FPURegisters::Name(fpuregnum+1),
447
                       FPURegisters::Name(fpuregnum),
448
                       lvalue1,
449
                       lvalue2,
450
                       dfvalue);
451
              }
452
            } else {
453
              PrintF("%s unrecognized\n", arg1);
454
            }
455
          }
456
        } else {
457
          if (argc == 3) {
458
            if (strcmp(arg2, "single") == 0) {
459
              int32_t value;
460
              float fvalue;
461
              int fpuregnum = FPURegisters::Number(arg1);
462

    
463
              if (fpuregnum != kInvalidFPURegister) {
464
                value = GetFPURegisterValueInt(fpuregnum);
465
                fvalue = GetFPURegisterValueFloat(fpuregnum);
466
                PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
467
              } else {
468
                PrintF("%s unrecognized\n", arg1);
469
              }
470
            } else {
471
              PrintF("print <fpu register> single\n");
472
            }
473
          } else {
474
            PrintF("print <register> or print <fpu register> single\n");
475
          }
476
        }
477
      } else if ((strcmp(cmd, "po") == 0)
478
                 || (strcmp(cmd, "printobject") == 0)) {
479
        if (argc == 2) {
480
          int32_t value;
481
          if (GetValue(arg1, &value)) {
482
            Object* obj = reinterpret_cast<Object*>(value);
483
            PrintF("%s: \n", arg1);
484
#ifdef DEBUG
485
            obj->PrintLn();
486
#else
487
            obj->ShortPrint();
488
            PrintF("\n");
489
#endif
490
          } else {
491
            PrintF("%s unrecognized\n", arg1);
492
          }
493
        } else {
494
          PrintF("printobject <value>\n");
495
        }
496
      } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
497
        int32_t* cur = NULL;
498
        int32_t* end = NULL;
499
        int next_arg = 1;
500

    
501
        if (strcmp(cmd, "stack") == 0) {
502
          cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
503
        } else {  // Command "mem".
504
          int32_t value;
505
          if (!GetValue(arg1, &value)) {
506
            PrintF("%s unrecognized\n", arg1);
507
            continue;
508
          }
509
          cur = reinterpret_cast<int32_t*>(value);
510
          next_arg++;
511
        }
512

    
513
        int32_t words;
514
        if (argc == next_arg) {
515
          words = 10;
516
        } else {
517
          if (!GetValue(argv[next_arg], &words)) {
518
            words = 10;
519
          }
520
        }
521
        end = cur + words;
522

    
523
        while (cur < end) {
524
          PrintF("  0x%08x:  0x%08x %10d",
525
                 reinterpret_cast<intptr_t>(cur), *cur, *cur);
526
          HeapObject* obj = reinterpret_cast<HeapObject*>(*cur);
527
          int value = *cur;
528
          Heap* current_heap = v8::internal::Isolate::Current()->heap();
529
          if (((value & 1) == 0) || current_heap->Contains(obj)) {
530
            PrintF(" (");
531
            if ((value & 1) == 0) {
532
              PrintF("smi %d", value / 2);
533
            } else {
534
              obj->ShortPrint();
535
            }
536
            PrintF(")");
537
          }
538
          PrintF("\n");
539
          cur++;
540
        }
541

    
542
      } else if ((strcmp(cmd, "disasm") == 0) ||
543
                 (strcmp(cmd, "dpc") == 0) ||
544
                 (strcmp(cmd, "di") == 0)) {
545
        disasm::NameConverter converter;
546
        disasm::Disassembler dasm(converter);
547
        // Use a reasonably large buffer.
548
        v8::internal::EmbeddedVector<char, 256> buffer;
549

    
550
        byte* cur = NULL;
551
        byte* end = NULL;
552

    
553
        if (argc == 1) {
554
          cur = reinterpret_cast<byte*>(sim_->get_pc());
555
          end = cur + (10 * Instruction::kInstrSize);
556
        } else if (argc == 2) {
557
          int regnum = Registers::Number(arg1);
558
          if (regnum != kInvalidRegister || strncmp(arg1, "0x", 2) == 0) {
559
            // The argument is an address or a register name.
560
            int32_t value;
561
            if (GetValue(arg1, &value)) {
562
              cur = reinterpret_cast<byte*>(value);
563
              // Disassemble 10 instructions at <arg1>.
564
              end = cur + (10 * Instruction::kInstrSize);
565
            }
566
          } else {
567
            // The argument is the number of instructions.
568
            int32_t value;
569
            if (GetValue(arg1, &value)) {
570
              cur = reinterpret_cast<byte*>(sim_->get_pc());
571
              // Disassemble <arg1> instructions.
572
              end = cur + (value * Instruction::kInstrSize);
573
            }
574
          }
575
        } else {
576
          int32_t value1;
577
          int32_t value2;
578
          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
579
            cur = reinterpret_cast<byte*>(value1);
580
            end = cur + (value2 * Instruction::kInstrSize);
581
          }
582
        }
583

    
584
        while (cur < end) {
585
          dasm.InstructionDecode(buffer, cur);
586
          PrintF("  0x%08x  %s\n",
587
              reinterpret_cast<intptr_t>(cur), buffer.start());
588
          cur += Instruction::kInstrSize;
589
        }
590
      } else if (strcmp(cmd, "gdb") == 0) {
591
        PrintF("relinquishing control to gdb\n");
592
        v8::internal::OS::DebugBreak();
593
        PrintF("regaining control from gdb\n");
594
      } else if (strcmp(cmd, "break") == 0) {
595
        if (argc == 2) {
596
          int32_t value;
597
          if (GetValue(arg1, &value)) {
598
            if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
599
              PrintF("setting breakpoint failed\n");
600
            }
601
          } else {
602
            PrintF("%s unrecognized\n", arg1);
603
          }
604
        } else {
605
          PrintF("break <address>\n");
606
        }
607
      } else if (strcmp(cmd, "del") == 0) {
608
        if (!DeleteBreakpoint(NULL)) {
609
          PrintF("deleting breakpoint failed\n");
610
        }
611
      } else if (strcmp(cmd, "flags") == 0) {
612
        PrintF("No flags on MIPS !\n");
613
      } else if (strcmp(cmd, "stop") == 0) {
614
        int32_t value;
615
        intptr_t stop_pc = sim_->get_pc() -
616
            2 * Instruction::kInstrSize;
617
        Instruction* stop_instr = reinterpret_cast<Instruction*>(stop_pc);
618
        Instruction* msg_address =
619
          reinterpret_cast<Instruction*>(stop_pc +
620
              Instruction::kInstrSize);
621
        if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
622
          // Remove the current stop.
623
          if (sim_->IsStopInstruction(stop_instr)) {
624
            stop_instr->SetInstructionBits(kNopInstr);
625
            msg_address->SetInstructionBits(kNopInstr);
626
          } else {
627
            PrintF("Not at debugger stop.\n");
628
          }
629
        } else if (argc == 3) {
630
          // Print information about all/the specified breakpoint(s).
631
          if (strcmp(arg1, "info") == 0) {
632
            if (strcmp(arg2, "all") == 0) {
633
              PrintF("Stop information:\n");
634
              for (uint32_t i = kMaxWatchpointCode + 1;
635
                   i <= kMaxStopCode;
636
                   i++) {
637
                sim_->PrintStopInfo(i);
638
              }
639
            } else if (GetValue(arg2, &value)) {
640
              sim_->PrintStopInfo(value);
641
            } else {
642
              PrintF("Unrecognized argument.\n");
643
            }
644
          } else if (strcmp(arg1, "enable") == 0) {
645
            // Enable all/the specified breakpoint(s).
646
            if (strcmp(arg2, "all") == 0) {
647
              for (uint32_t i = kMaxWatchpointCode + 1;
648
                   i <= kMaxStopCode;
649
                   i++) {
650
                sim_->EnableStop(i);
651
              }
652
            } else if (GetValue(arg2, &value)) {
653
              sim_->EnableStop(value);
654
            } else {
655
              PrintF("Unrecognized argument.\n");
656
            }
657
          } else if (strcmp(arg1, "disable") == 0) {
658
            // Disable all/the specified breakpoint(s).
659
            if (strcmp(arg2, "all") == 0) {
660
              for (uint32_t i = kMaxWatchpointCode + 1;
661
                   i <= kMaxStopCode;
662
                   i++) {
663
                sim_->DisableStop(i);
664
              }
665
            } else if (GetValue(arg2, &value)) {
666
              sim_->DisableStop(value);
667
            } else {
668
              PrintF("Unrecognized argument.\n");
669
            }
670
          }
671
        } else {
672
          PrintF("Wrong usage. Use help command for more information.\n");
673
        }
674
      } else if ((strcmp(cmd, "stat") == 0) || (strcmp(cmd, "st") == 0)) {
675
        // Print registers and disassemble.
676
        PrintAllRegs();
677
        PrintF("\n");
678

    
679
        disasm::NameConverter converter;
680
        disasm::Disassembler dasm(converter);
681
        // Use a reasonably large buffer.
682
        v8::internal::EmbeddedVector<char, 256> buffer;
683

    
684
        byte* cur = NULL;
685
        byte* end = NULL;
686

    
687
        if (argc == 1) {
688
          cur = reinterpret_cast<byte*>(sim_->get_pc());
689
          end = cur + (10 * Instruction::kInstrSize);
690
        } else if (argc == 2) {
691
          int32_t value;
692
          if (GetValue(arg1, &value)) {
693
            cur = reinterpret_cast<byte*>(value);
694
            // no length parameter passed, assume 10 instructions
695
            end = cur + (10 * Instruction::kInstrSize);
696
          }
697
        } else {
698
          int32_t value1;
699
          int32_t value2;
700
          if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
701
            cur = reinterpret_cast<byte*>(value1);
702
            end = cur + (value2 * Instruction::kInstrSize);
703
          }
704
        }
705

    
706
        while (cur < end) {
707
          dasm.InstructionDecode(buffer, cur);
708
          PrintF("  0x%08x  %s\n",
709
                 reinterpret_cast<intptr_t>(cur), buffer.start());
710
          cur += Instruction::kInstrSize;
711
        }
712
      } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
713
        PrintF("cont\n");
714
        PrintF("  continue execution (alias 'c')\n");
715
        PrintF("stepi\n");
716
        PrintF("  step one instruction (alias 'si')\n");
717
        PrintF("print <register>\n");
718
        PrintF("  print register content (alias 'p')\n");
719
        PrintF("  use register name 'all' to print all registers\n");
720
        PrintF("printobject <register>\n");
721
        PrintF("  print an object from a register (alias 'po')\n");
722
        PrintF("stack [<words>]\n");
723
        PrintF("  dump stack content, default dump 10 words)\n");
724
        PrintF("mem <address> [<words>]\n");
725
        PrintF("  dump memory content, default dump 10 words)\n");
726
        PrintF("flags\n");
727
        PrintF("  print flags\n");
728
        PrintF("disasm [<instructions>]\n");
729
        PrintF("disasm [<address/register>]\n");
730
        PrintF("disasm [[<address/register>] <instructions>]\n");
731
        PrintF("  disassemble code, default is 10 instructions\n");
732
        PrintF("  from pc (alias 'di')\n");
733
        PrintF("gdb\n");
734
        PrintF("  enter gdb\n");
735
        PrintF("break <address>\n");
736
        PrintF("  set a break point on the address\n");
737
        PrintF("del\n");
738
        PrintF("  delete the breakpoint\n");
739
        PrintF("stop feature:\n");
740
        PrintF("  Description:\n");
741
        PrintF("    Stops are debug instructions inserted by\n");
742
        PrintF("    the Assembler::stop() function.\n");
743
        PrintF("    When hitting a stop, the Simulator will\n");
744
        PrintF("    stop and and give control to the Debugger.\n");
745
        PrintF("    All stop codes are watched:\n");
746
        PrintF("    - They can be enabled / disabled: the Simulator\n");
747
        PrintF("       will / won't stop when hitting them.\n");
748
        PrintF("    - The Simulator keeps track of how many times they \n");
749
        PrintF("      are met. (See the info command.) Going over a\n");
750
        PrintF("      disabled stop still increases its counter. \n");
751
        PrintF("  Commands:\n");
752
        PrintF("    stop info all/<code> : print infos about number <code>\n");
753
        PrintF("      or all stop(s).\n");
754
        PrintF("    stop enable/disable all/<code> : enables / disables\n");
755
        PrintF("      all or number <code> stop(s)\n");
756
        PrintF("    stop unstop\n");
757
        PrintF("      ignore the stop instruction at the current location\n");
758
        PrintF("      from now on\n");
759
      } else {
760
        PrintF("Unknown command: %s\n", cmd);
761
      }
762
    }
763
  }
764

    
765
  // Add all the breakpoints back to stop execution and enter the debugger
766
  // shell when hit.
767
  RedoBreakpoints();
768

    
769
#undef COMMAND_SIZE
770
#undef ARG_SIZE
771

    
772
#undef STR
773
#undef XSTR
774
}
775

    
776

    
777
static bool ICacheMatch(void* one, void* two) {
778
  ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
779
  ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
780
  return one == two;
781
}
782

    
783

    
784
static uint32_t ICacheHash(void* key) {
785
  return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
786
}
787

    
788

    
789
static bool AllOnOnePage(uintptr_t start, int size) {
790
  intptr_t start_page = (start & ~CachePage::kPageMask);
791
  intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
792
  return start_page == end_page;
793
}
794

    
795

    
796
void Simulator::set_last_debugger_input(char* input) {
797
  DeleteArray(last_debugger_input_);
798
  last_debugger_input_ = input;
799
}
800

    
801

    
802
void Simulator::FlushICache(v8::internal::HashMap* i_cache,
803
                            void* start_addr,
804
                            size_t size) {
805
  intptr_t start = reinterpret_cast<intptr_t>(start_addr);
806
  int intra_line = (start & CachePage::kLineMask);
807
  start -= intra_line;
808
  size += intra_line;
809
  size = ((size - 1) | CachePage::kLineMask) + 1;
810
  int offset = (start & CachePage::kPageMask);
811
  while (!AllOnOnePage(start, size - 1)) {
812
    int bytes_to_flush = CachePage::kPageSize - offset;
813
    FlushOnePage(i_cache, start, bytes_to_flush);
814
    start += bytes_to_flush;
815
    size -= bytes_to_flush;
816
    ASSERT_EQ(0, start & CachePage::kPageMask);
817
    offset = 0;
818
  }
819
  if (size != 0) {
820
    FlushOnePage(i_cache, start, size);
821
  }
822
}
823

    
824

    
825
CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
826
  v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
827
                                                        ICacheHash(page),
828
                                                        true);
829
  if (entry->value == NULL) {
830
    CachePage* new_page = new CachePage();
831
    entry->value = new_page;
832
  }
833
  return reinterpret_cast<CachePage*>(entry->value);
834
}
835

    
836

    
837
// Flush from start up to and not including start + size.
838
void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
839
                             intptr_t start,
840
                             int size) {
841
  ASSERT(size <= CachePage::kPageSize);
842
  ASSERT(AllOnOnePage(start, size - 1));
843
  ASSERT((start & CachePage::kLineMask) == 0);
844
  ASSERT((size & CachePage::kLineMask) == 0);
845
  void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
846
  int offset = (start & CachePage::kPageMask);
847
  CachePage* cache_page = GetCachePage(i_cache, page);
848
  char* valid_bytemap = cache_page->ValidityByte(offset);
849
  memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
850
}
851

    
852

    
853
void Simulator::CheckICache(v8::internal::HashMap* i_cache,
854
                            Instruction* instr) {
855
  intptr_t address = reinterpret_cast<intptr_t>(instr);
856
  void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
857
  void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
858
  int offset = (address & CachePage::kPageMask);
859
  CachePage* cache_page = GetCachePage(i_cache, page);
860
  char* cache_valid_byte = cache_page->ValidityByte(offset);
861
  bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
862
  char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
863
  if (cache_hit) {
864
    // Check that the data in memory matches the contents of the I-cache.
865
    CHECK(memcmp(reinterpret_cast<void*>(instr),
866
                 cache_page->CachedData(offset),
867
                 Instruction::kInstrSize) == 0);
868
  } else {
869
    // Cache miss.  Load memory into the cache.
870
    OS::MemCopy(cached_line, line, CachePage::kLineLength);
871
    *cache_valid_byte = CachePage::LINE_VALID;
872
  }
873
}
874

    
875

    
876
void Simulator::Initialize(Isolate* isolate) {
877
  if (isolate->simulator_initialized()) return;
878
  isolate->set_simulator_initialized(true);
879
  ::v8::internal::ExternalReference::set_redirector(isolate,
880
                                                    &RedirectExternalReference);
881
}
882

    
883

    
884
Simulator::Simulator(Isolate* isolate) : isolate_(isolate) {
885
  i_cache_ = isolate_->simulator_i_cache();
886
  if (i_cache_ == NULL) {
887
    i_cache_ = new v8::internal::HashMap(&ICacheMatch);
888
    isolate_->set_simulator_i_cache(i_cache_);
889
  }
890
  Initialize(isolate);
891
  // Set up simulator support first. Some of this information is needed to
892
  // setup the architecture state.
893
  stack_ = reinterpret_cast<char*>(malloc(stack_size_));
894
  pc_modified_ = false;
895
  icount_ = 0;
896
  break_count_ = 0;
897
  break_pc_ = NULL;
898
  break_instr_ = 0;
899

    
900
  // Set up architecture state.
901
  // All registers are initialized to zero to start with.
902
  for (int i = 0; i < kNumSimuRegisters; i++) {
903
    registers_[i] = 0;
904
  }
905
  for (int i = 0; i < kNumFPURegisters; i++) {
906
    FPUregisters_[i] = 0;
907
  }
908
  FCSR_ = 0;
909

    
910
  // The sp is initialized to point to the bottom (high address) of the
911
  // allocated stack area. To be safe in potential stack underflows we leave
912
  // some buffer below.
913
  registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
914
  // The ra and pc are initialized to a known bad value that will cause an
915
  // access violation if the simulator ever tries to execute it.
916
  registers_[pc] = bad_ra;
917
  registers_[ra] = bad_ra;
918
  InitializeCoverage();
919
  for (int i = 0; i < kNumExceptions; i++) {
920
    exceptions[i] = 0;
921
  }
922

    
923
  last_debugger_input_ = NULL;
924
}
925

    
926

    
927
// When the generated code calls an external reference we need to catch that in
928
// the simulator.  The external reference will be a function compiled for the
929
// host architecture.  We need to call that function instead of trying to
930
// execute it with the simulator.  We do that by redirecting the external
931
// reference to a swi (software-interrupt) instruction that is handled by
932
// the simulator.  We write the original destination of the jump just at a known
933
// offset from the swi instruction so the simulator knows what to call.
934
class Redirection {
935
 public:
936
  Redirection(void* external_function, ExternalReference::Type type)
937
      : external_function_(external_function),
938
        swi_instruction_(rtCallRedirInstr),
939
        type_(type),
940
        next_(NULL) {
941
    Isolate* isolate = Isolate::Current();
942
    next_ = isolate->simulator_redirection();
943
    Simulator::current(isolate)->
944
        FlushICache(isolate->simulator_i_cache(),
945
                    reinterpret_cast<void*>(&swi_instruction_),
946
                    Instruction::kInstrSize);
947
    isolate->set_simulator_redirection(this);
948
  }
949

    
950
  void* address_of_swi_instruction() {
951
    return reinterpret_cast<void*>(&swi_instruction_);
952
  }
953

    
954
  void* external_function() { return external_function_; }
955
  ExternalReference::Type type() { return type_; }
956

    
957
  static Redirection* Get(void* external_function,
958
                          ExternalReference::Type type) {
959
    Isolate* isolate = Isolate::Current();
960
    Redirection* current = isolate->simulator_redirection();
961
    for (; current != NULL; current = current->next_) {
962
      if (current->external_function_ == external_function) return current;
963
    }
964
    return new Redirection(external_function, type);
965
  }
966

    
967
  static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
968
    char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
969
    char* addr_of_redirection =
970
        addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
971
    return reinterpret_cast<Redirection*>(addr_of_redirection);
972
  }
973

    
974
 private:
975
  void* external_function_;
976
  uint32_t swi_instruction_;
977
  ExternalReference::Type type_;
978
  Redirection* next_;
979
};
980

    
981

    
982
void* Simulator::RedirectExternalReference(void* external_function,
983
                                           ExternalReference::Type type) {
984
  Redirection* redirection = Redirection::Get(external_function, type);
985
  return redirection->address_of_swi_instruction();
986
}
987

    
988

    
989
// Get the active Simulator for the current thread.
990
Simulator* Simulator::current(Isolate* isolate) {
991
  v8::internal::Isolate::PerIsolateThreadData* isolate_data =
992
       isolate->FindOrAllocatePerThreadDataForThisThread();
993
  ASSERT(isolate_data != NULL);
994
  ASSERT(isolate_data != NULL);
995

    
996
  Simulator* sim = isolate_data->simulator();
997
  if (sim == NULL) {
998
    // TODO(146): delete the simulator object when a thread/isolate goes away.
999
    sim = new Simulator(isolate);
1000
    isolate_data->set_simulator(sim);
1001
  }
1002
  return sim;
1003
}
1004

    
1005

    
1006
// Sets the register in the architecture state. It will also deal with updating
1007
// Simulator internal state for special registers such as PC.
1008
void Simulator::set_register(int reg, int32_t value) {
1009
  ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1010
  if (reg == pc) {
1011
    pc_modified_ = true;
1012
  }
1013

    
1014
  // Zero register always holds 0.
1015
  registers_[reg] = (reg == 0) ? 0 : value;
1016
}
1017

    
1018

    
1019
void Simulator::set_dw_register(int reg, const int* dbl) {
1020
  ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1021
  registers_[reg] = dbl[0];
1022
  registers_[reg + 1] = dbl[1];
1023
}
1024

    
1025

    
1026
void Simulator::set_fpu_register(int fpureg, int32_t value) {
1027
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1028
  FPUregisters_[fpureg] = value;
1029
}
1030

    
1031

    
1032
void Simulator::set_fpu_register_float(int fpureg, float value) {
1033
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1034
  *BitCast<float*>(&FPUregisters_[fpureg]) = value;
1035
}
1036

    
1037

    
1038
void Simulator::set_fpu_register_double(int fpureg, double value) {
1039
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1040
  *BitCast<double*>(&FPUregisters_[fpureg]) = value;
1041
}
1042

    
1043

    
1044
// Get the register from the architecture state. This function does handle
1045
// the special case of accessing the PC register.
1046
int32_t Simulator::get_register(int reg) const {
1047
  ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
1048
  if (reg == 0)
1049
    return 0;
1050
  else
1051
    return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
1052
}
1053

    
1054

    
1055
double Simulator::get_double_from_register_pair(int reg) {
1056
  ASSERT((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0));
1057

    
1058
  double dm_val = 0.0;
1059
  // Read the bits from the unsigned integer register_[] array
1060
  // into the double precision floating point value and return it.
1061
  char buffer[2 * sizeof(registers_[0])];
1062
  OS::MemCopy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
1063
  OS::MemCopy(&dm_val, buffer, 2 * sizeof(registers_[0]));
1064
  return(dm_val);
1065
}
1066

    
1067

    
1068
int32_t Simulator::get_fpu_register(int fpureg) const {
1069
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1070
  return FPUregisters_[fpureg];
1071
}
1072

    
1073

    
1074
int64_t Simulator::get_fpu_register_long(int fpureg) const {
1075
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1076
  return *BitCast<int64_t*>(
1077
      const_cast<int32_t*>(&FPUregisters_[fpureg]));
1078
}
1079

    
1080

    
1081
float Simulator::get_fpu_register_float(int fpureg) const {
1082
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
1083
  return *BitCast<float*>(
1084
      const_cast<int32_t*>(&FPUregisters_[fpureg]));
1085
}
1086

    
1087

    
1088
double Simulator::get_fpu_register_double(int fpureg) const {
1089
  ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
1090
  return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
1091
}
1092

    
1093

    
1094
// Runtime FP routines take up to two double arguments and zero
1095
// or one integer arguments. All are constructed here,
1096
// from a0-a3 or f12 and f14.
1097
void Simulator::GetFpArgs(double* x, double* y, int32_t* z) {
1098
  if (!IsMipsSoftFloatABI) {
1099
    *x = get_fpu_register_double(12);
1100
    *y = get_fpu_register_double(14);
1101
    *z = get_register(a2);
1102
  } else {
1103
    // We use a char buffer to get around the strict-aliasing rules which
1104
    // otherwise allow the compiler to optimize away the copy.
1105
    char buffer[sizeof(*x)];
1106
    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1107

    
1108
    // Registers a0 and a1 -> x.
1109
    reg_buffer[0] = get_register(a0);
1110
    reg_buffer[1] = get_register(a1);
1111
    OS::MemCopy(x, buffer, sizeof(buffer));
1112
    // Registers a2 and a3 -> y.
1113
    reg_buffer[0] = get_register(a2);
1114
    reg_buffer[1] = get_register(a3);
1115
    OS::MemCopy(y, buffer, sizeof(buffer));
1116
    // Register 2 -> z.
1117
    reg_buffer[0] = get_register(a2);
1118
    OS::MemCopy(z, buffer, sizeof(*z));
1119
  }
1120
}
1121

    
1122

    
1123
// The return value is either in v0/v1 or f0.
1124
void Simulator::SetFpResult(const double& result) {
1125
  if (!IsMipsSoftFloatABI) {
1126
    set_fpu_register_double(0, result);
1127
  } else {
1128
    char buffer[2 * sizeof(registers_[0])];
1129
    int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer);
1130
    OS::MemCopy(buffer, &result, sizeof(buffer));
1131
    // Copy result to v0 and v1.
1132
    set_register(v0, reg_buffer[0]);
1133
    set_register(v1, reg_buffer[1]);
1134
  }
1135
}
1136

    
1137

    
1138
// Helper functions for setting and testing the FCSR register's bits.
1139
void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
1140
  if (value) {
1141
    FCSR_ |= (1 << cc);
1142
  } else {
1143
    FCSR_ &= ~(1 << cc);
1144
  }
1145
}
1146

    
1147

    
1148
bool Simulator::test_fcsr_bit(uint32_t cc) {
1149
  return FCSR_ & (1 << cc);
1150
}
1151

    
1152

    
1153
// Sets the rounding error codes in FCSR based on the result of the rounding.
1154
// Returns true if the operation was invalid.
1155
bool Simulator::set_fcsr_round_error(double original, double rounded) {
1156
  bool ret = false;
1157

    
1158
  if (!std::isfinite(original) || !std::isfinite(rounded)) {
1159
    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1160
    ret = true;
1161
  }
1162

    
1163
  if (original != rounded) {
1164
    set_fcsr_bit(kFCSRInexactFlagBit, true);
1165
  }
1166

    
1167
  if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) {
1168
    set_fcsr_bit(kFCSRUnderflowFlagBit, true);
1169
    ret = true;
1170
  }
1171

    
1172
  if (rounded > INT_MAX || rounded < INT_MIN) {
1173
    set_fcsr_bit(kFCSROverflowFlagBit, true);
1174
    // The reference is not really clear but it seems this is required:
1175
    set_fcsr_bit(kFCSRInvalidOpFlagBit, true);
1176
    ret = true;
1177
  }
1178

    
1179
  return ret;
1180
}
1181

    
1182

    
1183
// Raw access to the PC register.
1184
void Simulator::set_pc(int32_t value) {
1185
  pc_modified_ = true;
1186
  registers_[pc] = value;
1187
}
1188

    
1189

    
1190
bool Simulator::has_bad_pc() const {
1191
  return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
1192
}
1193

    
1194

    
1195
// Raw access to the PC register without the special adjustment when reading.
1196
int32_t Simulator::get_pc() const {
1197
  return registers_[pc];
1198
}
1199

    
1200

    
1201
// The MIPS cannot do unaligned reads and writes.  On some MIPS platforms an
1202
// interrupt is caused.  On others it does a funky rotation thing.  For now we
1203
// simply disallow unaligned reads, but at some point we may want to move to
1204
// emulating the rotate behaviour.  Note that simulator runs have the runtime
1205
// system running directly on the host system and only generated code is
1206
// executed in the simulator.  Since the host is typically IA32 we will not
1207
// get the correct MIPS-like behaviour on unaligned accesses.
1208

    
1209
int Simulator::ReadW(int32_t addr, Instruction* instr) {
1210
  if (addr >=0 && addr < 0x400) {
1211
    // This has to be a NULL-dereference, drop into debugger.
1212
    PrintF("Memory read from bad address: 0x%08x, pc=0x%08x\n",
1213
           addr, reinterpret_cast<intptr_t>(instr));
1214
    MipsDebugger dbg(this);
1215
    dbg.Debug();
1216
  }
1217
  if ((addr & kPointerAlignmentMask) == 0) {
1218
    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1219
    return *ptr;
1220
  }
1221
  PrintF("Unaligned read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1222
         addr,
1223
         reinterpret_cast<intptr_t>(instr));
1224
  MipsDebugger dbg(this);
1225
  dbg.Debug();
1226
  return 0;
1227
}
1228

    
1229

    
1230
void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
1231
  if (addr >= 0 && addr < 0x400) {
1232
    // This has to be a NULL-dereference, drop into debugger.
1233
    PrintF("Memory write to bad address: 0x%08x, pc=0x%08x\n",
1234
           addr, reinterpret_cast<intptr_t>(instr));
1235
    MipsDebugger dbg(this);
1236
    dbg.Debug();
1237
  }
1238
  if ((addr & kPointerAlignmentMask) == 0) {
1239
    intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1240
    *ptr = value;
1241
    return;
1242
  }
1243
  PrintF("Unaligned write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1244
         addr,
1245
         reinterpret_cast<intptr_t>(instr));
1246
  MipsDebugger dbg(this);
1247
  dbg.Debug();
1248
}
1249

    
1250

    
1251
double Simulator::ReadD(int32_t addr, Instruction* instr) {
1252
  if ((addr & kDoubleAlignmentMask) == 0) {
1253
    double* ptr = reinterpret_cast<double*>(addr);
1254
    return *ptr;
1255
  }
1256
  PrintF("Unaligned (double) read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1257
         addr,
1258
         reinterpret_cast<intptr_t>(instr));
1259
  OS::Abort();
1260
  return 0;
1261
}
1262

    
1263

    
1264
void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
1265
  if ((addr & kDoubleAlignmentMask) == 0) {
1266
    double* ptr = reinterpret_cast<double*>(addr);
1267
    *ptr = value;
1268
    return;
1269
  }
1270
  PrintF("Unaligned (double) write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1271
         addr,
1272
         reinterpret_cast<intptr_t>(instr));
1273
  OS::Abort();
1274
}
1275

    
1276

    
1277
uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
1278
  if ((addr & 1) == 0) {
1279
    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1280
    return *ptr;
1281
  }
1282
  PrintF("Unaligned unsigned halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1283
         addr,
1284
         reinterpret_cast<intptr_t>(instr));
1285
  OS::Abort();
1286
  return 0;
1287
}
1288

    
1289

    
1290
int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
1291
  if ((addr & 1) == 0) {
1292
    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1293
    return *ptr;
1294
  }
1295
  PrintF("Unaligned signed halfword read at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1296
         addr,
1297
         reinterpret_cast<intptr_t>(instr));
1298
  OS::Abort();
1299
  return 0;
1300
}
1301

    
1302

    
1303
void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
1304
  if ((addr & 1) == 0) {
1305
    uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1306
    *ptr = value;
1307
    return;
1308
  }
1309
  PrintF("Unaligned unsigned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1310
         addr,
1311
         reinterpret_cast<intptr_t>(instr));
1312
  OS::Abort();
1313
}
1314

    
1315

    
1316
void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
1317
  if ((addr & 1) == 0) {
1318
    int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1319
    *ptr = value;
1320
    return;
1321
  }
1322
  PrintF("Unaligned halfword write at 0x%08x, pc=0x%08" V8PRIxPTR "\n",
1323
         addr,
1324
         reinterpret_cast<intptr_t>(instr));
1325
  OS::Abort();
1326
}
1327

    
1328

    
1329
uint32_t Simulator::ReadBU(int32_t addr) {
1330
  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1331
  return *ptr & 0xff;
1332
}
1333

    
1334

    
1335
int32_t Simulator::ReadB(int32_t addr) {
1336
  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1337
  return *ptr;
1338
}
1339

    
1340

    
1341
void Simulator::WriteB(int32_t addr, uint8_t value) {
1342
  uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1343
  *ptr = value;
1344
}
1345

    
1346

    
1347
void Simulator::WriteB(int32_t addr, int8_t value) {
1348
  int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1349
  *ptr = value;
1350
}
1351

    
1352

    
1353
// Returns the limit of the stack area to enable checking for stack overflows.
1354
uintptr_t Simulator::StackLimit() const {
1355
  // Leave a safety margin of 1024 bytes to prevent overrunning the stack when
1356
  // pushing values.
1357
  return reinterpret_cast<uintptr_t>(stack_) + 1024;
1358
}
1359

    
1360

    
1361
// Unsupported instructions use Format to print an error and stop execution.
1362
void Simulator::Format(Instruction* instr, const char* format) {
1363
  PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
1364
         reinterpret_cast<intptr_t>(instr), format);
1365
  UNIMPLEMENTED_MIPS();
1366
}
1367

    
1368

    
1369
// Calls into the V8 runtime are based on this very simple interface.
1370
// Note: To be able to return two values from some calls the code in runtime.cc
1371
// uses the ObjectPair which is essentially two 32-bit values stuffed into a
1372
// 64-bit value. With the code below we assume that all runtime calls return
1373
// 64 bits of result. If they don't, the v1 result register contains a bogus
1374
// value, which is fine because it is caller-saved.
1375
typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1376
                                        int32_t arg1,
1377
                                        int32_t arg2,
1378
                                        int32_t arg3,
1379
                                        int32_t arg4,
1380
                                        int32_t arg5);
1381

    
1382
// These prototypes handle the four types of FP calls.
1383
typedef int64_t (*SimulatorRuntimeCompareCall)(double darg0, double darg1);
1384
typedef double (*SimulatorRuntimeFPFPCall)(double darg0, double darg1);
1385
typedef double (*SimulatorRuntimeFPCall)(double darg0);
1386
typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
1387

    
1388
// This signature supports direct call in to API function native callback
1389
// (refer to InvocationCallback in v8.h).
1390
typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1391
typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, int32_t arg1);
1392

    
1393
// This signature supports direct call to accessor getter callback.
1394
typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
1395
typedef void (*SimulatorRuntimeProfilingGetterCall)(
1396
    int32_t arg0, int32_t arg1, int32_t arg2);
1397

    
1398
// Software interrupt instructions are used by the simulator to call into the
1399
// C-based V8 runtime. They are also used for debugging with simulator.
1400
void Simulator::SoftwareInterrupt(Instruction* instr) {
1401
  // There are several instructions that could get us here,
1402
  // the break_ instruction, or several variants of traps. All
1403
  // Are "SPECIAL" class opcode, and are distinuished by function.
1404
  int32_t func = instr->FunctionFieldRaw();
1405
  uint32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1406

    
1407
  // We first check if we met a call_rt_redirected.
1408
  if (instr->InstructionBits() == rtCallRedirInstr) {
1409
    Redirection* redirection = Redirection::FromSwiInstruction(instr);
1410
    int32_t arg0 = get_register(a0);
1411
    int32_t arg1 = get_register(a1);
1412
    int32_t arg2 = get_register(a2);
1413
    int32_t arg3 = get_register(a3);
1414

    
1415
    int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1416
    // Args 4 and 5 are on the stack after the reserved space for args 0..3.
1417
    int32_t arg4 = stack_pointer[4];
1418
    int32_t arg5 = stack_pointer[5];
1419

    
1420
    bool fp_call =
1421
         (redirection->type() == ExternalReference::BUILTIN_FP_FP_CALL) ||
1422
         (redirection->type() == ExternalReference::BUILTIN_COMPARE_CALL) ||
1423
         (redirection->type() == ExternalReference::BUILTIN_FP_CALL) ||
1424
         (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL);
1425

    
1426
    if (!IsMipsSoftFloatABI) {
1427
      // With the hard floating point calling convention, double
1428
      // arguments are passed in FPU registers. Fetch the arguments
1429
      // from there and call the builtin using soft floating point
1430
      // convention.
1431
      switch (redirection->type()) {
1432
      case ExternalReference::BUILTIN_FP_FP_CALL:
1433
      case ExternalReference::BUILTIN_COMPARE_CALL:
1434
        arg0 = get_fpu_register(f12);
1435
        arg1 = get_fpu_register(f13);
1436
        arg2 = get_fpu_register(f14);
1437
        arg3 = get_fpu_register(f15);
1438
        break;
1439
      case ExternalReference::BUILTIN_FP_CALL:
1440
        arg0 = get_fpu_register(f12);
1441
        arg1 = get_fpu_register(f13);
1442
        break;
1443
      case ExternalReference::BUILTIN_FP_INT_CALL:
1444
        arg0 = get_fpu_register(f12);
1445
        arg1 = get_fpu_register(f13);
1446
        arg2 = get_register(a2);
1447
        break;
1448
      default:
1449
        break;
1450
      }
1451
    }
1452

    
1453
    // This is dodgy but it works because the C entry stubs are never moved.
1454
    // See comment in codegen-arm.cc and bug 1242173.
1455
    int32_t saved_ra = get_register(ra);
1456

    
1457
    intptr_t external =
1458
          reinterpret_cast<intptr_t>(redirection->external_function());
1459

    
1460
    // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1461
    // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1462
    // simulator. Soft-float has additional abstraction of ExternalReference,
1463
    // to support serialization.
1464
    if (fp_call) {
1465
      double dval0, dval1;  // one or two double parameters
1466
      int32_t ival;         // zero or one integer parameters
1467
      int64_t iresult = 0;  // integer return value
1468
      double dresult = 0;   // double return value
1469
      GetFpArgs(&dval0, &dval1, &ival);
1470
      SimulatorRuntimeCall generic_target =
1471
          reinterpret_cast<SimulatorRuntimeCall>(external);
1472
      if (::v8::internal::FLAG_trace_sim) {
1473
        switch (redirection->type()) {
1474
          case ExternalReference::BUILTIN_FP_FP_CALL:
1475
          case ExternalReference::BUILTIN_COMPARE_CALL:
1476
            PrintF("Call to host function at %p with args %f, %f",
1477
                   FUNCTION_ADDR(generic_target), dval0, dval1);
1478
            break;
1479
          case ExternalReference::BUILTIN_FP_CALL:
1480
            PrintF("Call to host function at %p with arg %f",
1481
                FUNCTION_ADDR(generic_target), dval0);
1482
            break;
1483
          case ExternalReference::BUILTIN_FP_INT_CALL:
1484
            PrintF("Call to host function at %p with args %f, %d",
1485
                   FUNCTION_ADDR(generic_target), dval0, ival);
1486
            break;
1487
          default:
1488
            UNREACHABLE();
1489
            break;
1490
        }
1491
      }
1492
      switch (redirection->type()) {
1493
      case ExternalReference::BUILTIN_COMPARE_CALL: {
1494
        SimulatorRuntimeCompareCall target =
1495
          reinterpret_cast<SimulatorRuntimeCompareCall>(external);
1496
        iresult = target(dval0, dval1);
1497
        set_register(v0, static_cast<int32_t>(iresult));
1498
        set_register(v1, static_cast<int32_t>(iresult >> 32));
1499
        break;
1500
      }
1501
      case ExternalReference::BUILTIN_FP_FP_CALL: {
1502
        SimulatorRuntimeFPFPCall target =
1503
          reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
1504
        dresult = target(dval0, dval1);
1505
        SetFpResult(dresult);
1506
        break;
1507
      }
1508
      case ExternalReference::BUILTIN_FP_CALL: {
1509
        SimulatorRuntimeFPCall target =
1510
          reinterpret_cast<SimulatorRuntimeFPCall>(external);
1511
        dresult = target(dval0);
1512
        SetFpResult(dresult);
1513
        break;
1514
      }
1515
      case ExternalReference::BUILTIN_FP_INT_CALL: {
1516
        SimulatorRuntimeFPIntCall target =
1517
          reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
1518
        dresult = target(dval0, ival);
1519
        SetFpResult(dresult);
1520
        break;
1521
      }
1522
      default:
1523
        UNREACHABLE();
1524
        break;
1525
      }
1526
      if (::v8::internal::FLAG_trace_sim) {
1527
        switch (redirection->type()) {
1528
        case ExternalReference::BUILTIN_COMPARE_CALL:
1529
          PrintF("Returned %08x\n", static_cast<int32_t>(iresult));
1530
          break;
1531
        case ExternalReference::BUILTIN_FP_FP_CALL:
1532
        case ExternalReference::BUILTIN_FP_CALL:
1533
        case ExternalReference::BUILTIN_FP_INT_CALL:
1534
          PrintF("Returned %f\n", dresult);
1535
          break;
1536
        default:
1537
          UNREACHABLE();
1538
          break;
1539
        }
1540
      }
1541
    } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1542
      if (::v8::internal::FLAG_trace_sim) {
1543
        PrintF("Call to host function at %p args %08x\n",
1544
            reinterpret_cast<void*>(external), arg0);
1545
      }
1546
      SimulatorRuntimeDirectApiCall target =
1547
          reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
1548
      target(arg0);
1549
    } else if (
1550
        redirection->type() == ExternalReference::PROFILING_API_CALL) {
1551
      if (::v8::internal::FLAG_trace_sim) {
1552
        PrintF("Call to host function at %p args %08x %08x\n",
1553
            reinterpret_cast<void*>(external), arg0, arg1);
1554
      }
1555
      SimulatorRuntimeProfilingApiCall target =
1556
          reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
1557
      target(arg0, arg1);
1558
    } else if (
1559
        redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1560
      if (::v8::internal::FLAG_trace_sim) {
1561
        PrintF("Call to host function at %p args %08x %08x\n",
1562
            reinterpret_cast<void*>(external), arg0, arg1);
1563
      }
1564
      SimulatorRuntimeDirectGetterCall target =
1565
          reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
1566
      target(arg0, arg1);
1567
    } else if (
1568
        redirection->type() == ExternalReference::PROFILING_GETTER_CALL) {
1569
      if (::v8::internal::FLAG_trace_sim) {
1570
        PrintF("Call to host function at %p args %08x %08x %08x\n",
1571
            reinterpret_cast<void*>(external), arg0, arg1, arg2);
1572
      }
1573
      SimulatorRuntimeProfilingGetterCall target =
1574
          reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
1575
      target(arg0, arg1, arg2);
1576
    } else {
1577
      SimulatorRuntimeCall target =
1578
                  reinterpret_cast<SimulatorRuntimeCall>(external);
1579
      if (::v8::internal::FLAG_trace_sim) {
1580
        PrintF(
1581
            "Call to host function at %p "
1582
            "args %08x, %08x, %08x, %08x, %08x, %08x\n",
1583
            FUNCTION_ADDR(target),
1584
            arg0,
1585
            arg1,
1586
            arg2,
1587
            arg3,
1588
            arg4,
1589
            arg5);
1590
      }
1591
      int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1592
      set_register(v0, static_cast<int32_t>(result));
1593
      set_register(v1, static_cast<int32_t>(result >> 32));
1594
    }
1595
    if (::v8::internal::FLAG_trace_sim) {
1596
      PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
1597
    }
1598
    set_register(ra, saved_ra);
1599
    set_pc(get_register(ra));
1600

    
1601
  } else if (func == BREAK && code <= kMaxStopCode) {
1602
    if (IsWatchpoint(code)) {
1603
      PrintWatchpoint(code);
1604
    } else {
1605
      IncreaseStopCounter(code);
1606
      HandleStop(code, instr);
1607
    }
1608
  } else {
1609
    // All remaining break_ codes, and all traps are handled here.
1610
    MipsDebugger dbg(this);
1611
    dbg.Debug();
1612
  }
1613
}
1614

    
1615

    
1616
// Stop helper functions.
1617
bool Simulator::IsWatchpoint(uint32_t code) {
1618
  return (code <= kMaxWatchpointCode);
1619
}
1620

    
1621

    
1622
void Simulator::PrintWatchpoint(uint32_t code) {
1623
  MipsDebugger dbg(this);
1624
  ++break_count_;
1625
  PrintF("\n---- break %d marker: %3d  (instr count: %8d) ----------"
1626
         "----------------------------------",
1627
         code, break_count_, icount_);
1628
  dbg.PrintAllRegs();  // Print registers and continue running.
1629
}
1630

    
1631

    
1632
void Simulator::HandleStop(uint32_t code, Instruction* instr) {
1633
  // Stop if it is enabled, otherwise go on jumping over the stop
1634
  // and the message address.
1635
  if (IsEnabledStop(code)) {
1636
    MipsDebugger dbg(this);
1637
    dbg.Stop(instr);
1638
  } else {
1639
    set_pc(get_pc() + 2 * Instruction::kInstrSize);
1640
  }
1641
}
1642

    
1643

    
1644
bool Simulator::IsStopInstruction(Instruction* instr) {
1645
  int32_t func = instr->FunctionFieldRaw();
1646
  uint32_t code = static_cast<uint32_t>(instr->Bits(25, 6));
1647
  return (func == BREAK) && code > kMaxWatchpointCode && code <= kMaxStopCode;
1648
}
1649

    
1650

    
1651
bool Simulator::IsEnabledStop(uint32_t code) {
1652
  ASSERT(code <= kMaxStopCode);
1653
  ASSERT(code > kMaxWatchpointCode);
1654
  return !(watched_stops_[code].count & kStopDisabledBit);
1655
}
1656

    
1657

    
1658
void Simulator::EnableStop(uint32_t code) {
1659
  if (!IsEnabledStop(code)) {
1660
    watched_stops_[code].count &= ~kStopDisabledBit;
1661
  }
1662
}
1663

    
1664

    
1665
void Simulator::DisableStop(uint32_t code) {
1666
  if (IsEnabledStop(code)) {
1667
    watched_stops_[code].count |= kStopDisabledBit;
1668
  }
1669
}
1670

    
1671

    
1672
void Simulator::IncreaseStopCounter(uint32_t code) {
1673
  ASSERT(code <= kMaxStopCode);
1674
  if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
1675
    PrintF("Stop counter for code %i has overflowed.\n"
1676
           "Enabling this code and reseting the counter to 0.\n", code);
1677
    watched_stops_[code].count = 0;
1678
    EnableStop(code);
1679
  } else {
1680
    watched_stops_[code].count++;
1681
  }
1682
}
1683

    
1684

    
1685
// Print a stop status.
1686
void Simulator::PrintStopInfo(uint32_t code) {
1687
  if (code <= kMaxWatchpointCode) {
1688
    PrintF("That is a watchpoint, not a stop.\n");
1689
    return;
1690
  } else if (code > kMaxStopCode) {
1691
    PrintF("Code too large, only %u stops can be used\n", kMaxStopCode + 1);
1692
    return;
1693
  }
1694
  const char* state = IsEnabledStop(code) ? "Enabled" : "Disabled";
1695
  int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
1696
  // Don't print the state of unused breakpoints.
1697
  if (count != 0) {
1698
    if (watched_stops_[code].desc) {
1699
      PrintF("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
1700
             code, code, state, count, watched_stops_[code].desc);
1701
    } else {
1702
      PrintF("stop %i - 0x%x: \t%s, \tcounter = %i\n",
1703
             code, code, state, count);
1704
    }
1705
  }
1706
}
1707

    
1708

    
1709
void Simulator::SignalExceptions() {
1710
  for (int i = 1; i < kNumExceptions; i++) {
1711
    if (exceptions[i] != 0) {
1712
      V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
1713
    }
1714
  }
1715
}
1716

    
1717

    
1718
// Handle execution based on instruction types.
1719

    
1720
void Simulator::ConfigureTypeRegister(Instruction* instr,
1721
                                      int32_t& alu_out,
1722
                                      int64_t& i64hilo,
1723
                                      uint64_t& u64hilo,
1724
                                      int32_t& next_pc,
1725
                                      bool& do_interrupt) {
1726
  // Every local variable declared here needs to be const.
1727
  // This is to make sure that changed values are sent back to
1728
  // DecodeTypeRegister correctly.
1729

    
1730
  // Instruction fields.
1731
  const Opcode   op     = instr->OpcodeFieldRaw();
1732
  const int32_t  rs_reg = instr->RsValue();
1733
  const int32_t  rs     = get_register(rs_reg);
1734
  const uint32_t rs_u   = static_cast<uint32_t>(rs);
1735
  const int32_t  rt_reg = instr->RtValue();
1736
  const int32_t  rt     = get_register(rt_reg);
1737
  const uint32_t rt_u   = static_cast<uint32_t>(rt);
1738
  const int32_t  rd_reg = instr->RdValue();
1739
  const uint32_t sa     = instr->SaValue();
1740

    
1741
  const int32_t  fs_reg = instr->FsValue();
1742

    
1743

    
1744
  // ---------- Configuration.
1745
  switch (op) {
1746
    case COP1:    // Coprocessor instructions.
1747
      switch (instr->RsFieldRaw()) {
1748
        case BC1:   // Handled in DecodeTypeImmed, should never come here.
1749
          UNREACHABLE();
1750
          break;
1751
        case CFC1:
1752
          // At the moment only FCSR is supported.
1753
          ASSERT(fs_reg == kFCSRRegister);
1754
          alu_out = FCSR_;
1755
          break;
1756
        case MFC1:
1757
          alu_out = get_fpu_register(fs_reg);
1758
          break;
1759
        case MFHC1:
1760
          UNIMPLEMENTED_MIPS();
1761
          break;
1762
        case CTC1:
1763
        case MTC1:
1764
        case MTHC1:
1765
          // Do the store in the execution step.
1766
          break;
1767
        case S:
1768
        case D:
1769
        case W:
1770
        case L:
1771
        case PS:
1772
          // Do everything in the execution step.
1773
          break;
1774
        default:
1775
          UNIMPLEMENTED_MIPS();
1776
      };
1777
      break;
1778
    case COP1X:
1779
      break;
1780
    case SPECIAL:
1781
      switch (instr->FunctionFieldRaw()) {
1782
        case JR:
1783
        case JALR:
1784
          next_pc = get_register(instr->RsValue());
1785
          break;
1786
        case SLL:
1787
          alu_out = rt << sa;
1788
          break;
1789
        case SRL:
1790
          if (rs_reg == 0) {
1791
            // Regular logical right shift of a word by a fixed number of
1792
            // bits instruction. RS field is always equal to 0.
1793
            alu_out = rt_u >> sa;
1794
          } else {
1795
            // Logical right-rotate of a word by a fixed number of bits. This
1796
            // is special case of SRL instruction, added in MIPS32 Release 2.
1797
            // RS field is equal to 00001.
1798
            alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1799
          }
1800
          break;
1801
        case SRA:
1802
          alu_out = rt >> sa;
1803
          break;
1804
        case SLLV:
1805
          alu_out = rt << rs;
1806
          break;
1807
        case SRLV:
1808
          if (sa == 0) {
1809
            // Regular logical right-shift of a word by a variable number of
1810
            // bits instruction. SA field is always equal to 0.
1811
            alu_out = rt_u >> rs;
1812
          } else {
1813
            // Logical right-rotate of a word by a variable number of bits.
1814
            // This is special case od SRLV instruction, added in MIPS32
1815
            // Release 2. SA field is equal to 00001.
1816
            alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1817
          }
1818
          break;
1819
        case SRAV:
1820
          alu_out = rt >> rs;
1821
          break;
1822
        case MFHI:
1823
          alu_out = get_register(HI);
1824
          break;
1825
        case MFLO:
1826
          alu_out = get_register(LO);
1827
          break;
1828
        case MULT:
1829
          i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
1830
          break;
1831
        case MULTU:
1832
          u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
1833
          break;
1834
        case ADD:
1835
          if (HaveSameSign(rs, rt)) {
1836
            if (rs > 0) {
1837
              exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
1838
            } else if (rs < 0) {
1839
              exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt);
1840
            }
1841
          }
1842
          alu_out = rs + rt;
1843
          break;
1844
        case ADDU:
1845
          alu_out = rs + rt;
1846
          break;
1847
        case SUB:
1848
          if (!HaveSameSign(rs, rt)) {
1849
            if (rs > 0) {
1850
              exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue + rt);
1851
            } else if (rs < 0) {
1852
              exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue + rt);
1853
            }
1854
          }
1855
          alu_out = rs - rt;
1856
          break;
1857
        case SUBU:
1858
          alu_out = rs - rt;
1859
          break;
1860
        case AND:
1861
          alu_out = rs & rt;
1862
          break;
1863
        case OR:
1864
          alu_out = rs | rt;
1865
          break;
1866
        case XOR:
1867
          alu_out = rs ^ rt;
1868
          break;
1869
        case NOR:
1870
          alu_out = ~(rs | rt);
1871
          break;
1872
        case SLT:
1873
          alu_out = rs < rt ? 1 : 0;
1874
          break;
1875
        case SLTU:
1876
          alu_out = rs_u < rt_u ? 1 : 0;
1877
          break;
1878
        // Break and trap instructions.
1879
        case BREAK:
1880

    
1881
          do_interrupt = true;
1882
          break;
1883
        case TGE:
1884
          do_interrupt = rs >= rt;
1885
          break;
1886
        case TGEU:
1887
          do_interrupt = rs_u >= rt_u;
1888
          break;
1889
        case TLT:
1890
          do_interrupt = rs < rt;
1891
          break;
1892
        case TLTU:
1893
          do_interrupt = rs_u < rt_u;
1894
          break;
1895
        case TEQ:
1896
          do_interrupt = rs == rt;
1897
          break;
1898
        case TNE:
1899
          do_interrupt = rs != rt;
1900
          break;
1901
        case MOVN:
1902
        case MOVZ:
1903
        case MOVCI:
1904
          // No action taken on decode.
1905
          break;
1906
        case DIV:
1907
        case DIVU:
1908
          // div and divu never raise exceptions.
1909
          break;
1910
        default:
1911
          UNREACHABLE();
1912
      };
1913
      break;
1914
    case SPECIAL2:
1915
      switch (instr->FunctionFieldRaw()) {
1916
        case MUL:
1917
          alu_out = rs_u * rt_u;  // Only the lower 32 bits are kept.
1918
          break;
1919
        case CLZ:
1920
          alu_out = __builtin_clz(rs_u);
1921
          break;
1922
        default:
1923
          UNREACHABLE();
1924
      };
1925
      break;
1926
    case SPECIAL3:
1927
      switch (instr->FunctionFieldRaw()) {
1928
        case INS: {   // Mips32r2 instruction.
1929
          // Interpret rd field as 5-bit msb of insert.
1930
          uint16_t msb = rd_reg;
1931
          // Interpret sa field as 5-bit lsb of insert.
1932
          uint16_t lsb = sa;
1933
          uint16_t size = msb - lsb + 1;
1934
          uint32_t mask = (1 << size) - 1;
1935
          alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1936
          break;
1937
        }
1938
        case EXT: {   // Mips32r2 instruction.
1939
          // Interpret rd field as 5-bit msb of extract.
1940
          uint16_t msb = rd_reg;
1941
          // Interpret sa field as 5-bit lsb of extract.
1942
          uint16_t lsb = sa;
1943
          uint16_t size = msb + 1;
1944
          uint32_t mask = (1 << size) - 1;
1945
          alu_out = (rs_u & (mask << lsb)) >> lsb;
1946
          break;
1947
        }
1948
        default:
1949
          UNREACHABLE();
1950
      };
1951
      break;
1952
    default:
1953
      UNREACHABLE();
1954
  };
1955
}
1956

    
1957

    
1958
void Simulator::DecodeTypeRegister(Instruction* instr) {
1959
  // Instruction fields.
1960
  const Opcode   op     = instr->OpcodeFieldRaw();
1961
  const int32_t  rs_reg = instr->RsValue();
1962
  const int32_t  rs     = get_register(rs_reg);
1963
  const uint32_t rs_u   = static_cast<uint32_t>(rs);
1964
  const int32_t  rt_reg = instr->RtValue();
1965
  const int32_t  rt     = get_register(rt_reg);
1966
  const uint32_t rt_u   = static_cast<uint32_t>(rt);
1967
  const int32_t  rd_reg = instr->RdValue();
1968

    
1969
  const int32_t  fr_reg = instr->FrValue();
1970
  const int32_t  fs_reg = instr->FsValue();
1971
  const int32_t  ft_reg = instr->FtValue();
1972
  const int32_t  fd_reg = instr->FdValue();
1973
  int64_t  i64hilo = 0;
1974
  uint64_t u64hilo = 0;
1975

    
1976
  // ALU output.
1977
  // It should not be used as is. Instructions using it should always
1978
  // initialize it first.
1979
  int32_t alu_out = 0x12345678;
1980

    
1981
  // For break and trap instructions.
1982
  bool do_interrupt = false;
1983

    
1984
  // For jr and jalr.
1985
  // Get current pc.
1986
  int32_t current_pc = get_pc();
1987
  // Next pc
1988
  int32_t next_pc = 0;
1989

    
1990
  // Set up the variables if needed before executing the instruction.
1991
  ConfigureTypeRegister(instr,
1992
                        alu_out,
1993
                        i64hilo,
1994
                        u64hilo,
1995
                        next_pc,
1996
                        do_interrupt);
1997

    
1998
  // ---------- Raise exceptions triggered.
1999
  SignalExceptions();
2000

    
2001
  // ---------- Execution.
2002
  switch (op) {
2003
    case COP1:
2004
      switch (instr->RsFieldRaw()) {
2005
        case BC1:   // Branch on coprocessor condition.
2006
          UNREACHABLE();
2007
          break;
2008
        case CFC1:
2009
          set_register(rt_reg, alu_out);
2010
        case MFC1:
2011
          set_register(rt_reg, alu_out);
2012
          break;
2013
        case MFHC1:
2014
          UNIMPLEMENTED_MIPS();
2015
          break;
2016
        case CTC1:
2017
          // At the moment only FCSR is supported.
2018
          ASSERT(fs_reg == kFCSRRegister);
2019
          FCSR_ = registers_[rt_reg];
2020
          break;
2021
        case MTC1:
2022
          FPUregisters_[fs_reg] = registers_[rt_reg];
2023
          break;
2024
        case MTHC1:
2025
          UNIMPLEMENTED_MIPS();
2026
          break;
2027
        case S:
2028
          float f;
2029
          switch (instr->FunctionFieldRaw()) {
2030
            case CVT_D_S:
2031
              f = get_fpu_register_float(fs_reg);
2032
              set_fpu_register_double(fd_reg, static_cast<double>(f));
2033
              break;
2034
            case CVT_W_S:
2035
            case CVT_L_S:
2036
            case TRUNC_W_S:
2037
            case TRUNC_L_S:
2038
            case ROUND_W_S:
2039
            case ROUND_L_S:
2040
            case FLOOR_W_S:
2041
            case FLOOR_L_S:
2042
            case CEIL_W_S:
2043
            case CEIL_L_S:
2044
            case CVT_PS_S:
2045
              UNIMPLEMENTED_MIPS();
2046
              break;
2047
            default:
2048
              UNREACHABLE();
2049
          }
2050
          break;
2051
        case D:
2052
          double ft, fs;
2053
          uint32_t cc, fcsr_cc;
2054
          int64_t  i64;
2055
          fs = get_fpu_register_double(fs_reg);
2056
          ft = get_fpu_register_double(ft_reg);
2057
          cc = instr->FCccValue();
2058
          fcsr_cc = get_fcsr_condition_bit(cc);
2059
          switch (instr->FunctionFieldRaw()) {
2060
            case ADD_D:
2061
              set_fpu_register_double(fd_reg, fs + ft);
2062
              break;
2063
            case SUB_D:
2064
              set_fpu_register_double(fd_reg, fs - ft);
2065
              break;
2066
            case MUL_D:
2067
              set_fpu_register_double(fd_reg, fs * ft);
2068
              break;
2069
            case DIV_D:
2070
              set_fpu_register_double(fd_reg, fs / ft);
2071
              break;
2072
            case ABS_D:
2073
              set_fpu_register_double(fd_reg, fabs(fs));
2074
              break;
2075
            case MOV_D:
2076
              set_fpu_register_double(fd_reg, fs);
2077
              break;
2078
            case NEG_D:
2079
              set_fpu_register_double(fd_reg, -fs);
2080
              break;
2081
            case SQRT_D:
2082
              set_fpu_register_double(fd_reg, sqrt(fs));
2083
              break;
2084
            case C_UN_D:
2085
              set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft));
2086
              break;
2087
            case C_EQ_D:
2088
              set_fcsr_bit(fcsr_cc, (fs == ft));
2089
              break;
2090
            case C_UEQ_D:
2091
              set_fcsr_bit(fcsr_cc,
2092
                           (fs == ft) || (std::isnan(fs) || std::isnan(ft)));
2093
              break;
2094
            case C_OLT_D:
2095
              set_fcsr_bit(fcsr_cc, (fs < ft));
2096
              break;
2097
            case C_ULT_D:
2098
              set_fcsr_bit(fcsr_cc,
2099
                           (fs < ft) || (std::isnan(fs) || std::isnan(ft)));
2100
              break;
2101
            case C_OLE_D:
2102
              set_fcsr_bit(fcsr_cc, (fs <= ft));
2103
              break;
2104
            case C_ULE_D:
2105
              set_fcsr_bit(fcsr_cc,
2106
                           (fs <= ft) || (std::isnan(fs) || std::isnan(ft)));
2107
              break;
2108
            case CVT_W_D:   // Convert double to word.
2109
              // Rounding modes are not yet supported.
2110
              ASSERT((FCSR_ & 3) == 0);
2111
              // In rounding mode 0 it should behave like ROUND.
2112
            case ROUND_W_D:  // Round double to word (round half to even).
2113
              {
2114
                double rounded = floor(fs + 0.5);
2115
                int32_t result = static_cast<int32_t>(rounded);
2116
                if ((result & 1) != 0 && result - fs == 0.5) {
2117
                  // If the number is halfway between two integers,
2118
                  // round to the even one.
2119
                  result--;
2120
                }
2121
                set_fpu_register(fd_reg, result);
2122
                if (set_fcsr_round_error(fs, rounded)) {
2123
                  set_fpu_register(fd_reg, kFPUInvalidResult);
2124
                }
2125
              }
2126
              break;
2127
            case TRUNC_W_D:  // Truncate double to word (round towards 0).
2128
              {
2129
                double rounded = trunc(fs);
2130
                int32_t result = static_cast<int32_t>(rounded);
2131
                set_fpu_register(fd_reg, result);
2132
                if (set_fcsr_round_error(fs, rounded)) {
2133
                  set_fpu_register(fd_reg, kFPUInvalidResult);
2134
                }
2135
              }
2136
              break;
2137
            case FLOOR_W_D:  // Round double to word towards negative infinity.
2138
              {
2139
                double rounded = floor(fs);
2140
                int32_t result = static_cast<int32_t>(rounded);
2141
                set_fpu_register(fd_reg, result);
2142
                if (set_fcsr_round_error(fs, rounded)) {
2143
                  set_fpu_register(fd_reg, kFPUInvalidResult);
2144
                }
2145
              }
2146
              break;
2147
            case CEIL_W_D:  // Round double to word towards positive infinity.
2148
              {
2149
                double rounded = ceil(fs);
2150
                int32_t result = static_cast<int32_t>(rounded);
2151
                set_fpu_register(fd_reg, result);
2152
                if (set_fcsr_round_error(fs, rounded)) {
2153
                  set_fpu_register(fd_reg, kFPUInvalidResult);
2154
                }
2155
              }
2156
              break;
2157
            case CVT_S_D:  // Convert double to float (single).
2158
              set_fpu_register_float(fd_reg, static_cast<float>(fs));
2159
              break;
2160
            case CVT_L_D: {  // Mips32r2: Truncate double to 64-bit long-word.
2161
              double rounded = trunc(fs);
2162
              i64 = static_cast<int64_t>(rounded);
2163
              set_fpu_register(fd_reg, i64 & 0xffffffff);
2164
              set_fpu_register(fd_reg + 1, i64 >> 32);
2165
              break;
2166
            }
2167
            case TRUNC_L_D: {  // Mips32r2 instruction.
2168
              double rounded = trunc(fs);
2169
              i64 = static_cast<int64_t>(rounded);
2170
              set_fpu_register(fd_reg, i64 & 0xffffffff);
2171
              set_fpu_register(fd_reg + 1, i64 >> 32);
2172
              break;
2173
            }
2174
            case ROUND_L_D: {  // Mips32r2 instruction.
2175
              double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
2176
              i64 = static_cast<int64_t>(rounded);
2177
              set_fpu_register(fd_reg, i64 & 0xffffffff);
2178
              set_fpu_register(fd_reg + 1, i64 >> 32);
2179
              break;
2180
            }
2181
            case FLOOR_L_D:  // Mips32r2 instruction.
2182
              i64 = static_cast<int64_t>(floor(fs));
2183
              set_fpu_register(fd_reg, i64 & 0xffffffff);
2184
              set_fpu_register(fd_reg + 1, i64 >> 32);
2185
              break;
2186
            case CEIL_L_D:  // Mips32r2 instruction.
2187
              i64 = static_cast<int64_t>(ceil(fs));
2188
              set_fpu_register(fd_reg, i64 & 0xffffffff);
2189
              set_fpu_register(fd_reg + 1, i64 >> 32);
2190
              break;
2191
            case C_F_D:
2192
              UNIMPLEMENTED_MIPS();
2193
              break;
2194
            default:
2195
              UNREACHABLE();
2196
          }
2197
          break;
2198
        case W:
2199
          switch (instr->FunctionFieldRaw()) {
2200
            case CVT_S_W:   // Convert word to float (single).
2201
              alu_out = get_fpu_register(fs_reg);
2202
              set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
2203
              break;
2204
            case CVT_D_W:   // Convert word to double.
2205
              alu_out = get_fpu_register(fs_reg);
2206
              set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
2207
              break;
2208
            default:
2209
              UNREACHABLE();
2210
          };
2211
          break;
2212
        case L:
2213
          switch (instr->FunctionFieldRaw()) {
2214
          case CVT_D_L:  // Mips32r2 instruction.
2215
            // Watch the signs here, we want 2 32-bit vals
2216
            // to make a sign-64.
2217
            i64 = static_cast<uint32_t>(get_fpu_register(fs_reg));
2218
            i64 |= static_cast<int64_t>(get_fpu_register(fs_reg + 1)) << 32;
2219
            set_fpu_register_double(fd_reg, static_cast<double>(i64));
2220
            break;
2221
            case CVT_S_L:
2222
              UNIMPLEMENTED_MIPS();
2223
              break;
2224
            default:
2225
              UNREACHABLE();
2226
          }
2227
          break;
2228
        case PS:
2229
          break;
2230
        default:
2231
          UNREACHABLE();
2232
      };
2233
      break;
2234
    case COP1X:
2235
      switch (instr->FunctionFieldRaw()) {
2236
        case MADD_D:
2237
          double fr, ft, fs;
2238
          fr = get_fpu_register_double(fr_reg);
2239
          fs = get_fpu_register_double(fs_reg);
2240
          ft = get_fpu_register_double(ft_reg);
2241
          set_fpu_register_double(fd_reg, fs * ft + fr);
2242
          break;
2243
        default:
2244
          UNREACHABLE();
2245
      };
2246
      break;
2247
    case SPECIAL:
2248
      switch (instr->FunctionFieldRaw()) {
2249
        case JR: {
2250
          Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2251
              current_pc+Instruction::kInstrSize);
2252
          BranchDelayInstructionDecode(branch_delay_instr);
2253
          set_pc(next_pc);
2254
          pc_modified_ = true;
2255
          break;
2256
        }
2257
        case JALR: {
2258
          Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
2259
              current_pc+Instruction::kInstrSize);
2260
          BranchDelayInstructionDecode(branch_delay_instr);
2261
          set_register(31, current_pc + 2 * Instruction::kInstrSize);
2262
          set_pc(next_pc);
2263
          pc_modified_ = true;
2264
          break;
2265
        }
2266
        // Instructions using HI and LO registers.
2267
        case MULT:
2268
          set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
2269
          set_register(HI, static_cast<int32_t>(i64hilo >> 32));
2270
          break;
2271
        case MULTU:
2272
          set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
2273
          set_register(HI, static_cast<int32_t>(u64hilo >> 32));
2274
          break;
2275
        case DIV:
2276
          // Divide by zero and overflow was not checked in the configuration
2277
          // step - div and divu do not raise exceptions. On division by 0
2278
          // the result will be UNPREDICTABLE. On overflow (INT_MIN/-1),
2279
          // return INT_MIN which is what the hardware does.
2280
          if (rs == INT_MIN && rt == -1) {
2281
            set_register(LO, INT_MIN);
2282
            set_register(HI, 0);
2283
          } else if (rt != 0) {
2284
            set_register(LO, rs / rt);
2285
            set_register(HI, rs % rt);
2286
          }
2287
          break;
2288
        case DIVU:
2289
          if (rt_u != 0) {
2290
            set_register(LO, rs_u / rt_u);
2291
            set_register(HI, rs_u % rt_u);
2292
          }
2293
          break;
2294
        // Break and trap instructions.
2295
        case BREAK:
2296
        case TGE:
2297
        case TGEU:
2298
        case TLT:
2299
        case TLTU:
2300
        case TEQ:
2301
        case TNE:
2302
          if (do_interrupt) {
2303
            SoftwareInterrupt(instr);
2304
          }
2305
          break;
2306
        // Conditional moves.
2307
        case MOVN:
2308
          if (rt) set_register(rd_reg, rs);
2309
          break;
2310
        case MOVCI: {
2311
          uint32_t cc = instr->FBccValue();
2312
          uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
2313
          if (instr->Bit(16)) {  // Read Tf bit.
2314
            if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2315
          } else {
2316
            if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
2317
          }
2318
          break;
2319
        }
2320
        case MOVZ:
2321
          if (!rt) set_register(rd_reg, rs);
2322
          break;
2323
        default:  // For other special opcodes we do the default operation.
2324
          set_register(rd_reg, alu_out);
2325
      };
2326
      break;
2327
    case SPECIAL2:
2328
      switch (instr->FunctionFieldRaw()) {
2329
        case MUL:
2330
          set_register(rd_reg, alu_out);
2331
          // HI and LO are UNPREDICTABLE after the operation.
2332
          set_register(LO, Unpredictable);
2333
          set_register(HI, Unpredictable);
2334
          break;
2335
        default:  // For other special2 opcodes we do the default operation.
2336
          set_register(rd_reg, alu_out);
2337
      }
2338
      break;
2339
    case SPECIAL3:
2340
      switch (instr->FunctionFieldRaw()) {
2341
        case INS:
2342
          // Ins instr leaves result in Rt, rather than Rd.
2343
          set_register(rt_reg, alu_out);
2344
          break;
2345
        case EXT:
2346
          // Ext instr leaves result in Rt, rather than Rd.
2347
          set_register(rt_reg, alu_out);
2348
          break;
2349
        default:
2350
          UNREACHABLE();
2351
      };
2352
      break;
2353
    // Unimplemented opcodes raised an error in the configuration step before,
2354
    // so we can use the default here to set the destination register in common
2355
    // cases.
2356
    default:
2357
      set_register(rd_reg, alu_out);
2358
  };
2359
}
2360

    
2361

    
2362
// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
2363
void Simulator::DecodeTypeImmediate(Instruction* instr) {
2364
  // Instruction fields.
2365
  Opcode   op     = instr->OpcodeFieldRaw();
2366
  int32_t  rs     = get_register(instr->RsValue());
2367
  uint32_t rs_u   = static_cast<uint32_t>(rs);
2368
  int32_t  rt_reg = instr->RtValue();  // Destination register.
2369
  int32_t  rt     = get_register(rt_reg);
2370
  int16_t  imm16  = instr->Imm16Value();
2371

    
2372
  int32_t  ft_reg = instr->FtValue();  // Destination register.
2373

    
2374
  // Zero extended immediate.
2375
  uint32_t  oe_imm16 = 0xffff & imm16;
2376
  // Sign extended immediate.
2377
  int32_t   se_imm16 = imm16;
2378

    
2379
  // Get current pc.
2380
  int32_t current_pc = get_pc();
2381
  // Next pc.
2382
  int32_t next_pc = bad_ra;
2383

    
2384
  // Used for conditional branch instructions.
2385
  bool do_branch = false;
2386
  bool execute_branch_delay_instruction = false;
2387

    
2388
  // Used for arithmetic instructions.
2389
  int32_t alu_out = 0;
2390
  // Floating point.
2391
  double fp_out = 0.0;
2392
  uint32_t cc, cc_value, fcsr_cc;
2393

    
2394
  // Used for memory instructions.
2395
  int32_t addr = 0x0;
2396
  // Value to be written in memory.
2397
  uint32_t mem_value = 0x0;
2398

    
2399
  // ---------- Configuration (and execution for REGIMM).
2400
  switch (op) {
2401
    // ------------- COP1. Coprocessor instructions.
2402
    case COP1:
2403
      switch (instr->RsFieldRaw()) {
2404
        case BC1:   // Branch on coprocessor condition.
2405
          cc = instr->FBccValue();
2406
          fcsr_cc = get_fcsr_condition_bit(cc);
2407
          cc_value = test_fcsr_bit(fcsr_cc);
2408
          do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
2409
          execute_branch_delay_instruction = true;
2410
          // Set next_pc.
2411
          if (do_branch) {
2412
            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2413
          } else {
2414
            next_pc = current_pc + kBranchReturnOffset;
2415
          }
2416
          break;
2417
        default:
2418
          UNREACHABLE();
2419
      };
2420
      break;
2421
    // ------------- REGIMM class.
2422
    case REGIMM:
2423
      switch (instr->RtFieldRaw()) {
2424
        case BLTZ:
2425
          do_branch = (rs  < 0);
2426
          break;
2427
        case BLTZAL:
2428
          do_branch = rs  < 0;
2429
          break;
2430
        case BGEZ:
2431
          do_branch = rs >= 0;
2432
          break;
2433
        case BGEZAL:
2434
          do_branch = rs >= 0;
2435
          break;
2436
        default:
2437
          UNREACHABLE();
2438
      };
2439
      switch (instr->RtFieldRaw()) {
2440
        case BLTZ:
2441
        case BLTZAL:
2442
        case BGEZ:
2443
        case BGEZAL:
2444
          // Branch instructions common part.
2445
          execute_branch_delay_instruction = true;
2446
          // Set next_pc.
2447
          if (do_branch) {
2448
            next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2449
            if (instr->IsLinkingInstruction()) {
2450
              set_register(31, current_pc + kBranchReturnOffset);
2451
            }
2452
          } else {
2453
            next_pc = current_pc + kBranchReturnOffset;
2454
          }
2455
        default:
2456
          break;
2457
        };
2458
    break;  // case REGIMM.
2459
    // ------------- Branch instructions.
2460
    // When comparing to zero, the encoding of rt field is always 0, so we don't
2461
    // need to replace rt with zero.
2462
    case BEQ:
2463
      do_branch = (rs == rt);
2464
      break;
2465
    case BNE:
2466
      do_branch = rs != rt;
2467
      break;
2468
    case BLEZ:
2469
      do_branch = rs <= 0;
2470
      break;
2471
    case BGTZ:
2472
      do_branch = rs  > 0;
2473
      break;
2474
    // ------------- Arithmetic instructions.
2475
    case ADDI:
2476
      if (HaveSameSign(rs, se_imm16)) {
2477
        if (rs > 0) {
2478
          exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16);
2479
        } else if (rs < 0) {
2480
          exceptions[kIntegerUnderflow] =
2481
              rs < (Registers::kMinValue - se_imm16);
2482
        }
2483
      }
2484
      alu_out = rs + se_imm16;
2485
      break;
2486
    case ADDIU:
2487
      alu_out = rs + se_imm16;
2488
      break;
2489
    case SLTI:
2490
      alu_out = (rs < se_imm16) ? 1 : 0;
2491
      break;
2492
    case SLTIU:
2493
      alu_out = (rs_u < static_cast<uint32_t>(se_imm16)) ? 1 : 0;
2494
      break;
2495
    case ANDI:
2496
        alu_out = rs & oe_imm16;
2497
      break;
2498
    case ORI:
2499
        alu_out = rs | oe_imm16;
2500
      break;
2501
    case XORI:
2502
        alu_out = rs ^ oe_imm16;
2503
      break;
2504
    case LUI:
2505
        alu_out = (oe_imm16 << 16);
2506
      break;
2507
    // ------------- Memory instructions.
2508
    case LB:
2509
      addr = rs + se_imm16;
2510
      alu_out = ReadB(addr);
2511
      break;
2512
    case LH:
2513
      addr = rs + se_imm16;
2514
      alu_out = ReadH(addr, instr);
2515
      break;
2516
    case LWL: {
2517
      // al_offset is offset of the effective address within an aligned word.
2518
      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2519
      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2520
      uint32_t mask = (1 << byte_shift * 8) - 1;
2521
      addr = rs + se_imm16 - al_offset;
2522
      alu_out = ReadW(addr, instr);
2523
      alu_out <<= byte_shift * 8;
2524
      alu_out |= rt & mask;
2525
      break;
2526
    }
2527
    case LW:
2528
      addr = rs + se_imm16;
2529
      alu_out = ReadW(addr, instr);
2530
      break;
2531
    case LBU:
2532
      addr = rs + se_imm16;
2533
      alu_out = ReadBU(addr);
2534
      break;
2535
    case LHU:
2536
      addr = rs + se_imm16;
2537
      alu_out = ReadHU(addr, instr);
2538
      break;
2539
    case LWR: {
2540
      // al_offset is offset of the effective address within an aligned word.
2541
      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2542
      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2543
      uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2544
      addr = rs + se_imm16 - al_offset;
2545
      alu_out = ReadW(addr, instr);
2546
      alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2547
      alu_out |= rt & mask;
2548
      break;
2549
    }
2550
    case SB:
2551
      addr = rs + se_imm16;
2552
      break;
2553
    case SH:
2554
      addr = rs + se_imm16;
2555
      break;
2556
    case SWL: {
2557
      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2558
      uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2559
      uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2560
      addr = rs + se_imm16 - al_offset;
2561
      mem_value = ReadW(addr, instr) & mask;
2562
      mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2563
      break;
2564
    }
2565
    case SW:
2566
      addr = rs + se_imm16;
2567
      break;
2568
    case SWR: {
2569
      uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2570
      uint32_t mask = (1 << al_offset * 8) - 1;
2571
      addr = rs + se_imm16 - al_offset;
2572
      mem_value = ReadW(addr, instr);
2573
      mem_value = (rt << al_offset * 8) | (mem_value & mask);
2574
      break;
2575
    }
2576
    case LWC1:
2577
      addr = rs + se_imm16;
2578
      alu_out = ReadW(addr, instr);
2579
      break;
2580
    case LDC1:
2581
      addr = rs + se_imm16;
2582
      fp_out = ReadD(addr, instr);
2583
      break;
2584
    case SWC1:
2585
    case SDC1:
2586
      addr = rs + se_imm16;
2587
      break;
2588
    default:
2589
      UNREACHABLE();
2590
  };
2591

    
2592
  // ---------- Raise exceptions triggered.
2593
  SignalExceptions();
2594

    
2595
  // ---------- Execution.
2596
  switch (op) {
2597
    // ------------- Branch instructions.
2598
    case BEQ:
2599
    case BNE:
2600
    case BLEZ:
2601
    case BGTZ:
2602
      // Branch instructions common part.
2603
      execute_branch_delay_instruction = true;
2604
      // Set next_pc.
2605
      if (do_branch) {
2606
        next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
2607
        if (instr->IsLinkingInstruction()) {
2608
          set_register(31, current_pc + 2* Instruction::kInstrSize);
2609
        }
2610
      } else {
2611
        next_pc = current_pc + 2 * Instruction::kInstrSize;
2612
      }
2613
      break;
2614
    // ------------- Arithmetic instructions.
2615
    case ADDI:
2616
    case ADDIU:
2617
    case SLTI:
2618
    case SLTIU:
2619
    case ANDI:
2620
    case ORI:
2621
    case XORI:
2622
    case LUI:
2623
      set_register(rt_reg, alu_out);
2624
      break;
2625
    // ------------- Memory instructions.
2626
    case LB:
2627
    case LH:
2628
    case LWL:
2629
    case LW:
2630
    case LBU:
2631
    case LHU:
2632
    case LWR:
2633
      set_register(rt_reg, alu_out);
2634
      break;
2635
    case SB:
2636
      WriteB(addr, static_cast<int8_t>(rt));
2637
      break;
2638
    case SH:
2639
      WriteH(addr, static_cast<uint16_t>(rt), instr);
2640
      break;
2641
    case SWL:
2642
      WriteW(addr, mem_value, instr);
2643
      break;
2644
    case SW:
2645
      WriteW(addr, rt, instr);
2646
      break;
2647
    case SWR:
2648
      WriteW(addr, mem_value, instr);
2649
      break;
2650
    case LWC1:
2651
      set_fpu_register(ft_reg, alu_out);
2652
      break;
2653
    case LDC1:
2654
      set_fpu_register_double(ft_reg, fp_out);
2655
      break;
2656
    case SWC1:
2657
      addr = rs + se_imm16;
2658
      WriteW(addr, get_fpu_register(ft_reg), instr);
2659
      break;
2660
    case SDC1:
2661
      addr = rs + se_imm16;
2662
      WriteD(addr, get_fpu_register_double(ft_reg), instr);
2663
      break;
2664
    default:
2665
      break;
2666
  };
2667

    
2668

    
2669
  if (execute_branch_delay_instruction) {
2670
    // Execute branch delay slot
2671
    // We don't check for end_sim_pc. First it should not be met as the current
2672
    // pc is valid. Secondly a jump should always execute its branch delay slot.
2673
    Instruction* branch_delay_instr =
2674
      reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
2675
    BranchDelayInstructionDecode(branch_delay_instr);
2676
  }
2677

    
2678
  // If needed update pc after the branch delay execution.
2679
  if (next_pc != bad_ra) {
2680
    set_pc(next_pc);
2681
  }
2682
}
2683

    
2684

    
2685
// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
2686
void Simulator::DecodeTypeJump(Instruction* instr) {
2687
  // Get current pc.
2688
  int32_t current_pc = get_pc();
2689
  // Get unchanged bits of pc.
2690
  int32_t pc_high_bits = current_pc & 0xf0000000;
2691
  // Next pc.
2692
  int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
2693

    
2694
  // Execute branch delay slot.
2695
  // We don't check for end_sim_pc. First it should not be met as the current pc
2696
  // is valid. Secondly a jump should always execute its branch delay slot.
2697
  Instruction* branch_delay_instr =
2698
      reinterpret_cast<Instruction*>(current_pc + Instruction::kInstrSize);
2699
  BranchDelayInstructionDecode(branch_delay_instr);
2700

    
2701
  // Update pc and ra if necessary.
2702
  // Do this after the branch delay execution.
2703
  if (instr->IsLinkingInstruction()) {
2704
    set_register(31, current_pc + 2 * Instruction::kInstrSize);
2705
  }
2706
  set_pc(next_pc);
2707
  pc_modified_ = true;
2708
}
2709

    
2710

    
2711
// Executes the current instruction.
2712
void Simulator::InstructionDecode(Instruction* instr) {
2713
  if (v8::internal::FLAG_check_icache) {
2714
    CheckICache(isolate_->simulator_i_cache(), instr);
2715
  }
2716
  pc_modified_ = false;
2717
  if (::v8::internal::FLAG_trace_sim) {
2718
    disasm::NameConverter converter;
2719
    disasm::Disassembler dasm(converter);
2720
    // Use a reasonably large buffer.
2721
    v8::internal::EmbeddedVector<char, 256> buffer;
2722
    dasm.InstructionDecode(buffer, reinterpret_cast<byte*>(instr));
2723
    PrintF("  0x%08x  %s\n", reinterpret_cast<intptr_t>(instr),
2724
        buffer.start());
2725
  }
2726

    
2727
  switch (instr->InstructionType()) {
2728
    case Instruction::kRegisterType:
2729
      DecodeTypeRegister(instr);
2730
      break;
2731
    case Instruction::kImmediateType:
2732
      DecodeTypeImmediate(instr);
2733
      break;
2734
    case Instruction::kJumpType:
2735
      DecodeTypeJump(instr);
2736
      break;
2737
    default:
2738
      UNSUPPORTED();
2739
  }
2740
  if (!pc_modified_) {
2741
    set_register(pc, reinterpret_cast<int32_t>(instr) +
2742
                 Instruction::kInstrSize);
2743
  }
2744
}
2745

    
2746

    
2747

    
2748
void Simulator::Execute() {
2749
  // Get the PC to simulate. Cannot use the accessor here as we need the
2750
  // raw PC value and not the one used as input to arithmetic instructions.
2751
  int program_counter = get_pc();
2752
  if (::v8::internal::FLAG_stop_sim_at == 0) {
2753
    // Fast version of the dispatch loop without checking whether the simulator
2754
    // should be stopping at a particular executed instruction.
2755
    while (program_counter != end_sim_pc) {
2756
      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2757
      icount_++;
2758
      InstructionDecode(instr);
2759
      program_counter = get_pc();
2760
    }
2761
  } else {
2762
    // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
2763
    // we reach the particular instuction count.
2764
    while (program_counter != end_sim_pc) {
2765
      Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
2766
      icount_++;
2767
      if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
2768
        MipsDebugger dbg(this);
2769
        dbg.Debug();
2770
      } else {
2771
        InstructionDecode(instr);
2772
      }
2773
      program_counter = get_pc();
2774
    }
2775
  }
2776
}
2777

    
2778

    
2779
void Simulator::CallInternal(byte* entry) {
2780
  // Prepare to execute the code at entry.
2781
  set_register(pc, reinterpret_cast<int32_t>(entry));
2782
  // Put down marker for end of simulation. The simulator will stop simulation
2783
  // when the PC reaches this value. By saving the "end simulation" value into
2784
  // the LR the simulation stops when returning to this call point.
2785
  set_register(ra, end_sim_pc);
2786

    
2787
  // Remember the values of callee-saved registers.
2788
  // The code below assumes that r9 is not used as sb (static base) in
2789
  // simulator code and therefore is regarded as a callee-saved register.
2790
  int32_t s0_val = get_register(s0);
2791
  int32_t s1_val = get_register(s1);
2792
  int32_t s2_val = get_register(s2);
2793
  int32_t s3_val = get_register(s3);
2794
  int32_t s4_val = get_register(s4);
2795
  int32_t s5_val = get_register(s5);
2796
  int32_t s6_val = get_register(s6);
2797
  int32_t s7_val = get_register(s7);
2798
  int32_t gp_val = get_register(gp);
2799
  int32_t sp_val = get_register(sp);
2800
  int32_t fp_val = get_register(fp);
2801

    
2802
  // Set up the callee-saved registers with a known value. To be able to check
2803
  // that they are preserved properly across JS execution.
2804
  int32_t callee_saved_value = icount_;
2805
  set_register(s0, callee_saved_value);
2806
  set_register(s1, callee_saved_value);
2807
  set_register(s2, callee_saved_value);
2808
  set_register(s3, callee_saved_value);
2809
  set_register(s4, callee_saved_value);
2810
  set_register(s5, callee_saved_value);
2811
  set_register(s6, callee_saved_value);
2812
  set_register(s7, callee_saved_value);
2813
  set_register(gp, callee_saved_value);
2814
  set_register(fp, callee_saved_value);
2815

    
2816
  // Start the simulation.
2817
  Execute();
2818

    
2819
  // Check that the callee-saved registers have been preserved.
2820
  CHECK_EQ(callee_saved_value, get_register(s0));
2821
  CHECK_EQ(callee_saved_value, get_register(s1));
2822
  CHECK_EQ(callee_saved_value, get_register(s2));
2823
  CHECK_EQ(callee_saved_value, get_register(s3));
2824
  CHECK_EQ(callee_saved_value, get_register(s4));
2825
  CHECK_EQ(callee_saved_value, get_register(s5));
2826
  CHECK_EQ(callee_saved_value, get_register(s6));
2827
  CHECK_EQ(callee_saved_value, get_register(s7));
2828
  CHECK_EQ(callee_saved_value, get_register(gp));
2829
  CHECK_EQ(callee_saved_value, get_register(fp));
2830

    
2831
  // Restore callee-saved registers with the original value.
2832
  set_register(s0, s0_val);
2833
  set_register(s1, s1_val);
2834
  set_register(s2, s2_val);
2835
  set_register(s3, s3_val);
2836
  set_register(s4, s4_val);
2837
  set_register(s5, s5_val);
2838
  set_register(s6, s6_val);
2839
  set_register(s7, s7_val);
2840
  set_register(gp, gp_val);
2841
  set_register(sp, sp_val);
2842
  set_register(fp, fp_val);
2843
}
2844

    
2845

    
2846
int32_t Simulator::Call(byte* entry, int argument_count, ...) {
2847
  va_list parameters;
2848
  va_start(parameters, argument_count);
2849
  // Set up arguments.
2850

    
2851
  // First four arguments passed in registers.
2852
  ASSERT(argument_count >= 4);
2853
  set_register(a0, va_arg(parameters, int32_t));
2854
  set_register(a1, va_arg(parameters, int32_t));
2855
  set_register(a2, va_arg(parameters, int32_t));
2856
  set_register(a3, va_arg(parameters, int32_t));
2857

    
2858
  // Remaining arguments passed on stack.
2859
  int original_stack = get_register(sp);
2860
  // Compute position of stack on entry to generated code.
2861
  int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
2862
                                    - kCArgsSlotsSize);
2863
  if (OS::ActivationFrameAlignment() != 0) {
2864
    entry_stack &= -OS::ActivationFrameAlignment();
2865
  }
2866
  // Store remaining arguments on stack, from low to high memory.
2867
  intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
2868
  for (int i = 4; i < argument_count; i++) {
2869
    stack_argument[i - 4 + kCArgSlotCount] = va_arg(parameters, int32_t);
2870
  }
2871
  va_end(parameters);
2872
  set_register(sp, entry_stack);
2873

    
2874
  CallInternal(entry);
2875

    
2876
  // Pop stack passed arguments.
2877
  CHECK_EQ(entry_stack, get_register(sp));
2878
  set_register(sp, original_stack);
2879

    
2880
  int32_t result = get_register(v0);
2881
  return result;
2882
}
2883

    
2884

    
2885
double Simulator::CallFP(byte* entry, double d0, double d1) {
2886
  if (!IsMipsSoftFloatABI) {
2887
    set_fpu_register_double(f12, d0);
2888
    set_fpu_register_double(f14, d1);
2889
  } else {
2890
    int buffer[2];
2891
    ASSERT(sizeof(buffer[0]) * 2 == sizeof(d0));
2892
    OS::MemCopy(buffer, &d0, sizeof(d0));
2893
    set_dw_register(a0, buffer);
2894
    OS::MemCopy(buffer, &d1, sizeof(d1));
2895
    set_dw_register(a2, buffer);
2896
  }
2897
  CallInternal(entry);
2898
  if (!IsMipsSoftFloatABI) {
2899
    return get_fpu_register_double(f0);
2900
  } else {
2901
    return get_double_from_register_pair(v0);
2902
  }
2903
}
2904

    
2905

    
2906
uintptr_t Simulator::PushAddress(uintptr_t address) {
2907
  int new_sp = get_register(sp) - sizeof(uintptr_t);
2908
  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
2909
  *stack_slot = address;
2910
  set_register(sp, new_sp);
2911
  return new_sp;
2912
}
2913

    
2914

    
2915
uintptr_t Simulator::PopAddress() {
2916
  int current_sp = get_register(sp);
2917
  uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
2918
  uintptr_t address = *stack_slot;
2919
  set_register(sp, current_sp + sizeof(uintptr_t));
2920
  return address;
2921
}
2922

    
2923

    
2924
#undef UNSUPPORTED
2925

    
2926
} }  // namespace v8::internal
2927

    
2928
#endif  // USE_SIMULATOR
2929

    
2930
#endif  // V8_TARGET_ARCH_MIPS