Home | History | Annotate | Download | only in ppc
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Declares a Simulator for PPC instructions if we are not generating a native
      6 // PPC binary. This Simulator allows us to run and debug PPC code generation on
      7 // regular desktop machines.
      8 // V8 calls into generated code via the GeneratedCode wrapper,
      9 // which will start execution in the Simulator or forwards to the real entry
     10 // on a PPC HW platform.
     11 
     12 #ifndef V8_PPC_SIMULATOR_PPC_H_
     13 #define V8_PPC_SIMULATOR_PPC_H_
     14 
     15 #include "src/allocation.h"
     16 
     17 #if defined(USE_SIMULATOR)
     18 // Running with a simulator.
     19 
     20 #include "src/assembler.h"
     21 #include "src/base/hashmap.h"
     22 #include "src/ppc/constants-ppc.h"
     23 #include "src/simulator-base.h"
     24 
     25 namespace v8 {
     26 namespace internal {
     27 
     28 class CachePage {
     29  public:
     30   static const int LINE_VALID = 0;
     31   static const int LINE_INVALID = 1;
     32 
     33   static const int kPageShift = 12;
     34   static const int kPageSize = 1 << kPageShift;
     35   static const int kPageMask = kPageSize - 1;
     36   static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
     37   static const int kLineLength = 1 << kLineShift;
     38   static const int kLineMask = kLineLength - 1;
     39 
     40   CachePage() { memset(&validity_map_, LINE_INVALID, sizeof(validity_map_)); }
     41 
     42   char* ValidityByte(int offset) {
     43     return &validity_map_[offset >> kLineShift];
     44   }
     45 
     46   char* CachedData(int offset) { return &data_[offset]; }
     47 
     48  private:
     49   char data_[kPageSize];  // The cached data.
     50   static const int kValidityMapSize = kPageSize >> kLineShift;
     51   char validity_map_[kValidityMapSize];  // One byte per line.
     52 };
     53 
     54 class Simulator : public SimulatorBase {
     55  public:
     56   friend class PPCDebugger;
     57   enum Register {
     58     no_reg = -1,
     59     r0 = 0,
     60     sp,
     61     r2,
     62     r3,
     63     r4,
     64     r5,
     65     r6,
     66     r7,
     67     r8,
     68     r9,
     69     r10,
     70     r11,
     71     r12,
     72     r13,
     73     r14,
     74     r15,
     75     r16,
     76     r17,
     77     r18,
     78     r19,
     79     r20,
     80     r21,
     81     r22,
     82     r23,
     83     r24,
     84     r25,
     85     r26,
     86     r27,
     87     r28,
     88     r29,
     89     r30,
     90     fp,
     91     kNumGPRs = 32,
     92     d0 = 0,
     93     d1,
     94     d2,
     95     d3,
     96     d4,
     97     d5,
     98     d6,
     99     d7,
    100     d8,
    101     d9,
    102     d10,
    103     d11,
    104     d12,
    105     d13,
    106     d14,
    107     d15,
    108     d16,
    109     d17,
    110     d18,
    111     d19,
    112     d20,
    113     d21,
    114     d22,
    115     d23,
    116     d24,
    117     d25,
    118     d26,
    119     d27,
    120     d28,
    121     d29,
    122     d30,
    123     d31,
    124     kNumFPRs = 32
    125   };
    126 
    127   explicit Simulator(Isolate* isolate);
    128   ~Simulator();
    129 
    130   // The currently executing Simulator instance. Potentially there can be one
    131   // for each native thread.
    132   static Simulator* current(v8::internal::Isolate* isolate);
    133 
    134   // Accessors for register state.
    135   void set_register(int reg, intptr_t value);
    136   intptr_t get_register(int reg) const;
    137   double get_double_from_register_pair(int reg);
    138   void set_d_register_from_double(int dreg, const double dbl) {
    139     DCHECK(dreg >= 0 && dreg < kNumFPRs);
    140     *bit_cast<double*>(&fp_registers_[dreg]) = dbl;
    141   }
    142   double get_double_from_d_register(int dreg) {
    143     DCHECK(dreg >= 0 && dreg < kNumFPRs);
    144     return *bit_cast<double*>(&fp_registers_[dreg]);
    145   }
    146   void set_d_register(int dreg, int64_t value) {
    147     DCHECK(dreg >= 0 && dreg < kNumFPRs);
    148     fp_registers_[dreg] = value;
    149   }
    150   int64_t get_d_register(int dreg) {
    151     DCHECK(dreg >= 0 && dreg < kNumFPRs);
    152     return fp_registers_[dreg];
    153   }
    154 
    155   // Special case of set_register and get_register to access the raw PC value.
    156   void set_pc(intptr_t value);
    157   intptr_t get_pc() const;
    158 
    159   Address get_sp() const { return static_cast<Address>(get_register(sp)); }
    160 
    161   // Accessor to the internal simulator stack area.
    162   uintptr_t StackLimit(uintptr_t c_limit) const;
    163 
    164   // Executes PPC instructions until the PC reaches end_sim_pc.
    165   void Execute();
    166 
    167   template <typename Return, typename... Args>
    168   Return Call(Address entry, Args... args) {
    169     return VariadicCall<Return>(this, &Simulator::CallImpl, entry, args...);
    170   }
    171 
    172   // Alternative: call a 2-argument double function.
    173   void CallFP(Address entry, double d0, double d1);
    174   int32_t CallFPReturnsInt(Address entry, double d0, double d1);
    175   double CallFPReturnsDouble(Address entry, double d0, double d1);
    176 
    177   // Push an address onto the JS stack.
    178   uintptr_t PushAddress(uintptr_t address);
    179 
    180   // Pop an address from the JS stack.
    181   uintptr_t PopAddress();
    182 
    183   // Debugger input.
    184   void set_last_debugger_input(char* input);
    185   char* last_debugger_input() { return last_debugger_input_; }
    186 
    187   // Redirection support.
    188   static void SetRedirectInstruction(Instruction* instruction);
    189 
    190   // ICache checking.
    191   static bool ICacheMatch(void* one, void* two);
    192   static void FlushICache(base::CustomMatcherHashMap* i_cache, void* start,
    193                           size_t size);
    194 
    195   // Returns true if pc register contains one of the 'special_values' defined
    196   // below (bad_lr, end_sim_pc).
    197   bool has_bad_pc() const;
    198 
    199  private:
    200   enum special_values {
    201     // Known bad pc value to ensure that the simulator does not execute
    202     // without being properly setup.
    203     bad_lr = -1,
    204     // A pc value used to signal the simulator to stop execution.  Generally
    205     // the lr is set to this value on transition from native C code to
    206     // simulated execution, so that the simulator can "return" to the native
    207     // C code.
    208     end_sim_pc = -2
    209   };
    210 
    211   intptr_t CallImpl(Address entry, int argument_count,
    212                     const intptr_t* arguments);
    213 
    214   enum BCType { BC_OFFSET, BC_LINK_REG, BC_CTR_REG };
    215 
    216   // Unsupported instructions use Format to print an error and stop execution.
    217   void Format(Instruction* instr, const char* format);
    218 
    219   // Helper functions to set the conditional flags in the architecture state.
    220   bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
    221   bool BorrowFrom(int32_t left, int32_t right);
    222   bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
    223                     bool addition);
    224 
    225   // Helper functions to decode common "addressing" modes
    226   int32_t GetShiftRm(Instruction* instr, bool* carry_out);
    227   int32_t GetImm(Instruction* instr, bool* carry_out);
    228   void ProcessPUW(Instruction* instr, int num_regs, int operand_size,
    229                   intptr_t* start_address, intptr_t* end_address);
    230   void HandleRList(Instruction* instr, bool load);
    231   void HandleVList(Instruction* inst);
    232   void SoftwareInterrupt(Instruction* instr);
    233 
    234   // Stop helper functions.
    235   inline bool isStopInstruction(Instruction* instr);
    236   inline bool isWatchedStop(uint32_t bkpt_code);
    237   inline bool isEnabledStop(uint32_t bkpt_code);
    238   inline void EnableStop(uint32_t bkpt_code);
    239   inline void DisableStop(uint32_t bkpt_code);
    240   inline void IncreaseStopCounter(uint32_t bkpt_code);
    241   void PrintStopInfo(uint32_t code);
    242 
    243   // Read and write memory.
    244   inline uint8_t ReadBU(intptr_t addr);
    245   inline uint8_t ReadExBU(intptr_t addr);
    246   inline int8_t ReadB(intptr_t addr);
    247   inline void WriteB(intptr_t addr, uint8_t value);
    248   inline int WriteExB(intptr_t addr, uint8_t value);
    249   inline void WriteB(intptr_t addr, int8_t value);
    250 
    251   inline uint16_t ReadHU(intptr_t addr, Instruction* instr);
    252   inline uint16_t ReadExHU(intptr_t addr, Instruction* instr);
    253   inline int16_t ReadH(intptr_t addr, Instruction* instr);
    254   // Note: Overloaded on the sign of the value.
    255   inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr);
    256   inline int WriteExH(intptr_t addr, uint16_t value, Instruction* instr);
    257   inline void WriteH(intptr_t addr, int16_t value, Instruction* instr);
    258 
    259   inline uint32_t ReadWU(intptr_t addr, Instruction* instr);
    260   inline uint32_t ReadExWU(intptr_t addr, Instruction* instr);
    261   inline int32_t ReadW(intptr_t addr, Instruction* instr);
    262   inline void WriteW(intptr_t addr, uint32_t value, Instruction* instr);
    263   inline int WriteExW(intptr_t addr, uint32_t value, Instruction* instr);
    264   inline void WriteW(intptr_t addr, int32_t value, Instruction* instr);
    265 
    266   intptr_t* ReadDW(intptr_t addr);
    267   void WriteDW(intptr_t addr, int64_t value);
    268 
    269   void Trace(Instruction* instr);
    270   void SetCR0(intptr_t result, bool setSO = false);
    271   void ExecuteBranchConditional(Instruction* instr, BCType type);
    272   void ExecuteExt1(Instruction* instr);
    273   bool ExecuteExt2_10bit_part1(Instruction* instr);
    274   bool ExecuteExt2_10bit_part2(Instruction* instr);
    275   bool ExecuteExt2_9bit_part1(Instruction* instr);
    276   bool ExecuteExt2_9bit_part2(Instruction* instr);
    277   void ExecuteExt2_5bit(Instruction* instr);
    278   void ExecuteExt2(Instruction* instr);
    279   void ExecuteExt3(Instruction* instr);
    280   void ExecuteExt4(Instruction* instr);
    281 #if V8_TARGET_ARCH_PPC64
    282   void ExecuteExt5(Instruction* instr);
    283 #endif
    284   void ExecuteExt6(Instruction* instr);
    285   void ExecuteGeneric(Instruction* instr);
    286 
    287   void SetFPSCR(int bit) { fp_condition_reg_ |= (1 << (31 - bit)); }
    288   void ClearFPSCR(int bit) { fp_condition_reg_ &= ~(1 << (31 - bit)); }
    289 
    290   // Executes one instruction.
    291   void ExecuteInstruction(Instruction* instr);
    292 
    293   // ICache.
    294   static void CheckICache(base::CustomMatcherHashMap* i_cache,
    295                           Instruction* instr);
    296   static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
    297                            int size);
    298   static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
    299                                  void* page);
    300 
    301   // Handle arguments and return value for runtime FP functions.
    302   void GetFpArgs(double* x, double* y, intptr_t* z);
    303   void SetFpResult(const double& result);
    304   void TrashCallerSaveRegisters();
    305 
    306   void CallInternal(Address entry);
    307 
    308   // Architecture state.
    309   // Saturating instructions require a Q flag to indicate saturation.
    310   // There is currently no way to read the CPSR directly, and thus read the Q
    311   // flag, so this is left unimplemented.
    312   intptr_t registers_[kNumGPRs];
    313   int32_t condition_reg_;
    314   int32_t fp_condition_reg_;
    315   intptr_t special_reg_lr_;
    316   intptr_t special_reg_pc_;
    317   intptr_t special_reg_ctr_;
    318   int32_t special_reg_xer_;
    319 
    320   int64_t fp_registers_[kNumFPRs];
    321 
    322   // Simulator support.
    323   char* stack_;
    324   static const size_t stack_protection_size_ = 256 * kPointerSize;
    325   bool pc_modified_;
    326   int icount_;
    327 
    328   // Debugger input.
    329   char* last_debugger_input_;
    330 
    331   // Registered breakpoints.
    332   Instruction* break_pc_;
    333   Instr break_instr_;
    334 
    335   v8::internal::Isolate* isolate_;
    336 
    337   // A stop is watched if its code is less than kNumOfWatchedStops.
    338   // Only watched stops support enabling/disabling and the counter feature.
    339   static const uint32_t kNumOfWatchedStops = 256;
    340 
    341   // Breakpoint is disabled if bit 31 is set.
    342   static const uint32_t kStopDisabledBit = 1 << 31;
    343 
    344   // A stop is enabled, meaning the simulator will stop when meeting the
    345   // instruction, if bit 31 of watched_stops_[code].count is unset.
    346   // The value watched_stops_[code].count & ~(1 << 31) indicates how many times
    347   // the breakpoint was hit or gone through.
    348   struct StopCountAndDesc {
    349     uint32_t count;
    350     char* desc;
    351   };
    352   StopCountAndDesc watched_stops_[kNumOfWatchedStops];
    353 
    354   // Synchronization primitives. See ARM DDI 0406C.b, A2.9.
    355   enum class MonitorAccess {
    356     Open,
    357     Exclusive,
    358   };
    359 
    360   enum class TransactionSize {
    361     None = 0,
    362     Byte = 1,
    363     HalfWord = 2,
    364     Word = 4,
    365   };
    366 
    367   class LocalMonitor {
    368    public:
    369     LocalMonitor();
    370 
    371     // These functions manage the state machine for the local monitor, but do
    372     // not actually perform loads and stores. NotifyStoreExcl only returns
    373     // true if the exclusive store is allowed; the global monitor will still
    374     // have to be checked to see whether the memory should be updated.
    375     void NotifyLoad(int32_t addr);
    376     void NotifyLoadExcl(int32_t addr, TransactionSize size);
    377     void NotifyStore(int32_t addr);
    378     bool NotifyStoreExcl(int32_t addr, TransactionSize size);
    379 
    380    private:
    381     void Clear();
    382 
    383     MonitorAccess access_state_;
    384     int32_t tagged_addr_;
    385     TransactionSize size_;
    386   };
    387 
    388   class GlobalMonitor {
    389    public:
    390     GlobalMonitor();
    391 
    392     class Processor {
    393      public:
    394       Processor();
    395 
    396      private:
    397       friend class GlobalMonitor;
    398       // These functions manage the state machine for the global monitor, but do
    399       // not actually perform loads and stores.
    400       void Clear_Locked();
    401       void NotifyLoadExcl_Locked(int32_t addr);
    402       void NotifyStore_Locked(int32_t addr, bool is_requesting_processor);
    403       bool NotifyStoreExcl_Locked(int32_t addr, bool is_requesting_processor);
    404 
    405       MonitorAccess access_state_;
    406       int32_t tagged_addr_;
    407       Processor* next_;
    408       Processor* prev_;
    409     };
    410 
    411     // Exposed so it can be accessed by Simulator::{Read,Write}Ex*.
    412     base::Mutex mutex;
    413 
    414     void NotifyLoadExcl_Locked(int32_t addr, Processor* processor);
    415     void NotifyStore_Locked(int32_t addr, Processor* processor);
    416     bool NotifyStoreExcl_Locked(int32_t addr, Processor* processor);
    417 
    418     // Called when the simulator is destroyed.
    419     void RemoveProcessor(Processor* processor);
    420 
    421    private:
    422     bool IsProcessorInLinkedList_Locked(Processor* processor) const;
    423     void PrependProcessor_Locked(Processor* processor);
    424 
    425     Processor* head_;
    426   };
    427 
    428   LocalMonitor local_monitor_;
    429   GlobalMonitor::Processor global_monitor_processor_;
    430   static base::LazyInstance<GlobalMonitor>::type global_monitor_;
    431 };
    432 
    433 }  // namespace internal
    434 }  // namespace v8
    435 
    436 #endif  // defined(USE_SIMULATOR)
    437 #endif  // V8_PPC_SIMULATOR_PPC_H_
    438