simulator-arm.h 16.7 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

// Declares a Simulator for ARM instructions if we are not generating a native
// ARM binary. This Simulator allows us to run and debug ARM code generation on
// regular desktop machines.
8
// V8 calls into generated code by using the GeneratedCode class,
9 10 11
// which will start execution in the Simulator or forwards to the real entry
// on a ARM HW platform.

12 13
#ifndef V8_EXECUTION_ARM_SIMULATOR_ARM_H_
#define V8_EXECUTION_ARM_SIMULATOR_ARM_H_
14

15
// globals.h defines USE_SIMULATOR.
16
#include "src/common/globals.h"
17

18
#if defined(USE_SIMULATOR)
19
// Running with a simulator.
20

lpy's avatar
lpy committed
21
#include "src/base/hashmap.h"
22 23
#include "src/base/lazy-instance.h"
#include "src/base/platform/mutex.h"
24
#include "src/codegen/arm/constants-arm.h"
25
#include "src/execution/simulator-base.h"
26 27
#include "src/utils/allocation.h"
#include "src/utils/boxed-float.h"
28

29 30
namespace v8 {
namespace internal {
31

32 33 34 35 36 37 38 39 40 41 42 43
class CachePage {
 public:
  static const int LINE_VALID = 0;
  static const int LINE_INVALID = 1;

  static const int kPageShift = 12;
  static const int kPageSize = 1 << kPageShift;
  static const int kPageMask = kPageSize - 1;
  static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
  static const int kLineLength = 1 << kLineShift;
  static const int kLineMask = kLineLength - 1;

44
  CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); }
45 46 47 48 49

  char* ValidityByte(int offset) {
    return &validity_map_[offset >> kLineShift];
  }

50
  char* CachedData(int offset) { return &data_[offset]; }
51 52

 private:
53
  char data_[kPageSize];  // The cached data.
54 55 56 57
  static const int kValidityMapSize = kPageSize >> kLineShift;
  char validity_map_[kValidityMapSize];  // One byte per line.
};

58
class Simulator : public SimulatorBase {
59
 public:
60
  friend class ArmDebugger;
61 62
  enum Register {
    no_reg = -1,
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    r0 = 0,
    r1,
    r2,
    r3,
    r4,
    r5,
    r6,
    r7,
    r8,
    r9,
    r10,
    r11,
    r12,
    r13,
    r14,
    r15,
79 80 81
    num_registers,
    sp = 13,
    lr = 14,
82
    pc = 15,
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    s0 = 0,
    s1,
    s2,
    s3,
    s4,
    s5,
    s6,
    s7,
    s8,
    s9,
    s10,
    s11,
    s12,
    s13,
    s14,
    s15,
    s16,
    s17,
    s18,
    s19,
    s20,
    s21,
    s22,
    s23,
    s24,
    s25,
    s26,
    s27,
    s28,
    s29,
    s30,
    s31,
115
    num_s_registers = 32,
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    d0 = 0,
    d1,
    d2,
    d3,
    d4,
    d5,
    d6,
    d7,
    d8,
    d9,
    d10,
    d11,
    d12,
    d13,
    d14,
    d15,
    d16,
    d17,
    d18,
    d19,
    d20,
    d21,
    d22,
    d23,
    d24,
    d25,
    d26,
    d27,
    d28,
    d29,
    d30,
    d31,
148
    num_d_registers = 32,
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
    q0 = 0,
    q1,
    q2,
    q3,
    q4,
    q5,
    q6,
    q7,
    q8,
    q9,
    q10,
    q11,
    q12,
    q13,
    q14,
    q15,
165
    num_q_registers = 16
166 167
  };

168
  explicit Simulator(Isolate* isolate);
169 170 171 172
  ~Simulator();

  // The currently executing Simulator instance. Potentially there can be one
  // for each native thread.
173
  V8_EXPORT_PRIVATE static Simulator* current(v8::internal::Isolate* isolate);
174 175 176 177 178

