1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 // Copyright 2011 the V8 project authors. All rights reserved. 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following 11 // disclaimer in the documentation and/or other materials provided 12 // with the distribution. 13 // * Neither the name of Google Inc. nor the names of its 14 // contributors may be used to endorse or promote products derived 15 // from this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29 #ifndef jit_mips32_Simulator_mips32_h 30 #define jit_mips32_Simulator_mips32_h 31 32 #ifdef JS_SIMULATOR_MIPS32 33 34 #include "jit/IonTypes.h" 35 #include "threading/Thread.h" 36 #include "vm/MutexIDs.h" 37 38 namespace js { 39 namespace jit { 40 41 class Simulator; 42 class Redirection; 43 class CachePage; 44 class AutoLockSimulator; 45 46 const intptr_t kPointerAlignment = 4; 47 const intptr_t kPointerAlignmentMask = kPointerAlignment - 1; 48 49 const intptr_t kDoubleAlignment = 8; 50 const intptr_t kDoubleAlignmentMask = kDoubleAlignment - 1; 51 52 53 // Number of general purpose registers. 54 const int kNumRegisters = 32; 55 56 // In the simulator, the PC register is simulated as the 34th register. 57 const int kPCRegister = 34; 58 59 // Number coprocessor registers. 60 const int kNumFPURegisters = 32; 61 62 // FPU (coprocessor 1) control registers. Currently only FCSR is implemented. 63 const int kFCSRRegister = 31; 64 const int kInvalidFPUControlRegister = -1; 65 const uint32_t kFPUInvalidResult = static_cast<uint32_t>(1 << 31) - 1; 66 67 // FCSR constants. 68 const uint32_t kFCSRInexactFlagBit = 2; 69 const uint32_t kFCSRUnderflowFlagBit = 3; 70 const uint32_t kFCSROverflowFlagBit = 4; 71 const uint32_t kFCSRDivideByZeroFlagBit = 5; 72 const uint32_t kFCSRInvalidOpFlagBit = 6; 73 74 const uint32_t kFCSRInexactFlagMask = 1 << kFCSRInexactFlagBit; 75 const uint32_t kFCSRUnderflowFlagMask = 1 << kFCSRUnderflowFlagBit; 76 const uint32_t kFCSROverflowFlagMask = 1 << kFCSROverflowFlagBit; 77 const uint32_t kFCSRDivideByZeroFlagMask = 1 << kFCSRDivideByZeroFlagBit; 78 const uint32_t kFCSRInvalidOpFlagMask = 1 << kFCSRInvalidOpFlagBit; 79 80 const uint32_t kFCSRFlagMask = 81 kFCSRInexactFlagMask | 82 kFCSRUnderflowFlagMask | 83 kFCSROverflowFlagMask | 84 kFCSRDivideByZeroFlagMask | 85 kFCSRInvalidOpFlagMask; 86 87 const uint32_t kFCSRExceptionFlagMask = kFCSRFlagMask ^ kFCSRInexactFlagMask; 88 89 // On MIPS Simulator breakpoints can have different codes: 90 // - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints, 91 // the simulator will run through them and print the registers. 92 // - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop() 93 // instructions (see Assembler::stop()). 94 // - Breaks larger than kMaxStopCode are simple breaks, dropping you into the 95 // debugger. 96 const uint32_t kMaxWatchpointCode = 31; 97 const uint32_t kMaxStopCode = 127; 98 99 // ----------------------------------------------------------------------------- 100 // Utility functions 101 102 typedef uint32_t Instr; 103 class SimInstruction; 104 105 class Simulator { 106 friend class Redirection; 107 friend class MipsDebugger; 108 friend class AutoLockSimulatorCache; 109 public: 110 111 // Registers are declared in order. See "See MIPS Run Linux" chapter 2. 112 enum Register { 113 no_reg = -1, 114 zero_reg = 0, 115 at, 116 v0, v1, 117 a0, a1, a2, a3, 118 t0, t1, t2, t3, t4, t5, t6, t7, 119 s0, s1, s2, s3, s4, s5, s6, s7, 120 t8, t9, 121 k0, k1, 122 gp, 123 sp, 124 s8, 125 ra, 126 // LO, HI, and pc. 127 LO, 128 HI, 129 pc, // pc must be the last register. 130 kNumSimuRegisters, 131 // aliases 132 fp = s8 133 }; 134 135 // Coprocessor registers. 136 enum FPURegister { 137 f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, 138 f12, f13, f14, f15, // f12 and f14 are arguments FPURegisters. 139 f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, 140 f26, f27, f28, f29, f30, f31, 141 kNumFPURegisters 142 }; 143 144 // Returns nullptr on OOM. 145 static Simulator* Create(JSContext* cx); 146 147 static void Destroy(Simulator* simulator); 148 149 // Constructor/destructor are for internal use only; use the static methods above. 150 Simulator(); 151 ~Simulator(); 152 153 // The currently executing Simulator instance. Potentially there can be one 154 // for each native thread. 155 static Simulator* Current(); 156 StackLimit()157 static inline uintptr_t StackLimit() { 158 return Simulator::Current()->stackLimit(); 159 } 160 161 uintptr_t* addressOfStackLimit(); 162 163 // Accessors for register state. Reading the pc value adheres to the MIPS 164 // architecture specification and is off by a 8 from the currently executing 165 // instruction. 166 void setRegister(int reg, int32_t value); 167 int32_t getRegister(int reg) const; 168 double getDoubleFromRegisterPair(int reg); 169 // Same for FPURegisters. 170 void setFpuRegister(int fpureg, int32_t value); 171 void setFpuRegisterFloat(int fpureg, float value); 172 void setFpuRegisterFloat(int fpureg, int64_t value); 173 void setFpuRegisterDouble(int fpureg, double value); 174 void setFpuRegisterDouble(int fpureg, int64_t value); 175 int32_t getFpuRegister(int fpureg) const; 176 int64_t getFpuRegisterLong(int fpureg) const; 177 float getFpuRegisterFloat(int fpureg) const; 178 double getFpuRegisterDouble(int fpureg) const; 179 void setFCSRBit(uint32_t cc, bool value); 180 bool testFCSRBit(uint32_t cc); 181 bool setFCSRRoundError(double original, double rounded); 182 183 // Special case of set_register and get_register to access the raw PC value. 184 void set_pc(int32_t value); 185 int32_t get_pc() const; 186 187 template <typename T> get_pc_as()188 T get_pc_as() const { return reinterpret_cast<T>(get_pc()); } 189 set_resume_pc(void * value)190 void set_resume_pc(void* value) { 191 resume_pc_ = int32_t(value); 192 } 193 194 // Accessor to the internal simulator stack area. 195 uintptr_t stackLimit() const; 196 bool overRecursed(uintptr_t newsp = 0) const; 197 bool overRecursedWithExtra(uint32_t extra) const; 198 199 // Executes MIPS instructions until the PC reaches end_sim_pc. 200 template<bool enableStopSimAt> 201 void execute(); 202 203 // Sets up the simulator state and grabs the result on return. 204 int32_t call(uint8_t* entry, int argument_count, ...); 205 206 // Push an address onto the JS stack. 207 uintptr_t pushAddress(uintptr_t address); 208 209 // Pop an address from the JS stack. 210 uintptr_t popAddress(); 211 212 // Debugger input. 213 void setLastDebuggerInput(char* input); lastDebuggerInput()214 char* lastDebuggerInput() { return lastDebuggerInput_; } 215 // ICache checking. 216 static void FlushICache(void* start, size_t size); 217 218 // Returns true if pc register contains one of the 'SpecialValues' defined 219 // below (bad_ra, end_sim_pc). 220 bool has_bad_pc() const; 221 222 private: 223 enum SpecialValues { 224 // Known bad pc value to ensure that the simulator does not execute 225 // without being properly setup. 226 bad_ra = -1, 227 // A pc value used to signal the simulator to stop execution. Generally 228 // the ra is set to this value on transition from native C code to 229 // simulated execution, so that the simulator can "return" to the native 230 // C code. 231 end_sim_pc = -2, 232 // Unpredictable value. 233 Unpredictable = 0xbadbeaf 234 }; 235 236 bool init(); 237 238 // Unsupported instructions use Format to print an error and stop execution. 239 void format(SimInstruction* instr, const char* format); 240 241 // Read and write memory. 242 inline uint32_t readBU(uint32_t addr); 243 inline int32_t readB(uint32_t addr); 244 inline void writeB(uint32_t addr, uint8_t value); 245 inline void writeB(uint32_t addr, int8_t value); 246 247 inline uint16_t readHU(uint32_t addr, SimInstruction* instr); 248 inline int16_t readH(uint32_t addr, SimInstruction* instr); 249 // Note: Overloaded on the sign of the value. 250 inline void writeH(uint32_t addr, uint16_t value, SimInstruction* instr); 251 inline void writeH(uint32_t addr, int16_t value, SimInstruction* instr); 252 253 inline int readW(uint32_t addr, SimInstruction* instr); 254 inline void writeW(uint32_t addr, int value, SimInstruction* instr); 255 256 inline double readD(uint32_t addr, SimInstruction* instr); 257 inline void writeD(uint32_t addr, double value, SimInstruction* instr); 258 259 // Executing is handled based on the instruction type. 260 void decodeTypeRegister(SimInstruction* instr); 261 262 // Helper function for decodeTypeRegister. 263 void configureTypeRegister(SimInstruction* instr, 264 int32_t& alu_out, 265 int64_t& i64hilo, 266 uint64_t& u64hilo, 267 int32_t& next_pc, 268 int32_t& return_addr_reg, 269 bool& do_interrupt); 270 271 void decodeTypeImmediate(SimInstruction* instr); 272 void decodeTypeJump(SimInstruction* instr); 273 274 // Used for breakpoints and traps. 275 void softwareInterrupt(SimInstruction* instr); 276 277 // Stop helper functions. 278 bool isWatchpoint(uint32_t code); 279 void printWatchpoint(uint32_t code); 280 void handleStop(uint32_t code, SimInstruction* instr); 281 bool isStopInstruction(SimInstruction* instr); 282 bool isEnabledStop(uint32_t code); 283 void enableStop(uint32_t code); 284 void disableStop(uint32_t code); 285 void increaseStopCounter(uint32_t code); 286 void printStopInfo(uint32_t code); 287 288 289 // Executes one instruction. 290 void instructionDecode(SimInstruction* instr); 291 // Execute one instruction placed in a branch delay slot. 292 void branchDelayInstructionDecode(SimInstruction* instr); 293 294 public: 295 static bool ICacheCheckingEnabled; 296 297 static int StopSimAt; 298 299 // Runtime call support. 300 static void* RedirectNativeFunction(void* nativeFunction, ABIFunctionType type); 301 302 private: 303 enum Exception { 304 kNone, 305 kIntegerOverflow, 306 kIntegerUnderflow, 307 kDivideByZero, 308 kNumExceptions 309 }; 310 int16_t exceptions[kNumExceptions]; 311 312 // Exceptions. 313 void signalExceptions(); 314 315 // Handle arguments and return value for runtime FP functions. 316 void getFpArgs(double* x, double* y, int32_t* z); 317 void getFpFromStack(int32_t* stack, double* x); 318 319 void setCallResultDouble(double result); 320 void setCallResultFloat(float result); 321 void setCallResult(int64_t res); 322 323 void callInternal(uint8_t* entry); 324 325 // Architecture state. 326 // Registers. 327 int32_t registers_[kNumSimuRegisters]; 328 // Coprocessor Registers. 329 int32_t FPUregisters_[kNumFPURegisters]; 330 // FPU control register. 331 uint32_t FCSR_; 332 333 // Simulator support. 334 char* stack_; 335 uintptr_t stackLimit_; 336 bool pc_modified_; 337 int icount_; 338 int break_count_; 339 340 int32_t resume_pc_; 341 342 // Debugger input. 343 char* lastDebuggerInput_; 344 345 // Registered breakpoints. 346 SimInstruction* break_pc_; 347 Instr break_instr_; 348 349 // A stop is watched if its code is less than kNumOfWatchedStops. 350 // Only watched stops support enabling/disabling and the counter feature. 351 static const uint32_t kNumOfWatchedStops = 256; 352 353 354 // Stop is disabled if bit 31 is set. 355 static const uint32_t kStopDisabledBit = 1U << 31; 356 357 // A stop is enabled, meaning the simulator will stop when meeting the 358 // instruction, if bit 31 of watchedStops_[code].count is unset. 359 // The value watchedStops_[code].count & ~(1 << 31) indicates how many times 360 // the breakpoint was hit or gone through. 361 struct StopCountAndDesc { 362 uint32_t count_; 363 char* desc_; 364 }; 365 StopCountAndDesc watchedStops_[kNumOfWatchedStops]; 366 367 private: 368 // ICache checking. 369 struct ICacheHasher { 370 typedef void* Key; 371 typedef void* Lookup; 372 static HashNumber hash(const Lookup& l); 373 static bool match(const Key& k, const Lookup& l); 374 }; 375 376 public: 377 typedef HashMap<void*, CachePage*, ICacheHasher, SystemAllocPolicy> ICacheMap; 378 379 private: 380 // This lock creates a critical section around 'redirection_' and 381 // 'icache_', which are referenced both by the execution engine 382 // and by the off-thread compiler (see Redirection::Get in the cpp file). 383 Mutex cacheLock_; 384 #ifdef DEBUG 385 mozilla::Maybe<Thread::Id> cacheLockHolder_; 386 #endif 387 388 Redirection* redirection_; 389 ICacheMap icache_; 390 391 public: icache()392 ICacheMap& icache() { 393 // Technically we need the lock to access the innards of the 394 // icache, not to take its address, but the latter condition 395 // serves as a useful complement to the former. 396 MOZ_ASSERT(cacheLockHolder_.isSome()); 397 return icache_; 398 } 399 redirection()400 Redirection* redirection() const { 401 MOZ_ASSERT(cacheLockHolder_.isSome()); 402 return redirection_; 403 } 404 setRedirection(js::jit::Redirection * redirection)405 void setRedirection(js::jit::Redirection* redirection) { 406 MOZ_ASSERT(cacheLockHolder_.isSome()); 407 redirection_ = redirection; 408 } 409 }; 410 411 #define JS_CHECK_SIMULATOR_RECURSION_WITH_EXTRA(cx, extra, onerror) \ 412 JS_BEGIN_MACRO \ 413 if (cx->mainThread().simulator()->overRecursedWithExtra(extra)) { \ 414 js::ReportOverRecursed(cx); \ 415 onerror; \ 416 } \ 417 JS_END_MACRO 418 419 } // namespace jit 420 } // namespace js 421 422 #endif /* JS_SIMULATOR_MIPS32 */ 423 424 #endif /* jit_mips32_Simulator_mips32_h */ 425