12 #ifndef V8_PPC_SIMULATOR_PPC_H_ 13 #define V8_PPC_SIMULATOR_PPC_H_ 15 #include "src/allocation.h" 16 #include "src/base/lazy-instance.h" 17 #include "src/base/platform/mutex.h" 19 #if defined(USE_SIMULATOR) 22 #include "src/assembler.h" 23 #include "src/base/hashmap.h" 24 #include "src/ppc/constants-ppc.h" 25 #include "src/simulator-base.h" 32 static const int LINE_VALID = 0;
33 static const int LINE_INVALID = 1;
35 static const int kPageShift = 12;
36 static const int kPageSize = 1 << kPageShift;
37 static const int kPageMask = kPageSize - 1;
38 static const int kLineShift = 2;
39 static const int kLineLength = 1 << kLineShift;
40 static const int kLineMask = kLineLength - 1;
42 CachePage() { memset(&validity_map_, LINE_INVALID,
sizeof(validity_map_)); }
44 char* ValidityByte(
int offset) {
45 return &validity_map_[offset >> kLineShift];
48 char* CachedData(
int offset) {
return &data_[offset]; }
51 char data_[kPageSize];
52 static const int kValidityMapSize = kPageSize >> kLineShift;
53 char validity_map_[kValidityMapSize];
56 class Simulator :
public SimulatorBase {
58 friend class PPCDebugger;
129 explicit Simulator(Isolate* isolate);
137 void set_register(
int reg, intptr_t value);
138 intptr_t get_register(
int reg)
const;
139 double get_double_from_register_pair(
int reg);
140 void set_d_register_from_double(
int dreg,
const double dbl) {
141 DCHECK(dreg >= 0 && dreg < kNumFPRs);
142 *bit_cast<
double*>(&fp_registers_[dreg]) = dbl;
144 double get_double_from_d_register(
int dreg) {
145 DCHECK(dreg >= 0 && dreg < kNumFPRs);
146 return *bit_cast<
double*>(&fp_registers_[dreg]);
148 void set_d_register(
int dreg,
int64_t value) {
149 DCHECK(dreg >= 0 && dreg < kNumFPRs);
150 fp_registers_[dreg] = value;
152 int64_t get_d_register(
int dreg) {
153 DCHECK(dreg >= 0 && dreg < kNumFPRs);
154 return fp_registers_[dreg];
158 void set_pc(intptr_t value);
159 intptr_t get_pc()
const;
161 Address get_sp()
const {
return static_cast<Address
>(get_register(sp)); }
169 template <
typename Return,
typename... Args>
170 Return Call(Address entry, Args... args) {
171 return VariadicCall<Return>(
this, &Simulator::CallImpl, entry, args...);
175 void CallFP(Address entry,
double d0,
double d1);
176 int32_t CallFPReturnsInt(Address entry,
double d0,
double d1);
177 double CallFPReturnsDouble(Address entry,
double d0,
double d1);
186 void set_last_debugger_input(
char* input);
187 char* last_debugger_input() {
return last_debugger_input_; }
190 static void SetRedirectInstruction(Instruction* instruction);
193 static bool ICacheMatch(
void* one,
void* two);
194 static void FlushICache(base::CustomMatcherHashMap* i_cache,
void* start,
199 bool has_bad_pc()
const;
202 enum special_values {
213 intptr_t CallImpl(Address entry,
int argument_count,
214 const intptr_t* arguments);
216 enum BCType { BC_OFFSET, BC_LINK_REG, BC_CTR_REG };
219 void Format(Instruction* instr,
const char* format);
222 bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
223 bool BorrowFrom(int32_t left, int32_t right);
224 bool OverflowFrom(int32_t alu_out, int32_t left, int32_t right,
228 int32_t GetShiftRm(Instruction* instr,
bool* carry_out);
229 int32_t GetImm(Instruction* instr,
bool* carry_out);
230 void ProcessPUW(Instruction* instr,
int num_regs,
int operand_size,
231 intptr_t* start_address, intptr_t* end_address);
232 void HandleRList(Instruction* instr,
bool load);
233 void HandleVList(Instruction* inst);
234 void SoftwareInterrupt(Instruction* instr);
237 inline bool isStopInstruction(Instruction* instr);
238 inline bool isWatchedStop(
uint32_t bkpt_code);
239 inline bool isEnabledStop(
uint32_t bkpt_code);
240 inline void EnableStop(
uint32_t bkpt_code);
241 inline void DisableStop(
uint32_t bkpt_code);
242 inline void IncreaseStopCounter(
uint32_t bkpt_code);
246 template <
typename T>
247 inline void Read(
uintptr_t address, T* value) {
248 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
249 memcpy(value, reinterpret_cast<const char*>(address),
sizeof(T));
252 template <
typename T>
253 inline void ReadEx(
uintptr_t address, T* value) {
254 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
255 global_monitor_.Pointer()->NotifyLoadExcl(
256 address, static_cast<TransactionSize>(
sizeof(T)),
257 isolate_->thread_id());
258 memcpy(value, reinterpret_cast<const char*>(address),
sizeof(T));
261 template <
typename T>
262 inline void Write(
uintptr_t address, T value) {
263 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
264 global_monitor_.Pointer()->NotifyStore(
265 address, static_cast<TransactionSize>(
sizeof(T)),
266 isolate_->thread_id());
267 memcpy(reinterpret_cast<char*>(address), &value,
sizeof(T));
270 template <
typename T>
271 inline int32_t WriteEx(
uintptr_t address, T value) {
272 base::MutexGuard lock_guard(&global_monitor_.Pointer()->mutex);
273 if (global_monitor_.Pointer()->NotifyStoreExcl(
274 address, static_cast<TransactionSize>(
sizeof(T)),
275 isolate_->thread_id())) {
276 memcpy(reinterpret_cast<char*>(address), &value,
sizeof(T));
283 #define RW_VAR_LIST(V) \ 287 V(W, int32_t) V(HU, uint16_t) V(H, int16_t) V(BU, uint8_t) V(B, int8_t) 289 #define GENERATE_RW_FUNC(size, type) \ 290 inline type Read##size(uintptr_t addr); \ 291 inline type ReadEx##size(uintptr_t addr); \ 292 inline void Write##size(uintptr_t addr, type value); \ 293 inline int32_t WriteEx##size(uintptr_t addr, type value); 295 RW_VAR_LIST(GENERATE_RW_FUNC);
296 #undef GENERATE_RW_FUNC 298 void Trace(Instruction* instr);
299 void SetCR0(intptr_t result,
bool setSO =
false);
300 void ExecuteBranchConditional(Instruction* instr, BCType type);
301 void ExecuteGeneric(Instruction* instr);
303 void SetFPSCR(
int bit) { fp_condition_reg_ |= (1 << (31 - bit)); }
304 void ClearFPSCR(
int bit) { fp_condition_reg_ &= ~(1 << (31 - bit)); }
307 void ExecuteInstruction(Instruction* instr);
310 static void CheckICache(base::CustomMatcherHashMap* i_cache,
312 static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
314 static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
318 void GetFpArgs(
double* x,
double* y, intptr_t* z);
319 void SetFpResult(
const double& result);
320 void TrashCallerSaveRegisters();
322 void CallInternal(Address entry);
328 intptr_t registers_[kNumGPRs];
329 int32_t condition_reg_;
330 int32_t fp_condition_reg_;
331 intptr_t special_reg_lr_;
332 intptr_t special_reg_pc_;
333 intptr_t special_reg_ctr_;
334 int32_t special_reg_xer_;
336 int64_t fp_registers_[kNumFPRs];
340 static const size_t stack_protection_size_ = 256 * kPointerSize;
345 char* last_debugger_input_;
348 Instruction* break_pc_;
355 static const uint32_t kNumOfWatchedStops = 256;
358 static const uint32_t kStopDisabledBit = 1 << 31;
364 struct StopCountAndDesc {
368 StopCountAndDesc watched_stops_[kNumOfWatchedStops];
371 enum class MonitorAccess {
376 enum class TransactionSize {
384 class GlobalMonitor {
391 void NotifyLoadExcl(
uintptr_t addr, TransactionSize size,
393 void NotifyStore(
uintptr_t addr, TransactionSize size, ThreadId thread_id);
394 bool NotifyStoreExcl(
uintptr_t addr, TransactionSize size,
400 MonitorAccess access_state_;
402 TransactionSize size_;
406 static base::LazyInstance<GlobalMonitor>::type global_monitor_;
412 #endif // defined(USE_SIMULATOR) 413 #endif // V8_PPC_SIMULATOR_PPC_H_