  // Accessors for register state. Reading the pc value adheres to the ARM
  // architecture specification and is off by a 8 from the currently executing
  // instruction.
  void set_register(int reg, int32_t value);
179
  V8_EXPORT_PRIVATE int32_t get_register(int reg) const;
180
  double get_double_from_register_pair(int reg);
181
  void set_register_pair_from_double(int reg, double* value);
182
  void set_dw_register(int dreg, const int* dbl);
183

184
  // Support for VFP.
185 186 187 188
  void get_d_register(int dreg, uint64_t* value);
  void set_d_register(int dreg, const uint64_t* value);
  void get_d_register(int dreg, uint32_t* value);
  void set_d_register(int dreg, const uint32_t* value);
189
  // Support for NEON.
190 191 192 193
  template <typename T, int SIZE = kSimd128Size>
  void get_neon_register(int reg, T (&value)[SIZE / sizeof(T)]);
  template <typename T, int SIZE = kSimd128Size>
  void set_neon_register(int reg, const T (&value)[SIZE / sizeof(T)]);
194

195 196
  void set_s_register(int reg, unsigned int value);
  unsigned int get_s_register(int reg) const;
197

198 199 200 201
  void set_d_register_from_double(int dreg, const Float64 dbl) {
    SetVFPRegister<Float64, 2>(dreg, dbl);
  }
  void set_d_register_from_double(int dreg, const double dbl) {
202 203 204
    SetVFPRegister<double, 2>(dreg, dbl);
  }

205 206
  Float64 get_double_from_d_register(int dreg) {
    return GetFromVFPRegister<Float64, 2>(dreg);
207 208
  }

209 210 211
  void set_s_register_from_float(int sreg, const Float32 flt) {
    SetVFPRegister<Float32, 1>(sreg, flt);
  }
212 213 214 215
  void set_s_register_from_float(int sreg, const float flt) {
    SetVFPRegister<float, 1>(sreg, flt);
  }

216 217
  Float32 get_float_from_s_register(int sreg) {
    return GetFromVFPRegister<Float32, 1>(sreg);
218 219 220 221 222 223 224 225 226
  }

  void set_s_register_from_sinteger(int sreg, const int sint) {
    SetVFPRegister<int, 1>(sreg, sint);
  }

  int get_sinteger_from_s_register(int sreg) {
    return GetFromVFPRegister<int, 1>(sreg);
  }
227

228 229
  // Special case of set_register and get_register to access the raw PC value.
  void set_pc(int32_t value);
230
  V8_EXPORT_PRIVATE int32_t get_pc() const;
231

232
  Address get_sp() const { return static_cast<Address>(get_register(sp)); }
233

234
  // Accessor to the internal simulator stack area.
235
  uintptr_t StackLimit(uintptr_t c_limit) const;
236 237

  // Executes ARM instructions until the PC reaches end_sim_pc.
238
  void Execute();
239

240
  template <typename Return, typename... Args>
241
  Return Call(Address entry, Args... args) {
242 243 244
    return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...);
  }

245
  // Alternative: call a 2-argument double function.
246
  template <typename Return>
247
  Return CallFP(Address entry, double d0, double d1) {
248 249
    return ConvertReturn<Return>(CallFPImpl(entry, d0, d1));
  }
250

251 252 253 254 255 256
  // Push an address onto the JS stack.
  uintptr_t PushAddress(uintptr_t address);

  // Pop an address from the JS stack.
  uintptr_t PopAddress();

257 258 259 260
  // Debugger input.
  void set_last_debugger_input(char* input);
  char* last_debugger_input() { return last_debugger_input_; }

261 262 263
  // Redirection support.
  static void SetRedirectInstruction(Instruction* instruction);

264
  // ICache checking.
265
  static bool ICacheMatch(void* one, void* two);
266 267
  static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
                          size_t size);
268

269 270 271 272
  // Returns true if pc register contains one of the 'special_values' defined
  // below (bad_lr, end_sim_pc).
  bool has_bad_pc() const;

273 274 275 276 277 278 279 280 281
  // EABI variant for double arguments in use.
  bool use_eabi_hardfloat() {
#if USE_EABI_HARDFLOAT
    return true;
#else
    return false;
#endif
  }

282 283 284 285 286 287 288 289 290 291 292 293
 private:
  enum special_values {
    // Known bad pc value to ensure that the simulator does not execute
    // without being properly setup.
    bad_lr = -1,
    // A pc value used to signal the simulator to stop execution.  Generally
    // the lr is set to this value on transition from native C code to
    // simulated execution, so that the simulator can "return" to the native
    // C code.
    end_sim_pc = -2
  };

294
  V8_EXPORT_PRIVATE intptr_t CallImpl(Address entry, int argument_count,
295
                                      const intptr_t* arguments);
296
  intptr_t CallFPImpl(Address entry, double d0, double d1);
297

298
  // Unsupported instructions use Format to print an error and stop execution.
299
  void Format(Instruction* instr, const char* format);
300 301 302

  // Checks if the current instruction should be executed based on its
  // condition bits.
303
  inline bool ConditionallyExecute(Instruction* instr);
304 305 306 307 308

  // Helper functions to set the conditional flags in the architecture state.
  void SetNZFlags(int32_t val);
  void SetCFlag(bool val);
  void SetVFlag(bool val);
309
  bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
310
  bool BorrowFrom(int32_t left, int32_t right, int32_t carry = 1);
311
  bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
312 313
                    bool addition);

314
  inline int GetCarry() { return c_flag_ ? 1 : 0; }
315

316
  // Support for VFP.
317
  void Compute_FPSCR_Flags(float val1, float val2);
318 319
  void Compute_FPSCR_Flags(double val1, double val2);
  void Copy_FPSCR_to_APSR();
320
  inline float canonicalizeNaN(float value);
321
  inline double canonicalizeNaN(double value);
322 323
  inline Float32 canonicalizeNaN(Float32 value);
  inline Float64 canonicalizeNaN(Float64 value);
324

325
  // Helper functions to decode common "addressing" modes
326 327
  int32_t GetShiftRm(Instruction* instr, bool* carry_out);
  int32_t GetImm(Instruction* instr, bool* carry_out);
328 329
  int32_t ProcessPU(Instruction* instr, int num_regs, int operand_size,
                    intptr_t* start_address, intptr_t* end_address);
330
  void HandleRList(Instruction* instr, bool load);
331
  void HandleVList(Instruction* inst);
332
  void SoftwareInterrupt(Instruction* instr);
333
  void DebugAtNextPC();
334

335 336 337 338 339 340 341 342
  // Stop helper functions.
  inline bool isWatchedStop(uint32_t bkpt_code);
  inline bool isEnabledStop(uint32_t bkpt_code);
  inline void EnableStop(uint32_t bkpt_code);
  inline void DisableStop(uint32_t bkpt_code);
  inline void IncreaseStopCounter(uint32_t bkpt_code);
  void PrintStopInfo(uint32_t code);

343
  // Read and write memory.
344 345
  // The *Ex functions are exclusive access. The writes return the strex status:
  // 0 if the write succeeds, and 1 if the write fails.
346 347
  inline uint8_t ReadBU(int32_t addr);
  inline int8_t ReadB(int32_t addr);
348
  uint8_t ReadExBU(int32_t addr);
349 350
  inline void WriteB(int32_t addr, uint8_t value);
  inline void WriteB(int32_t addr, int8_t value);
351
  int WriteExB(int32_t addr, uint8_t value);
352

353 354 355
  inline uint16_t ReadHU(int32_t addr);
  inline int16_t ReadH(int32_t addr);
  uint16_t ReadExHU(int32_t addr);
356
  // Note: Overloaded on the sign of the value.
357 358 359 360 361 362 363 364
  inline void WriteH(int32_t addr, uint16_t value);
  inline void WriteH(int32_t addr, int16_t value);
  int WriteExH(int32_t addr, uint16_t value);

  inline int ReadW(int32_t addr);
  int ReadExW(int32_t addr);
  inline void WriteW(int32_t addr, int value);
  int WriteExW(int32_t addr, int value);
365

366 367
  int32_t* ReadDW(int32_t addr);
  void WriteDW(int32_t addr, int32_t value1, int32_t value2);
368 369
  int32_t* ReadExDW(int32_t addr);
  int WriteExDW(int32_t addr, int32_t value1, int32_t value2);
370

371
  // Executing is handled based on the instruction type.
372 373 374 375 376 377 378 379
  // Both type 0 and type 1 rolled into one.
  void DecodeType01(Instruction* instr);
  void DecodeType2(Instruction* instr);
  void DecodeType3(Instruction* instr);
  void DecodeType4(Instruction* instr);
  void DecodeType5(Instruction* instr);
  void DecodeType6(Instruction* instr);
  void DecodeType7(Instruction* instr);
380

381 382 383
  // CP15 coprocessor instructions.
  void DecodeTypeCP15(Instruction* instr);

384
  // Support for VFP.
385 386
  void DecodeTypeVFP(Instruction* instr);
  void DecodeType6CoprocessorIns(Instruction* instr);
387
  void DecodeSpecialCondition(Instruction* instr);
388

389 390 391
  void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instruction* instr);
  void DecodeVCMP(Instruction* instr);
  void DecodeVCVTBetweenDoubleAndSingle(Instruction* instr);
392 393
  int32_t ConvertDoubleToInt(double val, bool unsigned_integer,
                             VFPRoundingMode mode);
394
  void DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr);
395

396
  // Executes one instruction.
397
  void InstructionDecode(Instruction* instr);
398

399
  // ICache.
400 401 402 403 404 405
  static void CheckICache(base::CustomMatcherHashMap* i_cache,
                          Instruction* instr);
  static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
                           int size);
  static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
                                 void* page);
406

407 408
  // Handle arguments and return value for runtime FP functions.
  void GetFpArgs(double* x, double* y, int32_t* z);
409 410 411
  void SetFpResult(const double& result);
  void TrashCallerSaveRegisters();

412 413
  template <class ReturnType, int register_size>
  ReturnType GetFromVFPRegister(int reg_index);
414

415 416
  template <class InputType, int register_size>
  void SetVFPRegister(int reg_index, const InputType& value);
417

418 419 420
  void SetSpecialRegister(SRegisterFieldMask reg_and_mask, uint32_t value);
  uint32_t GetFromSpecialRegister(SRegister reg);

421
  void CallInternal(Address entry);
422

423
  // Architecture state.
424 425 426
  // Saturating instructions require a Q flag to indicate saturation.
  // There is currently no way to read the CPSR directly, and thus read the Q
  // flag, so this is left unimplemented.
427 428 429 430 431 432
  int32_t registers_[16];
  bool n_flag_;
  bool z_flag_;
  bool c_flag_;
  bool v_flag_;

433
  // VFP architecture state.
434
  unsigned int vfp_registers_[num_d_registers * 2];
435 436 437 438 439
  bool n_flag_FPSCR_;
  bool z_flag_FPSCR_;
  bool c_flag_FPSCR_;
  bool v_flag_FPSCR_;

440
  // VFP rounding mode. See ARM DDI 0406B Page A2-29.
441
  VFPRoundingMode FPSCR_rounding_mode_;
442
  bool FPSCR_default_NaN_mode_;
443

444 445 446 447 448 449 450
  // VFP FP exception flags architecture state.
  bool inv_op_vfp_flag_;
  bool div_zero_vfp_flag_;
  bool overflow_vfp_flag_;
  bool underflow_vfp_flag_;
  bool inexact_vfp_flag_;

451
  // Simulator support.
452 453 454 455
  char* stack_;
  bool pc_modified_;
  int icount_;

456 457 458
  // Debugger input.
  char* last_debugger_input_;

459
  // Registered breakpoints.
460 461
  Instruction* break_pc_;
  Instr break_instr_;
462

463 464
  v8::internal::Isolate* isolate_;

465 466 467 468 469 470 471 472
  // A stop is watched if its code is less than kNumOfWatchedStops.
  // Only watched stops support enabling/disabling and the counter feature.
  static const uint32_t kNumOfWatchedStops = 256;

  // Breakpoint is disabled if bit 31 is set.
  static const uint32_t kStopDisabledBit = 1 << 31;

  // A stop is enabled, meaning the simulator will stop when meeting the
473 474
  // instruction, if bit 31 of watched_stops_[code].count is unset.
  // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
475
  // the breakpoint was hit or gone through.
476
  struct StopCountAndDesc {
477 478 479
    uint32_t count;
    char* desc;
  };
480
  StopCountAndDesc watched_stops_[kNumOfWatchedStops];
481

482
  // Synchronization primitives. See ARM DDI 0406C.b, A2.9.
483 484 485 486 487 488 489 490 491 492
  enum class MonitorAccess {
    Open,
    Exclusive,
  };

  enum class TransactionSize {
    None = 0,
    Byte = 1,
    HalfWord = 2,
    Word = 4,
493
    DoubleWord = 8,
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
  };

  // The least-significant bits of the address are ignored. The number of bits
  // is implementation-defined, between 3 and 11. See ARM DDI 0406C.b, A3.4.3.
  static const int32_t kExclusiveTaggedAddrMask = ~((1 << 11) - 1);

  class LocalMonitor {
   public:
    LocalMonitor();

    // These functions manage the state machine for the local monitor, but do
    // not actually perform loads and stores. NotifyStoreExcl only returns
    // true if the exclusive store is allowed; the global monitor will still
    // have to be checked to see whether the memory should be updated.
    void NotifyLoad(int32_t addr);
    void NotifyLoadExcl(int32_t addr, TransactionSize size);
    void NotifyStore(int32_t addr);
    bool NotifyStoreExcl(int32_t addr, TransactionSize size);

   private:
    void Clear();

    MonitorAccess access_state_;
    int32_t tagged_addr_;
    TransactionSize size_;
  };

  class GlobalMonitor {
   public:
    class Processor {
     public:
      Processor();

     private:
      friend class GlobalMonitor;
      // These functions manage the state machine for the global monitor, but do
      // not actually perform loads and stores.
      void Clear_Locked();
      void NotifyLoadExcl_Locked(int32_t addr);
      void NotifyStore_Locked(int32_t addr, bool is_requesting_processor);
      bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor);

      MonitorAccess access_state_;
      int32_t tagged_addr_;
      Processor* next_;
      Processor* prev_;
      // A strex can fail due to background cache evictions. Rather than
      // simulating this, we'll just occasionally introduce cases where an
      // exclusive store fails. This will happen once after every
      // kMaxFailureCounter exclusive stores.
      static const int kMaxFailureCounter = 5;
      int failure_counter_;
    };

    // Exposed so it can be accessed by Simulator::{Read,Write}Ex*.
    base::Mutex mutex;

    void NotifyLoadExcl_Locked(int32_t addr, Processor* processor);
    void NotifyStore_Locked(int32_t addr, Processor* processor);
    bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor);

    // Called when the simulator is destroyed.
    void RemoveProcessor(Processor* processor);

558 559
    static GlobalMonitor* Get();

560
   private:
561 562 563 564
    // Private constructor. Call {GlobalMonitor::Get()} to get the singleton.
    GlobalMonitor() = default;
    friend class base::LeakyObject<GlobalMonitor>;

565 566 567
    bool IsProcessorInLinkedList_Locked(Processor* processor) const;
    void PrependProcessor_Locked(Processor* processor);

568
    Processor* head_ = nullptr;
569 570 571 572
  };

  LocalMonitor local_monitor_;
  GlobalMonitor::Processor global_monitor_processor_;
573 574
};

575 576
}  // namespace internal
}  // namespace v8
577

578
#endif  // defined(USE_SIMULATOR)
579
#endif  // V8_EXECUTION_ARM_SIMULATOR_ARM_H_