1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 // Copyright 2012 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 #include "jit/arm/Simulator-arm.h"
30 
31 #include "mozilla/Casting.h"
32 #include "mozilla/DebugOnly.h"
33 #include "mozilla/FloatingPoint.h"
34 #include "mozilla/Likely.h"
35 #include "mozilla/MathAlgorithms.h"
36 #include "mozilla/SizePrintfMacros.h"
37 
38 #include "asmjs/AsmJSValidate.h"
39 #include "jit/arm/Assembler-arm.h"
40 #include "jit/arm/disasm/Constants-arm.h"
41 #include "jit/AtomicOperations.h"
42 #include "vm/Runtime.h"
43 #include "vm/SharedMem.h"
44 
45 extern "C" {
46 
47 int64_t
__aeabi_idivmod(int x,int y)48 __aeabi_idivmod(int x, int y)
49 {
50     uint32_t lo = uint32_t(x / y);
51     uint32_t hi = uint32_t(x % y);
52     return (int64_t(hi) << 32) | lo;
53 }
54 
55 int64_t
__aeabi_uidivmod(int x,int y)56 __aeabi_uidivmod(int x, int y)
57 {
58     uint32_t lo = uint32_t(x) / uint32_t(y);
59     uint32_t hi = uint32_t(x) % uint32_t(y);
60     return (int64_t(hi) << 32) | lo;
61 }
62 }
63 
64 namespace js {
65 namespace jit {
66 
67 // Load/store multiple addressing mode.
68 enum BlockAddrMode {
69     // Alias modes for comparison when writeback does not matter.
70     da_x         = (0|0|0) << 21,  // Decrement after.
71     ia_x         = (0|4|0) << 21,  // Increment after.
72     db_x         = (8|0|0) << 21,  // Decrement before.
73     ib_x         = (8|4|0) << 21,  // Increment before.
74 };
75 
76 // Type of VFP register. Determines register encoding.
77 enum VFPRegPrecision {
78     kSinglePrecision = 0,
79     kDoublePrecision = 1
80 };
81 
82 enum NeonListType {
83     nlt_1 = 0x7,
84     nlt_2 = 0xA,
85     nlt_3 = 0x6,
86     nlt_4 = 0x2
87 };
88 
89 // Supervisor Call (svc) specific support.
90 
91 // Special Software Interrupt codes when used in the presence of the ARM
92 // simulator.
93 // svc (formerly swi) provides a 24bit immediate value. Use bits 22:0 for
94 // standard SoftwareInterrupCode. Bit 23 is reserved for the stop feature.
95 enum SoftwareInterruptCodes {
96     kCallRtRedirected = 0x10,  // Transition to C code.
97     kBreakpoint= 0x20, // Breakpoint.
98     kStopCode = 1 << 23 // Stop.
99 };
100 
101 const uint32_t kStopCodeMask = kStopCode - 1;
102 const uint32_t kMaxStopCode = kStopCode - 1;
103 
104 // -----------------------------------------------------------------------------
105 // Instruction abstraction.
106 
107 // The class Instruction enables access to individual fields defined in the ARM
108 // architecture instruction set encoding as described in figure A3-1.
109 // Note that the Assembler uses typedef int32_t Instr.
110 //
111 // Example: Test whether the instruction at ptr does set the condition code
112 // bits.
113 //
114 // bool InstructionSetsConditionCodes(byte* ptr) {
115 //   Instruction* instr = Instruction::At(ptr);
116 //   int type = instr->TypeValue();
117 //   return ((type == 0) || (type == 1)) && instr->hasS();
118 // }
119 //
120 class SimInstruction {
121   public:
122     enum {
123         kInstrSize = 4,
124         kPCReadOffset = 8
125     };
126 
127     // Get the raw instruction bits.
instructionBits() const128     inline Instr instructionBits() const {
129         return *reinterpret_cast<const Instr*>(this);
130     }
131 
132     // Set the raw instruction bits to value.
setInstructionBits(Instr value)133     inline void setInstructionBits(Instr value) {
134         *reinterpret_cast<Instr*>(this) = value;
135     }
136 
137     // Read one particular bit out of the instruction bits.
bit(int nr) const138     inline int bit(int nr) const {
139         return (instructionBits() >> nr) & 1;
140     }
141 
142     // Read a bit field's value out of the instruction bits.
bits(int hi,int lo) const143     inline int bits(int hi, int lo) const {
144         return (instructionBits() >> lo) & ((2 << (hi - lo)) - 1);
145     }
146 
147     // Read a bit field out of the instruction bits.
bitField(int hi,int lo) const148     inline int bitField(int hi, int lo) const {
149         return instructionBits() & (((2 << (hi - lo)) - 1) << lo);
150     }
151 
152     // Accessors for the different named fields used in the ARM encoding.
153     // The naming of these accessor corresponds to figure A3-1.
154     //
155     // Two kind of accessors are declared:
156     // - <Name>Field() will return the raw field, i.e. the field's bits at their
157     //   original place in the instruction encoding.
158     //   e.g. if instr is the 'addgt r0, r1, r2' instruction, encoded as
159     //   0xC0810002 conditionField(instr) will return 0xC0000000.
160     // - <Name>Value() will return the field value, shifted back to bit 0.
161     //   e.g. if instr is the 'addgt r0, r1, r2' instruction, encoded as
162     //   0xC0810002 conditionField(instr) will return 0xC.
163 
164     // Generally applicable fields
conditionField() const165     inline Assembler::ARMCondition conditionField() const {
166         return static_cast<Assembler::ARMCondition>(bitField(31, 28));
167     }
typeValue() const168     inline int typeValue() const { return bits(27, 25); }
specialValue() const169     inline int specialValue() const { return bits(27, 23); }
170 
rnValue() const171     inline int rnValue() const { return bits(19, 16); }
rdValue() const172     inline int rdValue() const { return bits(15, 12); }
173 
coprocessorValue() const174     inline int coprocessorValue() const { return bits(11, 8); }
175 
176     // Support for VFP.
177     // Vn(19-16) | Vd(15-12) |  Vm(3-0)
vnValue() const178     inline int vnValue() const { return bits(19, 16); }
vmValue() const179     inline int vmValue() const { return bits(3, 0); }
vdValue() const180     inline int vdValue() const { return bits(15, 12); }
nValue() const181     inline int nValue() const { return bit(7); }
mValue() const182     inline int mValue() const { return bit(5); }
dValue() const183     inline int dValue() const { return bit(22); }
rtValue() const184     inline int rtValue() const { return bits(15, 12); }
pValue() const185     inline int pValue() const { return bit(24); }
uValue() const186     inline int uValue() const { return bit(23); }
opc1Value() const187     inline int opc1Value() const { return (bit(23) << 2) | bits(21, 20); }
opc2Value() const188     inline int opc2Value() const { return bits(19, 16); }
opc3Value() const189     inline int opc3Value() const { return bits(7, 6); }
szValue() const190     inline int szValue() const { return bit(8); }
VLValue() const191     inline int VLValue() const { return bit(20); }
VCValue() const192     inline int VCValue() const { return bit(8); }
VAValue() const193     inline int VAValue() const { return bits(23, 21); }
VBValue() const194     inline int VBValue() const { return bits(6, 5); }
VFPNRegValue(VFPRegPrecision pre)195     inline int VFPNRegValue(VFPRegPrecision pre) { return VFPGlueRegValue(pre, 16, 7); }
VFPMRegValue(VFPRegPrecision pre)196     inline int VFPMRegValue(VFPRegPrecision pre) { return VFPGlueRegValue(pre, 0, 5); }
VFPDRegValue(VFPRegPrecision pre)197     inline int VFPDRegValue(VFPRegPrecision pre) { return VFPGlueRegValue(pre, 12, 22); }
198 
199     // Fields used in Data processing instructions.
opcodeValue() const200     inline int opcodeValue() const { return static_cast<ALUOp>(bits(24, 21)); }
opcodeField() const201     inline ALUOp opcodeField() const { return static_cast<ALUOp>(bitField(24, 21)); }
sValue() const202     inline int sValue() const { return bit(20); }
203 
204     // With register.
rmValue() const205     inline int rmValue() const { return bits(3, 0); }
shifttypeValue() const206     inline ShiftType shifttypeValue() const { return static_cast<ShiftType>(bits(6, 5)); }
rsValue() const207     inline int rsValue() const { return bits(11, 8); }
shiftAmountValue() const208     inline int shiftAmountValue() const { return bits(11, 7); }
209 
210     // With immediate.
rotateValue() const211     inline int rotateValue() const { return bits(11, 8); }
immed8Value() const212     inline int immed8Value() const { return bits(7, 0); }
immed4Value() const213     inline int immed4Value() const { return bits(19, 16); }
immedMovwMovtValue() const214     inline int immedMovwMovtValue() const { return immed4Value() << 12 | offset12Value(); }
215 
216     // Fields used in Load/Store instructions.
PUValue() const217     inline int PUValue() const { return bits(24, 23); }
PUField() const218     inline int PUField() const { return bitField(24, 23); }
bValue() const219     inline int bValue() const { return bit(22); }
wValue() const220     inline int wValue() const { return bit(21); }
lValue() const221     inline int lValue() const { return bit(20); }
222 
223     // With register uses same fields as Data processing instructions above with
224     // immediate.
offset12Value() const225     inline int offset12Value() const { return bits(11, 0); }
226 
227     // Multiple.
rlistValue() const228     inline int rlistValue() const { return bits(15, 0); }
229 
230     // Extra loads and stores.
signValue() const231     inline int signValue() const { return bit(6); }
hValue() const232     inline int hValue() const { return bit(5); }
immedHValue() const233     inline int immedHValue() const { return bits(11, 8); }
immedLValue() const234     inline int immedLValue() const { return bits(3, 0); }
235 
236     // Fields used in Branch instructions.
linkValue() const237     inline int linkValue() const { return bit(24); }
sImmed24Value() const238     inline int sImmed24Value() const { return ((instructionBits() << 8) >> 8); }
239 
240     // Fields used in Software interrupt instructions.
svcValue() const241     inline SoftwareInterruptCodes svcValue() const {
242         return static_cast<SoftwareInterruptCodes>(bits(23, 0));
243     }
244 
245     // Test for special encodings of type 0 instructions (extra loads and
246     // stores, as well as multiplications).
isSpecialType0() const247     inline bool isSpecialType0() const { return (bit(7) == 1) && (bit(4) == 1); }
248 
249     // Test for miscellaneous instructions encodings of type 0 instructions.
isMiscType0() const250     inline bool isMiscType0() const {
251         return bit(24) == 1 && bit(23) == 0 && bit(20) == 0 && (bit(7) == 0);
252     }
253 
254     // Test for a nop instruction, which falls under type 1.
isNopType1() const255     inline bool isNopType1() const { return bits(24, 0) == 0x0120F000; }
256 
257     // Test for a stop instruction.
isStop() const258     inline bool isStop() const {
259         return typeValue() == 7 && bit(24) == 1 && svcValue() >= kStopCode;
260     }
261 
262     // Special accessors that test for existence of a value.
hasS() const263     inline bool hasS()    const { return sValue() == 1; }
hasB() const264     inline bool hasB()    const { return bValue() == 1; }
hasW() const265     inline bool hasW()    const { return wValue() == 1; }
hasL() const266     inline bool hasL()    const { return lValue() == 1; }
hasU() const267     inline bool hasU()    const { return uValue() == 1; }
hasSign() const268     inline bool hasSign() const { return signValue() == 1; }
hasH() const269     inline bool hasH()    const { return hValue() == 1; }
hasLink() const270     inline bool hasLink() const { return linkValue() == 1; }
271 
272     // Decoding the double immediate in the vmov instruction.
273     double doubleImmedVmov() const;
274     // Decoding the float32 immediate in the vmov.f32 instruction.
275     float float32ImmedVmov() const;
276 
277   private:
278     // Join split register codes, depending on single or double precision.
279     // four_bit is the position of the least-significant bit of the four
280     // bit specifier. one_bit is the position of the additional single bit
281     // specifier.
VFPGlueRegValue(VFPRegPrecision pre,int four_bit,int one_bit)282     inline int VFPGlueRegValue(VFPRegPrecision pre, int four_bit, int one_bit) {
283         if (pre == kSinglePrecision)
284             return (bits(four_bit + 3, four_bit) << 1) | bit(one_bit);
285         return (bit(one_bit) << 4) | bits(four_bit + 3, four_bit);
286     }
287 
288     SimInstruction() = delete;
289     SimInstruction(const SimInstruction& other) = delete;
290     void operator=(const SimInstruction& other) = delete;
291 };
292 
293 double
doubleImmedVmov() const294 SimInstruction::doubleImmedVmov() const
295 {
296     // Reconstruct a double from the immediate encoded in the vmov instruction.
297     //
298     //   instruction: [xxxxxxxx,xxxxabcd,xxxxxxxx,xxxxefgh]
299     //   double: [aBbbbbbb,bbcdefgh,00000000,00000000,
300     //            00000000,00000000,00000000,00000000]
301     //
302     // where B = ~b. Only the high 16 bits are affected.
303     uint64_t high16;
304     high16  = (bits(17, 16) << 4) | bits(3, 0);   // xxxxxxxx,xxcdefgh.
305     high16 |= (0xff * bit(18)) << 6;              // xxbbbbbb,bbxxxxxx.
306     high16 |= (bit(18) ^ 1) << 14;                // xBxxxxxx,xxxxxxxx.
307     high16 |= bit(19) << 15;                      // axxxxxxx,xxxxxxxx.
308 
309     uint64_t imm = high16 << 48;
310     return mozilla::BitwiseCast<double>(imm);
311 }
312 
313 float
float32ImmedVmov() const314 SimInstruction::float32ImmedVmov() const
315 {
316     // Reconstruct a float32 from the immediate encoded in the vmov instruction.
317     //
318     //   instruction: [xxxxxxxx,xxxxabcd,xxxxxxxx,xxxxefgh]
319     //   float32: [aBbbbbbc, defgh000, 00000000, 00000000]
320     //
321     // where B = ~b. Only the high 16 bits are affected.
322     uint32_t imm;
323     imm  = (bits(17, 16) << 23) | (bits(3, 0) << 19); // xxxxxxxc,defgh000.0.0
324     imm |= (0x1f * bit(18)) << 25;                    // xxbbbbbx,xxxxxxxx.0.0
325     imm |= (bit(18) ^ 1) << 30;                       // xBxxxxxx,xxxxxxxx.0.0
326     imm |= bit(19) << 31;                             // axxxxxxx,xxxxxxxx.0.0
327 
328     return mozilla::BitwiseCast<float>(imm);
329 }
330 
331 class CachePage
332 {
333   public:
334     static const int LINE_VALID = 0;
335     static const int LINE_INVALID = 1;
336     static const int kPageShift = 12;
337     static const int kPageSize = 1 << kPageShift;
338     static const int kPageMask = kPageSize - 1;
339     static const int kLineShift = 2;  // The cache line is only 4 bytes right now.
340     static const int kLineLength = 1 << kLineShift;
341     static const int kLineMask = kLineLength - 1;
342 
CachePage()343     CachePage() {
344         memset(&validity_map_, LINE_INVALID, sizeof(validity_map_));
345     }
validityByte(int offset)346     char* validityByte(int offset) {
347         return &validity_map_[offset >> kLineShift];
348     }
cachedData(int offset)349     char* cachedData(int offset) {
350         return &data_[offset];
351     }
352 
353   private:
354     char data_[kPageSize];   // The cached data.
355     static const int kValidityMapSize = kPageSize >> kLineShift;
356     char validity_map_[kValidityMapSize];  // One byte per line.
357 };
358 
359 // Protects the icache() and redirection() properties of the
360 // Simulator.
361 class AutoLockSimulatorCache
362 {
363   public:
AutoLockSimulatorCache(Simulator * sim)364     explicit AutoLockSimulatorCache(Simulator* sim) : sim_(sim) {
365         PR_Lock(sim_->cacheLock_);
366         MOZ_ASSERT(!sim_->cacheLockHolder_);
367 #ifdef DEBUG
368         sim_->cacheLockHolder_ = PR_GetCurrentThread();
369 #endif
370     }
371 
~AutoLockSimulatorCache()372     ~AutoLockSimulatorCache() {
373         MOZ_ASSERT(sim_->cacheLockHolder_);
374 #ifdef DEBUG
375         sim_->cacheLockHolder_ = nullptr;
376 #endif
377         PR_Unlock(sim_->cacheLock_);
378     }
379 
380   private:
381     Simulator* const sim_;
382 };
383 
384 bool Simulator::ICacheCheckingEnabled = false;
385 
386 int64_t Simulator::StopSimAt = -1L;
387 
388 Simulator*
Create()389 Simulator::Create()
390 {
391     Simulator* sim = js_new<Simulator>();
392     if (!sim)
393         return nullptr;
394 
395     if (!sim->init()) {
396         js_delete(sim);
397         return nullptr;
398     }
399 
400     if (getenv("ARM_SIM_ICACHE_CHECKS"))
401         Simulator::ICacheCheckingEnabled = true;
402 
403     char* stopAtStr = getenv("ARM_SIM_STOP_AT");
404     int64_t stopAt;
405     if (stopAtStr && sscanf(stopAtStr, "%lld", &stopAt) == 1) {
406         fprintf(stderr, "\nStopping simulation at icount %lld\n", stopAt);
407         Simulator::StopSimAt = stopAt;
408     }
409 
410     return sim;
411 }
412 
413 void
Destroy(Simulator * sim)414 Simulator::Destroy(Simulator* sim)
415 {
416     js_delete(sim);
417 }
418 
419 // The ArmDebugger class is used by the simulator while debugging simulated ARM
420 // code.
421 class ArmDebugger {
422   public:
ArmDebugger(Simulator * sim)423     explicit ArmDebugger(Simulator* sim) : sim_(sim) { }
424 
425     void stop(SimInstruction* instr);
426     void debug();
427 
428   private:
429     static const Instr kBreakpointInstr = (Assembler::AL | (7 * (1 << 25)) | (1* (1 << 24)) | kBreakpoint);
430     static const Instr kNopInstr = (Assembler::AL | (13 * (1 << 21)));
431 
432     Simulator* sim_;
433 
434     int32_t getRegisterValue(int regnum);
435     double getRegisterPairDoubleValue(int regnum);
436     double getVFPDoubleRegisterValue(int regnum);
437     bool getValue(const char* desc, int32_t* value);
438     bool getVFPDoubleValue(const char* desc, double* value);
439 
440     // Set or delete a breakpoint. Returns true if successful.
441     bool setBreakpoint(SimInstruction* breakpc);
442     bool deleteBreakpoint(SimInstruction* breakpc);
443 
444     // Undo and redo all breakpoints. This is needed to bracket disassembly and
445     // execution to skip past breakpoints when run from the debugger.
446     void undoBreakpoints();
447     void redoBreakpoints();
448 };
449 
450 void
stop(SimInstruction * instr)451 ArmDebugger::stop(SimInstruction * instr)
452 {
453     // Get the stop code.
454     uint32_t code = instr->svcValue() & kStopCodeMask;
455     // Retrieve the encoded address, which comes just after this stop.
456     char* msg = *reinterpret_cast<char**>(sim_->get_pc()
457                                           + SimInstruction::kInstrSize);
458     // Update this stop description.
459     if (sim_->isWatchedStop(code) && !sim_->watched_stops_[code].desc) {
460         sim_->watched_stops_[code].desc = msg;
461     }
462     // Print the stop message and code if it is not the default code.
463     if (code != kMaxStopCode) {
464         printf("Simulator hit stop %u: %s\n", code, msg);
465     } else {
466         printf("Simulator hit %s\n", msg);
467     }
468     sim_->set_pc(sim_->get_pc() + 2 * SimInstruction::kInstrSize);
469     debug();
470 }
471 
472 int32_t
getRegisterValue(int regnum)473 ArmDebugger::getRegisterValue(int regnum)
474 {
475     if (regnum == Registers::pc)
476         return sim_->get_pc();
477     return sim_->get_register(regnum);
478 }
479 
480 double
getRegisterPairDoubleValue(int regnum)481 ArmDebugger::getRegisterPairDoubleValue(int regnum)
482 {
483     return sim_->get_double_from_register_pair(regnum);
484 }
485 
486 double
getVFPDoubleRegisterValue(int regnum)487 ArmDebugger::getVFPDoubleRegisterValue(int regnum)
488 {
489     return sim_->get_double_from_d_register(regnum);
490 }
491 
492 bool
getValue(const char * desc,int32_t * value)493 ArmDebugger::getValue(const char* desc, int32_t* value)
494 {
495     Register reg = Register::FromName(desc);
496     if (reg != InvalidReg) {
497         *value = getRegisterValue(reg.code());
498         return true;
499     }
500     if (strncmp(desc, "0x", 2) == 0)
501         return sscanf(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
502     return sscanf(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
503 }
504 
505 bool
getVFPDoubleValue(const char * desc,double * value)506 ArmDebugger::getVFPDoubleValue(const char* desc, double* value)
507 {
508     FloatRegister reg(FloatRegister::FromName(desc));
509     if (reg != InvalidFloatReg) {
510         *value = sim_->get_double_from_d_register(reg.code());
511         return true;
512     }
513     return false;
514 }
515 
516 bool
setBreakpoint(SimInstruction * breakpc)517 ArmDebugger::setBreakpoint(SimInstruction* breakpc)
518 {
519     // Check if a breakpoint can be set. If not return without any side-effects.
520     if (sim_->break_pc_)
521         return false;
522 
523     // Set the breakpoint.
524     sim_->break_pc_ = breakpc;
525     sim_->break_instr_ = breakpc->instructionBits();
526     // Not setting the breakpoint instruction in the code itself. It will be set
527     // when the debugger shell continues.
528     return true;
529 }
530 
531 bool
deleteBreakpoint(SimInstruction * breakpc)532 ArmDebugger::deleteBreakpoint(SimInstruction* breakpc)
533 {
534     if (sim_->break_pc_ != nullptr)
535         sim_->break_pc_->setInstructionBits(sim_->break_instr_);
536 
537     sim_->break_pc_ = nullptr;
538     sim_->break_instr_ = 0;
539     return true;
540 }
541 
542 void
undoBreakpoints()543 ArmDebugger::undoBreakpoints()
544 {
545     if (sim_->break_pc_)
546         sim_->break_pc_->setInstructionBits(sim_->break_instr_);
547 }
548 
549 void
redoBreakpoints()550 ArmDebugger::redoBreakpoints()
551 {
552     if (sim_->break_pc_)
553         sim_->break_pc_->setInstructionBits(kBreakpointInstr);
554 }
555 
556 static char*
ReadLine(const char * prompt)557 ReadLine(const char* prompt)
558 {
559     char* result = nullptr;
560     char line_buf[256];
561     int offset = 0;
562     bool keep_going = true;
563     fprintf(stdout, "%s", prompt);
564     fflush(stdout);
565     while (keep_going) {
566         if (fgets(line_buf, sizeof(line_buf), stdin) == nullptr) {
567             // fgets got an error. Just give up.
568             if (result)
569                 js_delete(result);
570             return nullptr;
571         }
572         int len = strlen(line_buf);
573         if (len > 0 && line_buf[len - 1] == '\n') {
574             // Since we read a new line we are done reading the line. This will
575             // exit the loop after copying this buffer into the result.
576             keep_going = false;
577         }
578         if (!result) {
579             // Allocate the initial result and make room for the terminating
580             // '\0'.
581             result = (char*)js_malloc(len + 1);
582             if (!result)
583                 return nullptr;
584         } else {
585             // Allocate a new result with enough room for the new addition.
586             int new_len = offset + len + 1;
587             char* new_result = (char*)js_malloc(new_len);
588             if (!new_result)
589                 return nullptr;
590             // Copy the existing input into the new array and set the new
591             // array as the result.
592             memcpy(new_result, result, offset * sizeof(char));
593             js_free(result);
594             result = new_result;
595         }
596         // Copy the newly read line into the result.
597         memcpy(result + offset, line_buf, len * sizeof(char));
598         offset += len;
599     }
600 
601     MOZ_ASSERT(result);
602     result[offset] = '\0';
603     return result;
604 }
605 
606 
607 void
debug()608 ArmDebugger::debug()
609 {
610     intptr_t last_pc = -1;
611     bool done = false;
612 
613 #define COMMAND_SIZE 63
614 #define ARG_SIZE 255
615 
616 #define STR(a) #a
617 #define XSTR(a) STR(a)
618 
619     char cmd[COMMAND_SIZE + 1];
620     char arg1[ARG_SIZE + 1];
621     char arg2[ARG_SIZE + 1];
622     char* argv[3] = { cmd, arg1, arg2 };
623 
624     // Make sure to have a proper terminating character if reaching the limit.
625     cmd[COMMAND_SIZE] = 0;
626     arg1[ARG_SIZE] = 0;
627     arg2[ARG_SIZE] = 0;
628 
629     // Undo all set breakpoints while running in the debugger shell. This will
630     // make them invisible to all commands.
631     undoBreakpoints();
632 
633 #ifndef JS_DISASM_ARM
634     static bool disasm_warning_printed = false;
635     if (!disasm_warning_printed) {
636         printf("  No ARM disassembler present.  Enable JS_DISASM_ARM in configure.in.");
637         disasm_warning_printed = true;
638     }
639 #endif
640 
641     while (!done && !sim_->has_bad_pc()) {
642         if (last_pc != sim_->get_pc()) {
643 #ifdef JS_DISASM_ARM
644             disasm::NameConverter converter;
645             disasm::Disassembler dasm(converter);
646             disasm::EmbeddedVector<char, disasm::ReasonableBufferSize> buffer;
647             dasm.InstructionDecode(buffer,
648                                    reinterpret_cast<uint8_t*>(sim_->get_pc()));
649             printf("  0x%08x  %s\n", sim_->get_pc(), buffer.start());
650 #endif
651             last_pc = sim_->get_pc();
652         }
653         char* line = ReadLine("sim> ");
654         if (line == nullptr) {
655             break;
656         } else {
657             char* last_input = sim_->lastDebuggerInput();
658             if (strcmp(line, "\n") == 0 && last_input != nullptr) {
659                 line = last_input;
660             } else {
661                 // Ownership is transferred to sim_;
662                 sim_->setLastDebuggerInput(line);
663             }
664 
665             // Use sscanf to parse the individual parts of the command line. At the
666             // moment no command expects more than two parameters.
667             int argc = sscanf(line,
668                               "%" XSTR(COMMAND_SIZE) "s "
669                               "%" XSTR(ARG_SIZE) "s "
670                               "%" XSTR(ARG_SIZE) "s",
671                               cmd, arg1, arg2);
672             if (argc < 0) {
673                 continue;
674             } else if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
675                 sim_->instructionDecode(reinterpret_cast<SimInstruction*>(sim_->get_pc()));
676                 sim_->icount_++;
677             } else if ((strcmp(cmd, "skip") == 0)) {
678                 sim_->set_pc(sim_->get_pc() + 4);
679                 sim_->icount_++;
680             } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
681                 // Execute the one instruction we broke at with breakpoints
682                 // disabled.
683                 sim_->instructionDecode(reinterpret_cast<SimInstruction*>(sim_->get_pc()));
684                 sim_->icount_++;
685                 // Leave the debugger shell.
686                 done = true;
687             } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
688                 if (argc == 2 || (argc == 3 && strcmp(arg2, "fp") == 0)) {
689                     int32_t value;
690                     double dvalue;
691                     if (strcmp(arg1, "all") == 0) {
692                         for (uint32_t i = 0; i < Registers::Total; i++) {
693                             value = getRegisterValue(i);
694                             printf("%3s: 0x%08x %10d", Registers::GetName(i), value, value);
695                             if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
696                                 i < 8 &&
697                                 (i % 2) == 0) {
698                                 dvalue = getRegisterPairDoubleValue(i);
699                                 printf(" (%.16g)\n", dvalue);
700                             } else {
701                                 printf("\n");
702                             }
703                         }
704                         for (uint32_t i = 0; i < FloatRegisters::TotalPhys; i++) {
705                             dvalue = getVFPDoubleRegisterValue(i);
706                             uint64_t as_words = mozilla::BitwiseCast<uint64_t>(dvalue);
707                             printf("%3s: %.16g 0x%08x %08x\n",
708                                    FloatRegister::FromCode(i).name(),
709                                    dvalue,
710                                    static_cast<uint32_t>(as_words >> 32),
711                                    static_cast<uint32_t>(as_words & 0xffffffff));
712                         }
713                     } else {
714                         if (getValue(arg1, &value)) {
715                             printf("%s: 0x%08x %d \n", arg1, value, value);
716                         } else if (getVFPDoubleValue(arg1, &dvalue)) {
717                             uint64_t as_words = mozilla::BitwiseCast<uint64_t>(dvalue);
718                             printf("%s: %.16g 0x%08x %08x\n",
719                                    arg1,
720                                    dvalue,
721                                    static_cast<uint32_t>(as_words >> 32),
722                                    static_cast<uint32_t>(as_words & 0xffffffff));
723                         } else {
724                             printf("%s unrecognized\n", arg1);
725                         }
726                     }
727                 } else {
728                     printf("print <register>\n");
729                 }
730             } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
731                 int32_t* cur = nullptr;
732                 int32_t* end = nullptr;
733                 int next_arg = 1;
734 
735                 if (strcmp(cmd, "stack") == 0) {
736                     cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
737                 } else {  // "mem"
738                     int32_t value;
739                     if (!getValue(arg1, &value)) {
740                         printf("%s unrecognized\n", arg1);
741                         continue;
742                     }
743                     cur = reinterpret_cast<int32_t*>(value);
744                     next_arg++;
745                 }
746 
747                 int32_t words;
748                 if (argc == next_arg) {
749                     words = 10;
750                 } else {
751                     if (!getValue(argv[next_arg], &words)) {
752                         words = 10;
753                     }
754                 }
755                 end = cur + words;
756 
757                 while (cur < end) {
758                     printf("  %p:  0x%08x %10d", cur, *cur, *cur);
759                     printf("\n");
760                     cur++;
761                 }
762             } else if (strcmp(cmd, "disasm") == 0 || strcmp(cmd, "di") == 0) {
763 #ifdef JS_DISASM_ARM
764                 uint8_t* prev = nullptr;
765                 uint8_t* cur = nullptr;
766                 uint8_t* end = nullptr;
767 
768                 if (argc == 1) {
769                     cur = reinterpret_cast<uint8_t*>(sim_->get_pc());
770                     end = cur + (10 * SimInstruction::kInstrSize);
771                 } else if (argc == 2) {
772                     Register reg = Register::FromName(arg1);
773                     if (reg != InvalidReg || strncmp(arg1, "0x", 2) == 0) {
774                         // The argument is an address or a register name.
775                         int32_t value;
776                         if (getValue(arg1, &value)) {
777                             cur = reinterpret_cast<uint8_t*>(value);
778                             // Disassemble 10 instructions at <arg1>.
779                             end = cur + (10 * SimInstruction::kInstrSize);
780                         }
781                     } else {
782                         // The argument is the number of instructions.
783                         int32_t value;
784                         if (getValue(arg1, &value)) {
785                             cur = reinterpret_cast<uint8_t*>(sim_->get_pc());
786                             // Disassemble <arg1> instructions.
787                             end = cur + (value * SimInstruction::kInstrSize);
788                         }
789                     }
790                 } else {
791                     int32_t value1;
792                     int32_t value2;
793                     if (getValue(arg1, &value1) && getValue(arg2, &value2)) {
794                         cur = reinterpret_cast<uint8_t*>(value1);
795                         end = cur + (value2 * SimInstruction::kInstrSize);
796                     }
797                 }
798                 while (cur < end) {
799                     disasm::NameConverter converter;
800                     disasm::Disassembler dasm(converter);
801                     disasm::EmbeddedVector<char, disasm::ReasonableBufferSize> buffer;
802 
803                     prev = cur;
804                     cur += dasm.InstructionDecode(buffer, cur);
805                     printf("  0x%08x  %s\n", reinterpret_cast<uint32_t>(prev), buffer.start());
806                 }
807 #endif
808             } else if (strcmp(cmd, "gdb") == 0) {
809                 printf("relinquishing control to gdb\n");
810                 asm("int $3");
811                 printf("regaining control from gdb\n");
812             } else if (strcmp(cmd, "break") == 0) {
813                 if (argc == 2) {
814                     int32_t value;
815                     if (getValue(arg1, &value)) {
816                         if (!setBreakpoint(reinterpret_cast<SimInstruction*>(value)))
817                             printf("setting breakpoint failed\n");
818                     } else {
819                         printf("%s unrecognized\n", arg1);
820                     }
821                 } else {
822                     printf("break <address>\n");
823                 }
824             } else if (strcmp(cmd, "del") == 0) {
825                 if (!deleteBreakpoint(nullptr)) {
826                     printf("deleting breakpoint failed\n");
827                 }
828             } else if (strcmp(cmd, "flags") == 0) {
829                 printf("N flag: %d; ", sim_->n_flag_);
830                 printf("Z flag: %d; ", sim_->z_flag_);
831                 printf("C flag: %d; ", sim_->c_flag_);
832                 printf("V flag: %d\n", sim_->v_flag_);
833                 printf("INVALID OP flag: %d; ", sim_->inv_op_vfp_flag_);
834                 printf("DIV BY ZERO flag: %d; ", sim_->div_zero_vfp_flag_);
835                 printf("OVERFLOW flag: %d; ", sim_->overflow_vfp_flag_);
836                 printf("UNDERFLOW flag: %d; ", sim_->underflow_vfp_flag_);
837                 printf("INEXACT flag: %d;\n", sim_->inexact_vfp_flag_);
838             } else if (strcmp(cmd, "stop") == 0) {
839                 int32_t value;
840                 intptr_t stop_pc = sim_->get_pc() - 2 * SimInstruction::kInstrSize;
841                 SimInstruction* stop_instr = reinterpret_cast<SimInstruction*>(stop_pc);
842                 SimInstruction* msg_address =
843                     reinterpret_cast<SimInstruction*>(stop_pc + SimInstruction::kInstrSize);
844                 if ((argc == 2) && (strcmp(arg1, "unstop") == 0)) {
845                     // Remove the current stop.
846                     if (sim_->isStopInstruction(stop_instr)) {
847                         stop_instr->setInstructionBits(kNopInstr);
848                         msg_address->setInstructionBits(kNopInstr);
849                     } else {
850                         printf("Not at debugger stop.\n");
851                     }
852                 } else if (argc == 3) {
853                     // Print information about all/the specified breakpoint(s).
854                     if (strcmp(arg1, "info") == 0) {
855                         if (strcmp(arg2, "all") == 0) {
856                             printf("Stop information:\n");
857                             for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++)
858                                 sim_->printStopInfo(i);
859                         } else if (getValue(arg2, &value)) {
860                             sim_->printStopInfo(value);
861                         } else {
862                             printf("Unrecognized argument.\n");
863                         }
864                     } else if (strcmp(arg1, "enable") == 0) {
865                         // Enable all/the specified breakpoint(s).
866                         if (strcmp(arg2, "all") == 0) {
867                             for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++)
868                                 sim_->enableStop(i);
869                         } else if (getValue(arg2, &value)) {
870                             sim_->enableStop(value);
871                         } else {
872                             printf("Unrecognized argument.\n");
873                         }
874                     } else if (strcmp(arg1, "disable") == 0) {
875                         // Disable all/the specified breakpoint(s).
876                         if (strcmp(arg2, "all") == 0) {
877                             for (uint32_t i = 0; i < sim_->kNumOfWatchedStops; i++) {
878                                 sim_->disableStop(i);
879                             }
880                         } else if (getValue(arg2, &value)) {
881                             sim_->disableStop(value);
882                         } else {
883                             printf("Unrecognized argument.\n");
884                         }
885                     }
886                 } else {
887                     printf("Wrong usage. Use help command for more information.\n");
888                 }
889             } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
890                 printf("cont\n");
891                 printf("  continue execution (alias 'c')\n");
892                 printf("skip\n");
893                 printf("  skip one instruction (set pc to next instruction)\n");
894                 printf("stepi\n");
895                 printf("  step one instruction (alias 'si')\n");
896                 printf("print <register>\n");
897                 printf("  print register content (alias 'p')\n");
898                 printf("  use register name 'all' to print all registers\n");
899                 printf("  add argument 'fp' to print register pair double values\n");
900                 printf("flags\n");
901                 printf("  print flags\n");
902                 printf("stack [<words>]\n");
903                 printf("  dump stack content, default dump 10 words)\n");
904                 printf("mem <address> [<words>]\n");
905                 printf("  dump memory content, default dump 10 words)\n");
906                 printf("disasm [<instructions>]\n");
907                 printf("disasm [<address/register>]\n");
908                 printf("disasm [[<address/register>] <instructions>]\n");
909                 printf("  disassemble code, default is 10 instructions\n");
910                 printf("  from pc (alias 'di')\n");
911                 printf("gdb\n");
912                 printf("  enter gdb\n");
913                 printf("break <address>\n");
914                 printf("  set a break point on the address\n");
915                 printf("del\n");
916                 printf("  delete the breakpoint\n");
917                 printf("stop feature:\n");
918                 printf("  Description:\n");
919                 printf("    Stops are debug instructions inserted by\n");
920                 printf("    the Assembler::stop() function.\n");
921                 printf("    When hitting a stop, the Simulator will\n");
922                 printf("    stop and and give control to the ArmDebugger.\n");
923                 printf("    The first %d stop codes are watched:\n",
924                        Simulator::kNumOfWatchedStops);
925                 printf("    - They can be enabled / disabled: the Simulator\n");
926                 printf("      will / won't stop when hitting them.\n");
927                 printf("    - The Simulator keeps track of how many times they \n");
928                 printf("      are met. (See the info command.) Going over a\n");
929                 printf("      disabled stop still increases its counter. \n");
930                 printf("  Commands:\n");
931                 printf("    stop info all/<code> : print infos about number <code>\n");
932                 printf("      or all stop(s).\n");
933                 printf("    stop enable/disable all/<code> : enables / disables\n");
934                 printf("      all or number <code> stop(s)\n");
935                 printf("    stop unstop\n");
936                 printf("      ignore the stop instruction at the current location\n");
937                 printf("      from now on\n");
938             } else {
939                 printf("Unknown command: %s\n", cmd);
940             }
941         }
942     }
943 
944     // Add all the breakpoints back to stop execution and enter the debugger
945     // shell when hit.
946     redoBreakpoints();
947 
948 #undef COMMAND_SIZE
949 #undef ARG_SIZE
950 
951 #undef STR
952 #undef XSTR
953 }
954 
955 static bool
AllOnOnePage(uintptr_t start,int size)956 AllOnOnePage(uintptr_t start, int size)
957 {
958     intptr_t start_page = (start & ~CachePage::kPageMask);
959     intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
960     return start_page == end_page;
961 }
962 
963 static CachePage*
GetCachePageLocked(Simulator::ICacheMap & i_cache,void * page)964 GetCachePageLocked(Simulator::ICacheMap& i_cache, void* page)
965 {
966     MOZ_ASSERT(Simulator::ICacheCheckingEnabled);
967 
968     Simulator::ICacheMap::AddPtr p = i_cache.lookupForAdd(page);
969     if (p)
970         return p->value();
971 
972     AutoEnterOOMUnsafeRegion oomUnsafe;
973     CachePage* new_page = js_new<CachePage>();
974     if (!new_page || !i_cache.add(p, page, new_page))
975         oomUnsafe.crash("Simulator CachePage");
976 
977     return new_page;
978 }
979 
980 // Flush from start up to and not including start + size.
981 static void
FlushOnePageLocked(Simulator::ICacheMap & i_cache,intptr_t start,int size)982 FlushOnePageLocked(Simulator::ICacheMap& i_cache, intptr_t start, int size)
983 {
984     MOZ_ASSERT(size <= CachePage::kPageSize);
985     MOZ_ASSERT(AllOnOnePage(start, size - 1));
986     MOZ_ASSERT((start & CachePage::kLineMask) == 0);
987     MOZ_ASSERT((size & CachePage::kLineMask) == 0);
988 
989     void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
990     int offset = (start & CachePage::kPageMask);
991     CachePage* cache_page = GetCachePageLocked(i_cache, page);
992     char* valid_bytemap = cache_page->validityByte(offset);
993     memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
994 }
995 
996 static void
FlushICacheLocked(Simulator::ICacheMap & i_cache,void * start_addr,size_t size)997 FlushICacheLocked(Simulator::ICacheMap& i_cache, void* start_addr, size_t size)
998 {
999     intptr_t start = reinterpret_cast<intptr_t>(start_addr);
1000     int intra_line = (start & CachePage::kLineMask);
1001     start -= intra_line;
1002     size += intra_line;
1003     size = ((size - 1) | CachePage::kLineMask) + 1;
1004     int offset = (start & CachePage::kPageMask);
1005     while (!AllOnOnePage(start, size - 1)) {
1006         int bytes_to_flush = CachePage::kPageSize - offset;
1007         FlushOnePageLocked(i_cache, start, bytes_to_flush);
1008         start += bytes_to_flush;
1009         size -= bytes_to_flush;
1010         MOZ_ASSERT((start & CachePage::kPageMask) == 0);
1011         offset = 0;
1012     }
1013     if (size != 0)
1014         FlushOnePageLocked(i_cache, start, size);
1015 }
1016 
1017 static void
CheckICacheLocked(Simulator::ICacheMap & i_cache,SimInstruction * instr)1018 CheckICacheLocked(Simulator::ICacheMap& i_cache, SimInstruction* instr)
1019 {
1020     intptr_t address = reinterpret_cast<intptr_t>(instr);
1021     void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
1022     void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
1023     int offset = (address & CachePage::kPageMask);
1024     CachePage* cache_page = GetCachePageLocked(i_cache, page);
1025     char* cache_valid_byte = cache_page->validityByte(offset);
1026     bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
1027     char* cached_line = cache_page->cachedData(offset & ~CachePage::kLineMask);
1028     if (cache_hit) {
1029         // Check that the data in memory matches the contents of the I-cache.
1030         MOZ_ASSERT(memcmp(reinterpret_cast<void*>(instr),
1031                           cache_page->cachedData(offset),
1032                           SimInstruction::kInstrSize) == 0);
1033     } else {
1034         // Cache miss. Load memory into the cache.
1035         memcpy(cached_line, line, CachePage::kLineLength);
1036         *cache_valid_byte = CachePage::LINE_VALID;
1037     }
1038 }
1039 
1040 HashNumber
hash(const Lookup & l)1041 Simulator::ICacheHasher::hash(const Lookup& l)
1042 {
1043     return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(l)) >> 2;
1044 }
1045 
1046 bool
match(const Key & k,const Lookup & l)1047 Simulator::ICacheHasher::match(const Key& k, const Lookup& l)
1048 {
1049     MOZ_ASSERT((reinterpret_cast<intptr_t>(k) & CachePage::kPageMask) == 0);
1050     MOZ_ASSERT((reinterpret_cast<intptr_t>(l) & CachePage::kPageMask) == 0);
1051     return k == l;
1052 }
1053 
1054 void
setLastDebuggerInput(char * input)1055 Simulator::setLastDebuggerInput(char* input)
1056 {
1057     js_free(lastDebuggerInput_);
1058     lastDebuggerInput_ = input;
1059 }
1060 
1061 void
FlushICache(void * start_addr,size_t size)1062 Simulator::FlushICache(void* start_addr, size_t size)
1063 {
1064     JitSpewCont(JitSpew_CacheFlush, "[%p %" PRIxSIZE "]", start_addr, size);
1065     if (Simulator::ICacheCheckingEnabled) {
1066         Simulator* sim = Simulator::Current();
1067 
1068         AutoLockSimulatorCache als(sim);
1069 
1070         js::jit::FlushICacheLocked(sim->icache(), start_addr, size);
1071     }
1072 }
1073 
Simulator()1074 Simulator::Simulator()
1075 {
1076     // Set up simulator support first. Some of this information is needed to
1077     // setup the architecture state.
1078 
1079     // Note, allocation and anything that depends on allocated memory is
1080     // deferred until init(), in order to handle OOM properly.
1081 
1082     stack_ = nullptr;
1083     stackLimit_ = 0;
1084     pc_modified_ = false;
1085     icount_ = 0L;
1086     resume_pc_ = 0;
1087     break_pc_ = nullptr;
1088     break_instr_ = 0;
1089     single_stepping_ = false;
1090     single_step_callback_ = nullptr;
1091     single_step_callback_arg_ = nullptr;
1092     skipCalleeSavedRegsCheck = false;
1093 
1094     // Set up architecture state.
1095     // All registers are initialized to zero to start with.
1096     for (int i = 0; i < num_registers; i++)
1097         registers_[i] = 0;
1098 
1099     n_flag_ = false;
1100     z_flag_ = false;
1101     c_flag_ = false;
1102     v_flag_ = false;
1103 
1104     for (int i = 0; i < num_d_registers * 2; i++)
1105         vfp_registers_[i] = 0;
1106 
1107     n_flag_FPSCR_ = false;
1108     z_flag_FPSCR_ = false;
1109     c_flag_FPSCR_ = false;
1110     v_flag_FPSCR_ = false;
1111     FPSCR_rounding_mode_ = SimRZ;
1112     FPSCR_default_NaN_mode_ = true;
1113 
1114     inv_op_vfp_flag_ = false;
1115     div_zero_vfp_flag_ = false;
1116     overflow_vfp_flag_ = false;
1117     underflow_vfp_flag_ = false;
1118     inexact_vfp_flag_ = false;
1119 
1120     // The lr and pc are initialized to a known bad value that will cause an
1121     // access violation if the simulator ever tries to execute it.
1122     registers_[pc] = bad_lr;
1123     registers_[lr] = bad_lr;
1124 
1125     lastDebuggerInput_ = nullptr;
1126 
1127     cacheLock_ = nullptr;
1128 #ifdef DEBUG
1129     cacheLockHolder_ = nullptr;
1130 #endif
1131     redirection_ = nullptr;
1132     exclusiveMonitorHeld_ = false;
1133     exclusiveMonitor_ = 0;
1134 }
1135 
1136 bool
init()1137 Simulator::init()
1138 {
1139     cacheLock_ = PR_NewLock();
1140     if (!cacheLock_)
1141         return false;
1142 
1143     if (!icache_.init())
1144         return false;
1145 
1146     // Allocate 2MB for the stack. Note that we will only use 1MB, see below.
1147     static const size_t stackSize = 2 * 1024*1024;
1148     stack_ = reinterpret_cast<char*>(js_malloc(stackSize));
1149     if (!stack_)
1150         return false;
1151 
1152     // Leave a safety margin of 1MB to prevent overrunning the stack when
1153     // pushing values (total stack size is 2MB).
1154     stackLimit_ = reinterpret_cast<uintptr_t>(stack_) + 1024 * 1024;
1155 
1156     // The sp is initialized to point to the bottom (high address) of the
1157     // allocated stack area. To be safe in potential stack underflows we leave
1158     // some buffer below.
1159     registers_[sp] = reinterpret_cast<int32_t>(stack_) + stackSize - 64;
1160 
1161     return true;
1162 }
1163 
1164 // When the generated code calls a VM function (masm.callWithABI) we need to
1165 // call that function instead of trying to execute it with the simulator
1166 // (because it's x86 code instead of arm code). We do that by redirecting the VM
1167 // call to a svc (Supervisor Call) instruction that is handled by the
1168 // simulator. We write the original destination of the jump just at a known
1169 // offset from the svc instruction so the simulator knows what to call.
1170 class Redirection
1171 {
1172     friend class Simulator;
1173 
1174     // sim's lock must already be held.
Redirection(void * nativeFunction,ABIFunctionType type,Simulator * sim)1175     Redirection(void* nativeFunction, ABIFunctionType type, Simulator* sim)
1176       : nativeFunction_(nativeFunction),
1177         swiInstruction_(Assembler::AL | (0xf * (1 << 24)) | kCallRtRedirected),
1178         type_(type),
1179         next_(nullptr)
1180     {
1181         next_ = sim->redirection();
1182         if (Simulator::ICacheCheckingEnabled)
1183             FlushICacheLocked(sim->icache(), addressOfSwiInstruction(), SimInstruction::kInstrSize);
1184         sim->setRedirection(this);
1185     }
1186 
1187   public:
addressOfSwiInstruction()1188     void* addressOfSwiInstruction() { return &swiInstruction_; }
nativeFunction() const1189     void* nativeFunction() const { return nativeFunction_; }
type() const1190     ABIFunctionType type() const { return type_; }
1191 
Get(void * nativeFunction,ABIFunctionType type)1192     static Redirection* Get(void* nativeFunction, ABIFunctionType type) {
1193         Simulator* sim = Simulator::Current();
1194 
1195         AutoLockSimulatorCache als(sim);
1196 
1197         Redirection* current = sim->redirection();
1198         for (; current != nullptr; current = current->next_) {
1199             if (current->nativeFunction_ == nativeFunction) {
1200                 MOZ_ASSERT(current->type() == type);
1201                 return current;
1202             }
1203         }
1204 
1205         AutoEnterOOMUnsafeRegion oomUnsafe;
1206         Redirection* redir = (Redirection*)js_malloc(sizeof(Redirection));
1207         if (!redir)
1208             oomUnsafe.crash("Simulator redirection");
1209         new(redir) Redirection(nativeFunction, type, sim);
1210         return redir;
1211     }
1212 
FromSwiInstruction(SimInstruction * swiInstruction)1213     static Redirection* FromSwiInstruction(SimInstruction* swiInstruction) {
1214         uint8_t* addrOfSwi = reinterpret_cast<uint8_t*>(swiInstruction);
1215         uint8_t* addrOfRedirection = addrOfSwi - offsetof(Redirection, swiInstruction_);
1216         return reinterpret_cast<Redirection*>(addrOfRedirection);
1217     }
1218 
1219   private:
1220     void* nativeFunction_;
1221     uint32_t swiInstruction_;
1222     ABIFunctionType type_;
1223     Redirection* next_;
1224 };
1225 
~Simulator()1226 Simulator::~Simulator()
1227 {
1228     js_free(stack_);
1229     PR_DestroyLock(cacheLock_);
1230     Redirection* r = redirection_;
1231     while (r) {
1232         Redirection* next = r->next_;
1233         js_delete(r);
1234         r = next;
1235     }
1236 }
1237 
1238 /* static */ void*
RedirectNativeFunction(void * nativeFunction,ABIFunctionType type)1239 Simulator::RedirectNativeFunction(void* nativeFunction, ABIFunctionType type)
1240 {
1241     Redirection* redirection = Redirection::Get(nativeFunction, type);
1242     return redirection->addressOfSwiInstruction();
1243 }
1244 
1245 // Sets the register in the architecture state. It will also deal with updating
1246 // Simulator internal state for special registers such as PC.
1247 void
set_register(int reg,int32_t value)1248 Simulator::set_register(int reg, int32_t value)
1249 {
1250     MOZ_ASSERT(reg >= 0 && reg < num_registers);
1251     if (reg == pc)
1252         pc_modified_ = true;
1253     registers_[reg] = value;
1254 }
1255 
1256 // Get the register from the architecture state. This function does handle the
1257 // special case of accessing the PC register.
1258 int32_t
get_register(int reg) const1259 Simulator::get_register(int reg) const
1260 {
1261     MOZ_ASSERT(reg >= 0 && reg < num_registers);
1262     // Work around GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43949
1263     if (reg >= num_registers) return 0;
1264     return registers_[reg] + ((reg == pc) ? SimInstruction::kPCReadOffset : 0);
1265 }
1266 
1267 double
get_double_from_register_pair(int reg)1268 Simulator::get_double_from_register_pair(int reg)
1269 {
1270     MOZ_ASSERT(reg >= 0 && reg < num_registers && (reg % 2) == 0);
1271 
1272     // Read the bits from the unsigned integer register_[] array into the double
1273     // precision floating point value and return it.
1274     double dm_val = 0.0;
1275     char buffer[2 * sizeof(vfp_registers_[0])];
1276     memcpy(buffer, &registers_[reg], 2 * sizeof(registers_[0]));
1277     memcpy(&dm_val, buffer, 2 * sizeof(registers_[0]));
1278     return dm_val;
1279 }
1280 
1281 void
set_register_pair_from_double(int reg,double * value)1282 Simulator::set_register_pair_from_double(int reg, double* value)
1283 {
1284     MOZ_ASSERT(reg >= 0 && reg < num_registers && (reg % 2) == 0);
1285     memcpy(registers_ + reg, value, sizeof(*value));
1286 }
1287 
1288 void
set_dw_register(int dreg,const int * dbl)1289 Simulator::set_dw_register(int dreg, const int* dbl)
1290 {
1291     MOZ_ASSERT(dreg >= 0 && dreg < num_d_registers);
1292     registers_[dreg] = dbl[0];
1293     registers_[dreg + 1] = dbl[1];
1294 }
1295 
1296 void
get_d_register(int dreg,uint64_t * value)1297 Simulator::get_d_register(int dreg, uint64_t* value)
1298 {
1299     MOZ_ASSERT(dreg >= 0 && dreg < int(FloatRegisters::TotalPhys));
1300     memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value));
1301 }
1302 
1303 void
set_d_register(int dreg,const uint64_t * value)1304 Simulator::set_d_register(int dreg, const uint64_t* value)
1305 {
1306     MOZ_ASSERT(dreg >= 0 && dreg < int(FloatRegisters::TotalPhys));
1307     memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value));
1308 }
1309 
1310 void
get_d_register(int dreg,uint32_t * value)1311 Simulator::get_d_register(int dreg, uint32_t* value)
1312 {
1313     MOZ_ASSERT(dreg >= 0 && dreg < int(FloatRegisters::TotalPhys));
1314     memcpy(value, vfp_registers_ + dreg * 2, sizeof(*value) * 2);
1315 }
1316 
1317 void
set_d_register(int dreg,const uint32_t * value)1318 Simulator::set_d_register(int dreg, const uint32_t* value)
1319 {
1320     MOZ_ASSERT(dreg >= 0 && dreg < int(FloatRegisters::TotalPhys));
1321     memcpy(vfp_registers_ + dreg * 2, value, sizeof(*value) * 2);
1322 }
1323 
1324 void
get_q_register(int qreg,uint64_t * value)1325 Simulator::get_q_register(int qreg, uint64_t* value)
1326 {
1327     MOZ_ASSERT(qreg >= 0 && qreg < num_q_registers);
1328     memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 2);
1329 }
1330 
1331 void
set_q_register(int qreg,const uint64_t * value)1332 Simulator::set_q_register(int qreg, const uint64_t* value)
1333 {
1334     MOZ_ASSERT(qreg >= 0 && qreg < num_q_registers);
1335     memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 2);
1336 }
1337 
1338 void
get_q_register(int qreg,uint32_t * value)1339 Simulator::get_q_register(int qreg, uint32_t* value)
1340 {
1341     MOZ_ASSERT(qreg >= 0 && qreg < num_q_registers);
1342     memcpy(value, vfp_registers_ + qreg * 4, sizeof(*value) * 4);
1343 }
1344 
1345 void
set_q_register(int qreg,const uint32_t * value)1346 Simulator::set_q_register(int qreg, const uint32_t* value)
1347 {
1348     MOZ_ASSERT((qreg >= 0) && (qreg < num_q_registers));
1349     memcpy(vfp_registers_ + qreg * 4, value, sizeof(*value) * 4);
1350 }
1351 
1352 void
set_pc(int32_t value)1353 Simulator::set_pc(int32_t value)
1354 {
1355     pc_modified_ = true;
1356     registers_[pc] = value;
1357 }
1358 
1359 bool
has_bad_pc() const1360 Simulator::has_bad_pc() const
1361 {
1362     return registers_[pc] == bad_lr || registers_[pc] == end_sim_pc;
1363 }
1364 
1365 // Raw access to the PC register without the special adjustment when reading.
1366 int32_t
get_pc() const1367 Simulator::get_pc() const
1368 {
1369     return registers_[pc];
1370 }
1371 
1372 void
set_s_register(int sreg,unsigned int value)1373 Simulator::set_s_register(int sreg, unsigned int value)
1374 {
1375     MOZ_ASSERT(sreg >= 0 && sreg < num_s_registers);
1376     vfp_registers_[sreg] = value;
1377 }
1378 
1379 unsigned
get_s_register(int sreg) const1380 Simulator::get_s_register(int sreg) const
1381 {
1382     MOZ_ASSERT(sreg >= 0 && sreg < num_s_registers);
1383     return vfp_registers_[sreg];
1384 }
1385 
1386 template<class InputType, int register_size>
1387 void
setVFPRegister(int reg_index,const InputType & value)1388 Simulator::setVFPRegister(int reg_index, const InputType& value)
1389 {
1390     MOZ_ASSERT(reg_index >= 0);
1391     MOZ_ASSERT_IF(register_size == 1, reg_index < num_s_registers);
1392     MOZ_ASSERT_IF(register_size == 2, reg_index < int(FloatRegisters::TotalPhys));
1393 
1394     char buffer[register_size * sizeof(vfp_registers_[0])];
1395     memcpy(buffer, &value, register_size * sizeof(vfp_registers_[0]));
1396     memcpy(&vfp_registers_[reg_index * register_size], buffer,
1397            register_size * sizeof(vfp_registers_[0]));
1398 }
1399 
1400 template<class ReturnType, int register_size>
1401 ReturnType Simulator::getFromVFPRegister(int reg_index)
1402 {
1403     MOZ_ASSERT(reg_index >= 0);
1404     MOZ_ASSERT_IF(register_size == 1, reg_index < num_s_registers);
1405     MOZ_ASSERT_IF(register_size == 2, reg_index < int(FloatRegisters::TotalPhys));
1406 
1407     ReturnType value = 0;
1408     char buffer[register_size * sizeof(vfp_registers_[0])];
1409     memcpy(buffer, &vfp_registers_[register_size * reg_index],
1410            register_size * sizeof(vfp_registers_[0]));
1411     memcpy(&value, buffer, register_size * sizeof(vfp_registers_[0]));
1412     return value;
1413 }
1414 
1415 // These forced-instantiations are for jsapi-tests. Evidently, nothing
1416 // requires these to be instantiated.
1417 template double Simulator::getFromVFPRegister<double, 2>(int reg_index);
1418 template float Simulator::getFromVFPRegister<float, 1>(int reg_index);
1419 template void Simulator::setVFPRegister<double, 2>(int reg_index, const double& value);
1420 template void Simulator::setVFPRegister<float, 1>(int reg_index, const float& value);
1421 
1422 void
getFpArgs(double * x,double * y,int32_t * z)1423 Simulator::getFpArgs(double* x, double* y, int32_t* z)
1424 {
1425     if (UseHardFpABI()) {
1426         *x = get_double_from_d_register(0);
1427         *y = get_double_from_d_register(1);
1428         *z = get_register(0);
1429     } else {
1430         *x = get_double_from_register_pair(0);
1431         *y = get_double_from_register_pair(2);
1432         *z = get_register(2);
1433     }
1434 }
1435 
1436 void
getFpFromStack(int32_t * stack,double * x)1437 Simulator::getFpFromStack(int32_t* stack, double* x)
1438 {
1439     MOZ_ASSERT(stack && x);
1440     char buffer[2 * sizeof(stack[0])];
1441     memcpy(buffer, stack, 2 * sizeof(stack[0]));
1442     memcpy(x, buffer, 2 * sizeof(stack[0]));
1443 }
1444 
1445 void
setCallResultDouble(double result)1446 Simulator::setCallResultDouble(double result)
1447 {
1448     // The return value is either in r0/r1 or d0.
1449     if (UseHardFpABI()) {
1450         char buffer[2 * sizeof(vfp_registers_[0])];
1451         memcpy(buffer, &result, sizeof(buffer));
1452         // Copy result to d0.
1453         memcpy(vfp_registers_, buffer, sizeof(buffer));
1454     } else {
1455         char buffer[2 * sizeof(registers_[0])];
1456         memcpy(buffer, &result, sizeof(buffer));
1457         // Copy result to r0 and r1.
1458         memcpy(registers_, buffer, sizeof(buffer));
1459     }
1460 }
1461 
1462 void
setCallResultFloat(float result)1463 Simulator::setCallResultFloat(float result)
1464 {
1465     if (UseHardFpABI()) {
1466         char buffer[sizeof(registers_[0])];
1467         memcpy(buffer, &result, sizeof(buffer));
1468         // Copy result to s0.
1469         memcpy(vfp_registers_, buffer, sizeof(buffer));
1470     } else {
1471         char buffer[sizeof(registers_[0])];
1472         memcpy(buffer, &result, sizeof(buffer));
1473         // Copy result to r0.
1474         memcpy(registers_, buffer, sizeof(buffer));
1475     }
1476 }
1477 
1478 void
setCallResult(int64_t res)1479 Simulator::setCallResult(int64_t res)
1480 {
1481     set_register(r0, static_cast<int32_t>(res));
1482     set_register(r1, static_cast<int32_t>(res >> 32));
1483 }
1484 
1485 void
exclusiveMonitorSet(uint64_t value)1486 Simulator::exclusiveMonitorSet(uint64_t value)
1487 {
1488     exclusiveMonitor_ = value;
1489     exclusiveMonitorHeld_ = true;
1490 }
1491 
1492 uint64_t
exclusiveMonitorGetAndClear(bool * held)1493 Simulator::exclusiveMonitorGetAndClear(bool* held)
1494 {
1495     *held = exclusiveMonitorHeld_;
1496     exclusiveMonitorHeld_ = false;
1497     return *held ? exclusiveMonitor_ : 0;
1498 }
1499 
1500 void
exclusiveMonitorClear()1501 Simulator::exclusiveMonitorClear()
1502 {
1503     exclusiveMonitorHeld_ = false;
1504 }
1505 
1506 int
readW(int32_t addr,SimInstruction * instr)1507 Simulator::readW(int32_t addr, SimInstruction* instr)
1508 {
1509     // The regexp engine emits unaligned loads, so we don't check for them here
1510     // like most of the other methods do.
1511     if ((addr & 3) == 0 || !HasAlignmentFault()) {
1512         intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1513         return *ptr;
1514     } else {
1515         printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
1516         MOZ_CRASH();
1517     }
1518 }
1519 
1520 void
writeW(int32_t addr,int value,SimInstruction * instr)1521 Simulator::writeW(int32_t addr, int value, SimInstruction* instr)
1522 {
1523     if ((addr & 3) == 0) {
1524         intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
1525         *ptr = value;
1526     } else {
1527         printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
1528         MOZ_CRASH();
1529     }
1530 }
1531 
1532 // For the time being, define Relaxed operations in terms of SeqCst
1533 // operations - we don't yet need Relaxed operations anywhere else in
1534 // the system, and the distinction is not important to the simulation
1535 // at the level where we're operating.
1536 
1537 template<typename T>
1538 static
loadRelaxed(SharedMem<T * > addr)1539 T loadRelaxed(SharedMem<T*> addr)
1540 {
1541     return AtomicOperations::loadSeqCst(addr);
1542 }
1543 
1544 template<typename T>
1545 static
compareExchangeRelaxed(SharedMem<T * > addr,T oldval,T newval)1546 T compareExchangeRelaxed(SharedMem<T*> addr, T oldval, T newval)
1547 {
1548     return AtomicOperations::compareExchangeSeqCst(addr, oldval, newval);
1549 }
1550 
1551 int
readExW(int32_t addr,SimInstruction * instr)1552 Simulator::readExW(int32_t addr, SimInstruction* instr)
1553 {
1554     // The regexp engine emits unaligned loads, so we don't check for them here
1555     // like most of the other methods do.
1556     if ((addr & 3) == 0 || !HasAlignmentFault()) {
1557         SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
1558         int32_t value = loadRelaxed(ptr);
1559         exclusiveMonitorSet(value);
1560         return value;
1561     } else {
1562         printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
1563         MOZ_CRASH();
1564     }
1565 }
1566 
1567 int32_t
writeExW(int32_t addr,int value,SimInstruction * instr)1568 Simulator::writeExW(int32_t addr, int value, SimInstruction* instr)
1569 {
1570     if ((addr & 3) == 0) {
1571         SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
1572         bool held;
1573         int32_t expected = int32_t(exclusiveMonitorGetAndClear(&held));
1574         if (!held)
1575             return 1;
1576         int32_t old = compareExchangeRelaxed(ptr, expected, int32_t(value));
1577         return old != expected;
1578     } else {
1579         printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
1580         MOZ_CRASH();
1581     }
1582 }
1583 
1584 uint16_t
readHU(int32_t addr,SimInstruction * instr)1585 Simulator::readHU(int32_t addr, SimInstruction* instr)
1586 {
1587     // The regexp engine emits unaligned loads, so we don't check for them here
1588     // like most of the other methods do.
1589     if ((addr & 1) == 0 || !HasAlignmentFault()) {
1590         uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1591         return *ptr;
1592     }
1593     printf("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
1594     MOZ_CRASH();
1595     return 0;
1596 }
1597 
1598 int16_t
readH(int32_t addr,SimInstruction * instr)1599 Simulator::readH(int32_t addr, SimInstruction* instr)
1600 {
1601     if ((addr & 1) == 0) {
1602         int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1603         return *ptr;
1604     }
1605     printf("Unaligned signed halfword read at 0x%08x\n", addr);
1606     MOZ_CRASH();
1607     return 0;
1608 }
1609 
1610 void
writeH(int32_t addr,uint16_t value,SimInstruction * instr)1611 Simulator::writeH(int32_t addr, uint16_t value, SimInstruction* instr)
1612 {
1613     if ((addr & 1) == 0) {
1614         uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
1615         *ptr = value;
1616     } else {
1617         printf("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
1618         MOZ_CRASH();
1619     }
1620 }
1621 
1622 void
writeH(int32_t addr,int16_t value,SimInstruction * instr)1623 Simulator::writeH(int32_t addr, int16_t value, SimInstruction* instr)
1624 {
1625     if ((addr & 1) == 0) {
1626         int16_t* ptr = reinterpret_cast<int16_t*>(addr);
1627         *ptr = value;
1628     } else {
1629         printf("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
1630         MOZ_CRASH();
1631     }
1632 }
1633 
1634 uint16_t
readExHU(int32_t addr,SimInstruction * instr)1635 Simulator::readExHU(int32_t addr, SimInstruction* instr)
1636 {
1637     // The regexp engine emits unaligned loads, so we don't check for them here
1638     // like most of the other methods do.
1639     if ((addr & 1) == 0 || !HasAlignmentFault()) {
1640         SharedMem<uint16_t*> ptr = SharedMem<uint16_t*>::shared(reinterpret_cast<uint16_t*>(addr));
1641         uint16_t value = loadRelaxed(ptr);
1642         exclusiveMonitorSet(value);
1643         return value;
1644     }
1645     printf("Unaligned atomic unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
1646     MOZ_CRASH();
1647     return 0;
1648 }
1649 
1650 int32_t
writeExH(int32_t addr,uint16_t value,SimInstruction * instr)1651 Simulator::writeExH(int32_t addr, uint16_t value, SimInstruction* instr)
1652 {
1653     if ((addr & 1) == 0) {
1654         SharedMem<uint16_t*> ptr = SharedMem<uint16_t*>::shared(reinterpret_cast<uint16_t*>(addr));
1655         bool held;
1656         uint16_t expected = uint16_t(exclusiveMonitorGetAndClear(&held));
1657         if (!held)
1658             return 1;
1659         uint16_t old = compareExchangeRelaxed(ptr, expected, value);
1660         return old != expected;
1661     } else {
1662         printf("Unaligned atomic unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
1663         MOZ_CRASH();
1664     }
1665 }
1666 
1667 uint8_t
readBU(int32_t addr)1668 Simulator::readBU(int32_t addr)
1669 {
1670     uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1671     return *ptr;
1672 }
1673 
1674 uint8_t
readExBU(int32_t addr)1675 Simulator::readExBU(int32_t addr)
1676 {
1677     SharedMem<uint8_t*> ptr = SharedMem<uint8_t*>::shared(reinterpret_cast<uint8_t*>(addr));
1678     uint8_t value = loadRelaxed(ptr);
1679     exclusiveMonitorSet(value);
1680     return value;
1681 }
1682 
1683 int32_t
writeExB(int32_t addr,uint8_t value)1684 Simulator::writeExB(int32_t addr, uint8_t value)
1685 {
1686     SharedMem<uint8_t*> ptr = SharedMem<uint8_t*>::shared(reinterpret_cast<uint8_t*>(addr));
1687     bool held;
1688     uint8_t expected = uint8_t(exclusiveMonitorGetAndClear(&held));
1689     if (!held)
1690         return 1;
1691     uint8_t old = compareExchangeRelaxed(ptr, expected, value);
1692     return old != expected;
1693 }
1694 
1695 int8_t
readB(int32_t addr)1696 Simulator::readB(int32_t addr)
1697 {
1698     int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1699     return *ptr;
1700 }
1701 
1702 void
writeB(int32_t addr,uint8_t value)1703 Simulator::writeB(int32_t addr, uint8_t value)
1704 {
1705     uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
1706     *ptr = value;
1707 }
1708 
1709 void
writeB(int32_t addr,int8_t value)1710 Simulator::writeB(int32_t addr, int8_t value)
1711 {
1712     int8_t* ptr = reinterpret_cast<int8_t*>(addr);
1713     *ptr = value;
1714 }
1715 
1716 int32_t*
readDW(int32_t addr)1717 Simulator::readDW(int32_t addr)
1718 {
1719     if ((addr & 3) == 0) {
1720         int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1721         return ptr;
1722     }
1723     printf("Unaligned read at 0x%08x\n", addr);
1724     MOZ_CRASH();
1725     return 0;
1726 }
1727 
1728 void
writeDW(int32_t addr,int32_t value1,int32_t value2)1729 Simulator::writeDW(int32_t addr, int32_t value1, int32_t value2)
1730 {
1731     if ((addr & 3) == 0) {
1732         int32_t* ptr = reinterpret_cast<int32_t*>(addr);
1733         *ptr++ = value1;
1734         *ptr = value2;
1735     } else {
1736         printf("Unaligned write at 0x%08x\n", addr);
1737         MOZ_CRASH();
1738     }
1739 }
1740 
1741 int32_t
readExDW(int32_t addr,int32_t * hibits)1742 Simulator::readExDW(int32_t addr, int32_t* hibits)
1743 {
1744 #if defined(__clang__) && defined(__i386)
1745     // This is OK for now, we don't yet generate LDREXD.
1746     MOZ_CRASH("Unimplemented - 8-byte atomics are unsupported in Clang on i386");
1747 #else
1748     if ((addr & 3) == 0) {
1749         SharedMem<uint64_t*> ptr = SharedMem<uint64_t*>::shared(reinterpret_cast<uint64_t*>(addr));
1750         uint64_t value = loadRelaxed(ptr);
1751         exclusiveMonitorSet(value);
1752         *hibits = int32_t(value);
1753         return int32_t(value >> 32);
1754     }
1755     printf("Unaligned read at 0x%08x\n", addr);
1756     MOZ_CRASH();
1757     return 0;
1758 #endif
1759 }
1760 
1761 int32_t
writeExDW(int32_t addr,int32_t value1,int32_t value2)1762 Simulator::writeExDW(int32_t addr, int32_t value1, int32_t value2)
1763 {
1764 #if defined(__clang__) && defined(__i386)
1765     // This is OK for now, we don't yet generate STREXD.
1766     MOZ_CRASH("Unimplemented - 8-byte atomics are unsupported in Clang on i386");
1767 #else
1768     if ((addr & 3) == 0) {
1769         SharedMem<uint64_t*> ptr = SharedMem<uint64_t*>::shared(reinterpret_cast<uint64_t*>(addr));
1770         uint64_t value = (uint64_t(value1) << 32) | uint32_t(value2);
1771         bool held;
1772         uint64_t expected = exclusiveMonitorGetAndClear(&held);
1773         if (!held)
1774             return 1;
1775         uint64_t old = compareExchangeRelaxed(ptr, expected, value);
1776         return old != expected;
1777     } else {
1778         printf("Unaligned write at 0x%08x\n", addr);
1779         MOZ_CRASH();
1780     }
1781 #endif
1782 }
1783 
1784 uintptr_t
stackLimit() const1785 Simulator::stackLimit() const
1786 {
1787     return stackLimit_;
1788 }
1789 
1790 uintptr_t*
addressOfStackLimit()1791 Simulator::addressOfStackLimit()
1792 {
1793     return &stackLimit_;
1794 }
1795 
1796 bool
overRecursed(uintptr_t newsp) const1797 Simulator::overRecursed(uintptr_t newsp) const
1798 {
1799     if (newsp == 0)
1800         newsp = get_register(sp);
1801     return newsp <= stackLimit();
1802 }
1803 
1804 bool
overRecursedWithExtra(uint32_t extra) const1805 Simulator::overRecursedWithExtra(uint32_t extra) const
1806 {
1807     uintptr_t newsp = get_register(sp) - extra;
1808     return newsp <= stackLimit();
1809 }
1810 
1811 // Checks if the current instruction should be executed based on its condition
1812 // bits.
1813 bool
conditionallyExecute(SimInstruction * instr)1814 Simulator::conditionallyExecute(SimInstruction* instr)
1815 {
1816     switch (instr->conditionField()) {
1817       case Assembler::EQ: return z_flag_;
1818       case Assembler::NE: return !z_flag_;
1819       case Assembler::CS: return c_flag_;
1820       case Assembler::CC: return !c_flag_;
1821       case Assembler::MI: return n_flag_;
1822       case Assembler::PL: return !n_flag_;
1823       case Assembler::VS: return v_flag_;
1824       case Assembler::VC: return !v_flag_;
1825       case Assembler::HI: return c_flag_ && !z_flag_;
1826       case Assembler::LS: return !c_flag_ || z_flag_;
1827       case Assembler::GE: return n_flag_ == v_flag_;
1828       case Assembler::LT: return n_flag_ != v_flag_;
1829       case Assembler::GT: return !z_flag_ && (n_flag_ == v_flag_);
1830       case Assembler::LE: return z_flag_ || (n_flag_ != v_flag_);
1831       case Assembler::AL: return true;
1832       default: MOZ_CRASH();
1833     }
1834     return false;
1835 }
1836 
1837 // Calculate and set the Negative and Zero flags.
1838 void
setNZFlags(int32_t val)1839 Simulator::setNZFlags(int32_t val)
1840 {
1841     n_flag_ = (val < 0);
1842     z_flag_ = (val == 0);
1843 }
1844 
1845 // Set the Carry flag.
1846 void
setCFlag(bool val)1847 Simulator::setCFlag(bool val)
1848 {
1849     c_flag_ = val;
1850 }
1851 
1852 // Set the oVerflow flag.
1853 void
setVFlag(bool val)1854 Simulator::setVFlag(bool val)
1855 {
1856     v_flag_ = val;
1857 }
1858 
1859 // Calculate C flag value for additions.
1860 bool
carryFrom(int32_t left,int32_t right,int32_t carry)1861 Simulator::carryFrom(int32_t left, int32_t right, int32_t carry)
1862 {
1863     uint32_t uleft = static_cast<uint32_t>(left);
1864     uint32_t uright = static_cast<uint32_t>(right);
1865     uint32_t urest  = 0xffffffffU - uleft;
1866     return (uright > urest) ||
1867            (carry && (((uright + 1) > urest) || (uright > (urest - 1))));
1868 }
1869 
1870 // Calculate C flag value for subtractions.
1871 bool
borrowFrom(int32_t left,int32_t right)1872 Simulator::borrowFrom(int32_t left, int32_t right)
1873 {
1874     uint32_t uleft = static_cast<uint32_t>(left);
1875     uint32_t uright = static_cast<uint32_t>(right);
1876     return (uright > uleft);
1877 }
1878 
1879 // Calculate V flag value for additions and subtractions.
1880 bool
overflowFrom(int32_t alu_out,int32_t left,int32_t right,bool addition)1881 Simulator::overflowFrom(int32_t alu_out, int32_t left, int32_t right, bool addition)
1882 {
1883     bool overflow;
1884     if (addition) {
1885         // Operands have the same sign.
1886         overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1887             // And operands and result have different sign.
1888             && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1889     } else {
1890         // Operands have different signs.
1891         overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1892             // And first operand and result have different signs.
1893             && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1894     }
1895     return overflow;
1896 }
1897 
1898 // Support for VFP comparisons.
1899 void
compute_FPSCR_Flags(double val1,double val2)1900 Simulator::compute_FPSCR_Flags(double val1, double val2)
1901 {
1902     if (mozilla::IsNaN(val1) || mozilla::IsNaN(val2)) {
1903         n_flag_FPSCR_ = false;
1904         z_flag_FPSCR_ = false;
1905         c_flag_FPSCR_ = true;
1906         v_flag_FPSCR_ = true;
1907         // All non-NaN cases.
1908     } else if (val1 == val2) {
1909         n_flag_FPSCR_ = false;
1910         z_flag_FPSCR_ = true;
1911         c_flag_FPSCR_ = true;
1912         v_flag_FPSCR_ = false;
1913     } else if (val1 < val2) {
1914         n_flag_FPSCR_ = true;
1915         z_flag_FPSCR_ = false;
1916         c_flag_FPSCR_ = false;
1917         v_flag_FPSCR_ = false;
1918     } else {
1919         // Case when (val1 > val2).
1920         n_flag_FPSCR_ = false;
1921         z_flag_FPSCR_ = false;
1922         c_flag_FPSCR_ = true;
1923         v_flag_FPSCR_ = false;
1924     }
1925 }
1926 
1927 void
copy_FPSCR_to_APSR()1928 Simulator::copy_FPSCR_to_APSR()
1929 {
1930     n_flag_ = n_flag_FPSCR_;
1931     z_flag_ = z_flag_FPSCR_;
1932     c_flag_ = c_flag_FPSCR_;
1933     v_flag_ = v_flag_FPSCR_;
1934 }
1935 
1936 // Addressing Mode 1 - Data-processing operands:
1937 // Get the value based on the shifter_operand with register.
1938 int32_t
getShiftRm(SimInstruction * instr,bool * carry_out)1939 Simulator::getShiftRm(SimInstruction* instr, bool* carry_out)
1940 {
1941     ShiftType shift = instr->shifttypeValue();
1942     int shift_amount = instr->shiftAmountValue();
1943     int32_t result = get_register(instr->rmValue());
1944     if (instr->bit(4) == 0) {
1945         // By immediate.
1946         if (shift == ROR && shift_amount == 0) {
1947             MOZ_CRASH("NYI");
1948             return result;
1949         }
1950         if ((shift == LSR || shift == ASR) && shift_amount == 0)
1951             shift_amount = 32;
1952         switch (shift) {
1953           case ASR: {
1954             if (shift_amount == 0) {
1955                 if (result < 0) {
1956                     result = 0xffffffff;
1957                     *carry_out = true;
1958                 } else {
1959                     result = 0;
1960                     *carry_out = false;
1961                 }
1962             } else {
1963                 result >>= (shift_amount - 1);
1964                 *carry_out = (result & 1) == 1;
1965                 result >>= 1;
1966             }
1967             break;
1968           }
1969 
1970           case LSL: {
1971             if (shift_amount == 0) {
1972                 *carry_out = c_flag_;
1973             } else {
1974                 result <<= (shift_amount - 1);
1975                 *carry_out = (result < 0);
1976                 result <<= 1;
1977             }
1978             break;
1979           }
1980 
1981           case LSR: {
1982             if (shift_amount == 0) {
1983                 result = 0;
1984                 *carry_out = c_flag_;
1985             } else {
1986                 uint32_t uresult = static_cast<uint32_t>(result);
1987                 uresult >>= (shift_amount - 1);
1988                 *carry_out = (uresult & 1) == 1;
1989                 uresult >>= 1;
1990                 result = static_cast<int32_t>(uresult);
1991             }
1992             break;
1993           }
1994 
1995           case ROR: {
1996             if (shift_amount == 0) {
1997                 *carry_out = c_flag_;
1998             } else {
1999                 uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
2000                 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
2001                 result = right | left;
2002                 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
2003             }
2004             break;
2005           }
2006 
2007           default:
2008             MOZ_CRASH();
2009         }
2010     } else {
2011         // By register.
2012         int rs = instr->rsValue();
2013         shift_amount = get_register(rs) &0xff;
2014         switch (shift) {
2015           case ASR: {
2016             if (shift_amount == 0) {
2017                 *carry_out = c_flag_;
2018             } else if (shift_amount < 32) {
2019                 result >>= (shift_amount - 1);
2020                 *carry_out = (result & 1) == 1;
2021                 result >>= 1;
2022             } else {
2023                 MOZ_ASSERT(shift_amount >= 32);
2024                 if (result < 0) {
2025                     *carry_out = true;
2026                     result = 0xffffffff;
2027                 } else {
2028                     *carry_out = false;
2029                     result = 0;
2030                 }
2031             }
2032             break;
2033           }
2034 
2035           case LSL: {
2036             if (shift_amount == 0) {
2037                 *carry_out = c_flag_;
2038             } else if (shift_amount < 32) {
2039                 result <<= (shift_amount - 1);
2040                 *carry_out = (result < 0);
2041                 result <<= 1;
2042             } else if (shift_amount == 32) {
2043                 *carry_out = (result & 1) == 1;
2044                 result = 0;
2045             } else {
2046                 MOZ_ASSERT(shift_amount > 32);
2047                 *carry_out = false;
2048                 result = 0;
2049             }
2050             break;
2051           }
2052 
2053           case LSR: {
2054             if (shift_amount == 0) {
2055                 *carry_out = c_flag_;
2056             } else if (shift_amount < 32) {
2057                 uint32_t uresult = static_cast<uint32_t>(result);
2058                 uresult >>= (shift_amount - 1);
2059                 *carry_out = (uresult & 1) == 1;
2060                 uresult >>= 1;
2061                 result = static_cast<int32_t>(uresult);
2062             } else if (shift_amount == 32) {
2063                 *carry_out = (result < 0);
2064                 result = 0;
2065             } else {
2066                 *carry_out = false;
2067                 result = 0;
2068             }
2069             break;
2070           }
2071 
2072           case ROR: {
2073             if (shift_amount == 0) {
2074                 *carry_out = c_flag_;
2075             } else {
2076                 uint32_t left = static_cast<uint32_t>(result) >> shift_amount;
2077                 uint32_t right = static_cast<uint32_t>(result) << (32 - shift_amount);
2078                 result = right | left;
2079                 *carry_out = (static_cast<uint32_t>(result) >> 31) != 0;
2080             }
2081             break;
2082           }
2083 
2084           default:
2085             MOZ_CRASH();
2086         }
2087     }
2088     return result;
2089 }
2090 
2091 // Addressing Mode 1 - Data-processing operands:
2092 // Get the value based on the shifter_operand with immediate.
2093 int32_t
getImm(SimInstruction * instr,bool * carry_out)2094 Simulator::getImm(SimInstruction* instr, bool* carry_out)
2095 {
2096     int rotate = instr->rotateValue() * 2;
2097     int immed8 = instr->immed8Value();
2098     int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
2099     *carry_out = (rotate == 0) ? c_flag_ : (imm < 0);
2100     return imm;
2101 }
2102 
2103 int32_t
processPU(SimInstruction * instr,int num_regs,int reg_size,intptr_t * start_address,intptr_t * end_address)2104 Simulator::processPU(SimInstruction* instr, int num_regs, int reg_size,
2105                      intptr_t* start_address, intptr_t* end_address)
2106 {
2107     int rn = instr->rnValue();
2108     int32_t rn_val = get_register(rn);
2109     switch (instr->PUField()) {
2110       case da_x:
2111         MOZ_CRASH();
2112         break;
2113       case ia_x:
2114         *start_address = rn_val;
2115         *end_address = rn_val + (num_regs * reg_size) - reg_size;
2116         rn_val = rn_val + (num_regs * reg_size);
2117         break;
2118       case db_x:
2119         *start_address = rn_val - (num_regs * reg_size);
2120         *end_address = rn_val - reg_size;
2121         rn_val = *start_address;
2122         break;
2123       case ib_x:
2124         *start_address = rn_val + reg_size;
2125         *end_address = rn_val + (num_regs * reg_size);
2126         rn_val = *end_address;
2127         break;
2128       default:
2129         MOZ_CRASH();
2130     }
2131     return rn_val;
2132 }
2133 
2134 // Addressing Mode 4 - Load and Store Multiple
2135 void
handleRList(SimInstruction * instr,bool load)2136 Simulator::handleRList(SimInstruction* instr, bool load)
2137 {
2138     int rlist = instr->rlistValue();
2139     int num_regs = mozilla::CountPopulation32(rlist);
2140 
2141     intptr_t start_address = 0;
2142     intptr_t end_address = 0;
2143     int32_t rn_val = processPU(instr, num_regs, sizeof(void*), &start_address, &end_address);
2144     intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
2145 
2146     // Catch null pointers a little earlier.
2147     MOZ_ASSERT(start_address > 8191 || start_address < 0);
2148 
2149     int reg = 0;
2150     while (rlist != 0) {
2151         if ((rlist & 1) != 0) {
2152             if (load) {
2153                 set_register(reg, *address);
2154             } else {
2155                 *address = get_register(reg);
2156             }
2157             address += 1;
2158         }
2159         reg++;
2160         rlist >>= 1;
2161     }
2162     MOZ_ASSERT(end_address == ((intptr_t)address) - 4);
2163     if (instr->hasW())
2164         set_register(instr->rnValue(), rn_val);
2165 }
2166 
2167 // Addressing Mode 6 - Load and Store Multiple Coprocessor registers.
2168 void
handleVList(SimInstruction * instr)2169 Simulator::handleVList(SimInstruction* instr)
2170 {
2171     VFPRegPrecision precision = (instr->szValue() == 0) ? kSinglePrecision : kDoublePrecision;
2172     int operand_size = (precision == kSinglePrecision) ? 4 : 8;
2173     bool load = (instr->VLValue() == 0x1);
2174 
2175     int vd;
2176     int num_regs;
2177     vd = instr->VFPDRegValue(precision);
2178     if (precision == kSinglePrecision)
2179         num_regs = instr->immed8Value();
2180     else
2181         num_regs = instr->immed8Value() / 2;
2182 
2183     intptr_t start_address = 0;
2184     intptr_t end_address = 0;
2185     int32_t rn_val = processPU(instr, num_regs, operand_size, &start_address, &end_address);
2186 
2187     intptr_t* address = reinterpret_cast<intptr_t*>(start_address);
2188     for (int reg = vd; reg < vd + num_regs; reg++) {
2189         if (precision == kSinglePrecision) {
2190             if (load)
2191                 set_s_register_from_sinteger(reg, readW(reinterpret_cast<int32_t>(address), instr));
2192             else
2193                 writeW(reinterpret_cast<int32_t>(address), get_sinteger_from_s_register(reg), instr);
2194             address += 1;
2195         } else {
2196             if (load) {
2197                 int32_t data[] = {
2198                     readW(reinterpret_cast<int32_t>(address), instr),
2199                     readW(reinterpret_cast<int32_t>(address + 1), instr)
2200                 };
2201                 double d;
2202                 memcpy(&d, data, 8);
2203                 set_d_register_from_double(reg, d);
2204             } else {
2205                 int32_t data[2];
2206                 double d = get_double_from_d_register(reg);
2207                 memcpy(data, &d, 8);
2208                 writeW(reinterpret_cast<int32_t>(address), data[0], instr);
2209                 writeW(reinterpret_cast<int32_t>(address + 1), data[1], instr);
2210             }
2211             address += 2;
2212         }
2213     }
2214     MOZ_ASSERT(reinterpret_cast<intptr_t>(address) - operand_size == end_address);
2215     if (instr->hasW())
2216         set_register(instr->rnValue(), rn_val);
2217 }
2218 
2219 
2220 // Note: With the code below we assume that all runtime calls return a 64 bits
2221 // result. If they don't, the r1 result register contains a bogus value, which
2222 // is fine because it is caller-saved.
2223 typedef int64_t (*Prototype_General0)();
2224 typedef int64_t (*Prototype_General1)(int32_t arg0);
2225 typedef int64_t (*Prototype_General2)(int32_t arg0, int32_t arg1);
2226 typedef int64_t (*Prototype_General3)(int32_t arg0, int32_t arg1, int32_t arg2);
2227 typedef int64_t (*Prototype_General4)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3);
2228 typedef int64_t (*Prototype_General5)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
2229                                       int32_t arg4);
2230 typedef int64_t (*Prototype_General6)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
2231                                       int32_t arg4, int32_t arg5);
2232 typedef int64_t (*Prototype_General7)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
2233                                       int32_t arg4, int32_t arg5, int32_t arg6);
2234 typedef int64_t (*Prototype_General8)(int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3,
2235                                       int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7);
2236 
2237 typedef double (*Prototype_Double_None)();
2238 typedef double (*Prototype_Double_Double)(double arg0);
2239 typedef double (*Prototype_Double_Int)(int32_t arg0);
2240 typedef int32_t (*Prototype_Int_Double)(double arg0);
2241 typedef int32_t (*Prototype_Int_DoubleIntInt)(double arg0, int32_t arg1, int32_t arg2);
2242 typedef int32_t (*Prototype_Int_IntDoubleIntInt)(int32_t arg0, double arg1, int32_t arg2,
2243                                                  int32_t arg3);
2244 typedef float (*Prototype_Float32_Float32)(float arg0);
2245 
2246 typedef double (*Prototype_DoubleInt)(double arg0, int32_t arg1);
2247 typedef double (*Prototype_Double_IntDouble)(int32_t arg0, double arg1);
2248 typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
2249 typedef int32_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
2250 
2251 typedef double (*Prototype_Double_DoubleDoubleDouble)(double arg0, double arg1, double arg2);
2252 typedef double (*Prototype_Double_DoubleDoubleDoubleDouble)(double arg0, double arg1,
2253                                                             double arg2, double arg3);
2254 
2255 // Fill the volatile registers with scratch values.
2256 //
2257 // Some of the ABI calls assume that the float registers are not scratched, even
2258 // though the ABI defines them as volatile - a performance optimization. These
2259 // are all calls passing operands in integer registers, so for now the simulator
2260 // does not scratch any float registers for these calls. Should try to narrow it
2261 // further in future.
2262 //
2263 void
scratchVolatileRegisters(bool scratchFloat)2264 Simulator::scratchVolatileRegisters(bool scratchFloat)
2265 {
2266     int32_t scratch_value = 0xa5a5a5a5 ^ uint32_t(icount_);
2267     set_register(r0, scratch_value);
2268     set_register(r1, scratch_value);
2269     set_register(r2, scratch_value);
2270     set_register(r3, scratch_value);
2271     set_register(r12, scratch_value); // Intra-Procedure-call scratch register.
2272     set_register(r14, scratch_value); // Link register.
2273 
2274     if (scratchFloat) {
2275         uint64_t scratch_value_d = 0x5a5a5a5a5a5a5a5aLU ^ uint64_t(icount_) ^ (uint64_t(icount_) << 30);
2276         for (uint32_t i = d0; i < d8; i++)
2277             set_d_register(i, &scratch_value_d);
2278         for (uint32_t i = d16; i < FloatRegisters::TotalPhys; i++)
2279             set_d_register(i, &scratch_value_d);
2280     }
2281 }
2282 
2283 // Software interrupt instructions are used by the simulator to call into C++.
2284 void
softwareInterrupt(SimInstruction * instr)2285 Simulator::softwareInterrupt(SimInstruction* instr)
2286 {
2287     int svc = instr->svcValue();
2288     switch (svc) {
2289       case kCallRtRedirected: {
2290         Redirection* redirection = Redirection::FromSwiInstruction(instr);
2291         int32_t arg0 = get_register(r0);
2292         int32_t arg1 = get_register(r1);
2293         int32_t arg2 = get_register(r2);
2294         int32_t arg3 = get_register(r3);
2295         int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
2296         int32_t arg4 = stack_pointer[0];
2297         int32_t arg5 = stack_pointer[1];
2298 
2299         int32_t saved_lr = get_register(lr);
2300         intptr_t external = reinterpret_cast<intptr_t>(redirection->nativeFunction());
2301 
2302         bool stack_aligned = (get_register(sp) & (ABIStackAlignment - 1)) == 0;
2303         if (!stack_aligned) {
2304             fprintf(stderr, "Runtime call with unaligned stack!\n");
2305             MOZ_CRASH();
2306         }
2307 
2308         if (single_stepping_)
2309             single_step_callback_(single_step_callback_arg_, this, nullptr);
2310 
2311         switch (redirection->type()) {
2312           case Args_General0: {
2313             Prototype_General0 target = reinterpret_cast<Prototype_General0>(external);
2314             int64_t result = target();
2315             scratchVolatileRegisters(/* scratchFloat = true */);
2316             setCallResult(result);
2317             break;
2318           }
2319           case Args_General1: {
2320             Prototype_General1 target = reinterpret_cast<Prototype_General1>(external);
2321             int64_t result = target(arg0);
2322             scratchVolatileRegisters(/* scratchFloat = true */);
2323             setCallResult(result);
2324             break;
2325           }
2326           case Args_General2: {
2327             Prototype_General2 target = reinterpret_cast<Prototype_General2>(external);
2328             int64_t result = target(arg0, arg1);
2329             // The ARM backend makes calls to __aeabi_idivmod and
2330             // __aeabi_uidivmod assuming that the float registers are
2331             // non-volatile as a performance optimization, so the float
2332             // registers must not be scratch when calling these.
2333             bool scratchFloat = target != __aeabi_idivmod && target != __aeabi_uidivmod;
2334             scratchVolatileRegisters(/* scratchFloat = */ scratchFloat);
2335             setCallResult(result);
2336             break;
2337           }
2338           case Args_General3: {
2339             Prototype_General3 target = reinterpret_cast<Prototype_General3>(external);
2340             int64_t result = target(arg0, arg1, arg2);
2341             scratchVolatileRegisters(/* scratchFloat = true*/);
2342             setCallResult(result);
2343             break;
2344           }
2345           case Args_General4: {
2346             Prototype_General4 target = reinterpret_cast<Prototype_General4>(external);
2347             int64_t result = target(arg0, arg1, arg2, arg3);
2348             scratchVolatileRegisters(/* scratchFloat = true*/);
2349             setCallResult(result);
2350             break;
2351           }
2352           case Args_General5: {
2353             Prototype_General5 target = reinterpret_cast<Prototype_General5>(external);
2354             int64_t result = target(arg0, arg1, arg2, arg3, arg4);
2355             scratchVolatileRegisters(/* scratchFloat = true */);
2356             setCallResult(result);
2357             break;
2358           }
2359           case Args_General6: {
2360             Prototype_General6 target = reinterpret_cast<Prototype_General6>(external);
2361             int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
2362             scratchVolatileRegisters(/* scratchFloat = true */);
2363             setCallResult(result);
2364             break;
2365           }
2366           case Args_General7: {
2367             Prototype_General7 target = reinterpret_cast<Prototype_General7>(external);
2368             int32_t arg6 = stack_pointer[2];
2369             int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
2370             scratchVolatileRegisters(/* scratchFloat = true */);
2371             setCallResult(result);
2372             break;
2373           }
2374           case Args_General8: {
2375             Prototype_General8 target = reinterpret_cast<Prototype_General8>(external);
2376             int32_t arg6 = stack_pointer[2];
2377             int32_t arg7 = stack_pointer[3];
2378             int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
2379             scratchVolatileRegisters(/* scratchFloat = true */);
2380             setCallResult(result);
2381             break;
2382           }
2383           case Args_Double_None: {
2384             Prototype_Double_None target = reinterpret_cast<Prototype_Double_None>(external);
2385             double dresult = target();
2386             scratchVolatileRegisters(/* scratchFloat = true */);
2387             setCallResultDouble(dresult);
2388             break;
2389           }
2390           case Args_Int_Double: {
2391             double dval0, dval1;
2392             int32_t ival;
2393             getFpArgs(&dval0, &dval1, &ival);
2394             Prototype_Int_Double target = reinterpret_cast<Prototype_Int_Double>(external);
2395             int32_t res = target(dval0);
2396             scratchVolatileRegisters(/* scratchFloat = true */);
2397             set_register(r0, res);
2398             break;
2399           }
2400           case Args_Double_Double: {
2401             double dval0, dval1;
2402             int32_t ival;
2403             getFpArgs(&dval0, &dval1, &ival);
2404             Prototype_Double_Double target = reinterpret_cast<Prototype_Double_Double>(external);
2405             double dresult = target(dval0);
2406             scratchVolatileRegisters(/* scratchFloat = true */);
2407             setCallResultDouble(dresult);
2408             break;
2409           }
2410           case Args_Float32_Float32: {
2411             float fval0;
2412             if (UseHardFpABI())
2413                 fval0 = get_float_from_s_register(0);
2414             else
2415                 fval0 = mozilla::BitwiseCast<float>(arg0);
2416             Prototype_Float32_Float32 target = reinterpret_cast<Prototype_Float32_Float32>(external);
2417             float fresult = target(fval0);
2418             scratchVolatileRegisters(/* scratchFloat = true */);
2419             setCallResultFloat(fresult);
2420             break;
2421           }
2422           case Args_Double_Int: {
2423             Prototype_Double_Int target = reinterpret_cast<Prototype_Double_Int>(external);
2424             double dresult = target(arg0);
2425             scratchVolatileRegisters(/* scratchFloat = true */);
2426             setCallResultDouble(dresult);
2427             break;
2428           }
2429           case Args_Double_DoubleInt: {
2430             double dval0, dval1;
2431             int32_t ival;
2432             getFpArgs(&dval0, &dval1, &ival);
2433             Prototype_DoubleInt target = reinterpret_cast<Prototype_DoubleInt>(external);
2434             double dresult = target(dval0, ival);
2435             scratchVolatileRegisters(/* scratchFloat = true */);
2436             setCallResultDouble(dresult);
2437             break;
2438           }
2439           case Args_Double_DoubleDouble: {
2440             double dval0, dval1;
2441             int32_t ival;
2442             getFpArgs(&dval0, &dval1, &ival);
2443             Prototype_Double_DoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDouble>(external);
2444             double dresult = target(dval0, dval1);
2445             scratchVolatileRegisters(/* scratchFloat = true */);
2446             setCallResultDouble(dresult);
2447             break;
2448           }
2449           case Args_Double_IntDouble: {
2450             int32_t ival = get_register(0);
2451             double dval0;
2452             if (UseHardFpABI())
2453                 dval0 = get_double_from_d_register(0);
2454             else
2455                 dval0 = get_double_from_register_pair(2);
2456             Prototype_Double_IntDouble target = reinterpret_cast<Prototype_Double_IntDouble>(external);
2457             double dresult = target(ival, dval0);
2458             scratchVolatileRegisters(/* scratchFloat = true */);
2459             setCallResultDouble(dresult);
2460             break;
2461           }
2462           case Args_Int_IntDouble: {
2463             int32_t ival = get_register(0);
2464             double dval0;
2465             if (UseHardFpABI())
2466                 dval0 = get_double_from_d_register(0);
2467             else
2468                 dval0 = get_double_from_register_pair(2);
2469             Prototype_Int_IntDouble target = reinterpret_cast<Prototype_Int_IntDouble>(external);
2470             int32_t result = target(ival, dval0);
2471             scratchVolatileRegisters(/* scratchFloat = true */);
2472             set_register(r0, result);
2473             break;
2474           }
2475           case Args_Int_DoubleIntInt: {
2476             double dval;
2477             int32_t result;
2478             Prototype_Int_DoubleIntInt target = reinterpret_cast<Prototype_Int_DoubleIntInt>(external);
2479             if (UseHardFpABI()) {
2480                 dval = get_double_from_d_register(0);
2481                 result = target(dval, arg0, arg1);
2482             } else {
2483                 dval = get_double_from_register_pair(0);
2484                 result = target(dval, arg2, arg3);
2485             }
2486             scratchVolatileRegisters(/* scratchFloat = true */);
2487             set_register(r0, result);
2488             break;
2489           }
2490           case Args_Int_IntDoubleIntInt: {
2491             double dval;
2492             int32_t result;
2493             Prototype_Int_IntDoubleIntInt target = reinterpret_cast<Prototype_Int_IntDoubleIntInt>(external);
2494             if (UseHardFpABI()) {
2495                 dval = get_double_from_d_register(0);
2496                 result = target(arg0, dval, arg1, arg2);
2497             } else {
2498                 dval = get_double_from_register_pair(2);
2499                 result = target(arg0, dval, arg4, arg5);
2500             }
2501             scratchVolatileRegisters(/* scratchFloat = true */);
2502             set_register(r0, result);
2503             break;
2504           }
2505           case Args_Double_DoubleDoubleDouble: {
2506             double dval0, dval1, dval2;
2507             int32_t ival;
2508             getFpArgs(&dval0, &dval1, &ival);
2509             // the last argument is on stack
2510             getFpFromStack(stack_pointer, &dval2);
2511             Prototype_Double_DoubleDoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDoubleDouble>(external);
2512             double dresult = target(dval0, dval1, dval2);
2513             scratchVolatileRegisters(/* scratchFloat = true */);
2514             setCallResultDouble(dresult);
2515             break;
2516          }
2517          case Args_Double_DoubleDoubleDoubleDouble: {
2518             double dval0, dval1, dval2, dval3;
2519             int32_t ival;
2520             getFpArgs(&dval0, &dval1, &ival);
2521             // the two last arguments are on stack
2522             getFpFromStack(stack_pointer, &dval2);
2523             getFpFromStack(stack_pointer + 2, &dval3);
2524             Prototype_Double_DoubleDoubleDoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDoubleDoubleDouble>(external);
2525             double dresult = target(dval0, dval1, dval2, dval3);
2526             scratchVolatileRegisters(/* scratchFloat = true */);
2527             setCallResultDouble(dresult);
2528             break;
2529           }
2530           default:
2531             MOZ_CRASH("call");
2532         }
2533 
2534         if (single_stepping_)
2535             single_step_callback_(single_step_callback_arg_, this, nullptr);
2536 
2537         set_register(lr, saved_lr);
2538         set_pc(get_register(lr));
2539         break;
2540       }
2541       case kBreakpoint: {
2542         ArmDebugger dbg(this);
2543         dbg.debug();
2544         break;
2545       }
2546       default: { // Stop uses all codes greater than 1 << 23.
2547         if (svc >= (1 << 23)) {
2548             uint32_t code = svc & kStopCodeMask;
2549             if (isWatchedStop(code))
2550                 increaseStopCounter(code);
2551 
2552             // Stop if it is enabled, otherwise go on jumping over the stop and
2553             // the message address.
2554             if (isEnabledStop(code)) {
2555                 ArmDebugger dbg(this);
2556                 dbg.stop(instr);
2557             } else {
2558                 set_pc(get_pc() + 2 * SimInstruction::kInstrSize);
2559             }
2560         } else {
2561             // This is not a valid svc code.
2562             MOZ_CRASH();
2563             break;
2564         }
2565       }
2566     }
2567 }
2568 
2569 double
canonicalizeNaN(double value)2570 Simulator::canonicalizeNaN(double value)
2571 {
2572     return FPSCR_default_NaN_mode_ ? JS::CanonicalizeNaN(value) : value;
2573 }
2574 
2575 // Stop helper functions.
2576 bool
isStopInstruction(SimInstruction * instr)2577 Simulator::isStopInstruction(SimInstruction* instr)
2578 {
2579     return (instr->bits(27, 24) == 0xF) && (instr->svcValue() >= kStopCode);
2580 }
2581 
isWatchedStop(uint32_t code)2582 bool Simulator::isWatchedStop(uint32_t code)
2583 {
2584     MOZ_ASSERT(code <= kMaxStopCode);
2585     return code < kNumOfWatchedStops;
2586 }
2587 
2588 bool
isEnabledStop(uint32_t code)2589 Simulator::isEnabledStop(uint32_t code)
2590 {
2591     MOZ_ASSERT(code <= kMaxStopCode);
2592     // Unwatched stops are always enabled.
2593     return !isWatchedStop(code) || !(watched_stops_[code].count & kStopDisabledBit);
2594 }
2595 
2596 void
enableStop(uint32_t code)2597 Simulator::enableStop(uint32_t code)
2598 {
2599     MOZ_ASSERT(isWatchedStop(code));
2600     if (!isEnabledStop(code))
2601         watched_stops_[code].count &= ~kStopDisabledBit;
2602 }
2603 
2604 void
disableStop(uint32_t code)2605 Simulator::disableStop(uint32_t code)
2606 {
2607     MOZ_ASSERT(isWatchedStop(code));
2608     if (isEnabledStop(code))
2609         watched_stops_[code].count |= kStopDisabledBit;
2610 }
2611 
2612 void
increaseStopCounter(uint32_t code)2613 Simulator::increaseStopCounter(uint32_t code)
2614 {
2615     MOZ_ASSERT(code <= kMaxStopCode);
2616     MOZ_ASSERT(isWatchedStop(code));
2617     if ((watched_stops_[code].count & ~(1 << 31)) == 0x7fffffff) {
2618         printf("Stop counter for code %i has overflowed.\n"
2619                "Enabling this code and reseting the counter to 0.\n", code);
2620         watched_stops_[code].count = 0;
2621         enableStop(code);
2622     } else {
2623         watched_stops_[code].count++;
2624     }
2625 }
2626 
2627 // Print a stop status.
2628 void
printStopInfo(uint32_t code)2629 Simulator::printStopInfo(uint32_t code)
2630 {
2631     MOZ_ASSERT(code <= kMaxStopCode);
2632     if (!isWatchedStop(code)) {
2633         printf("Stop not watched.");
2634     } else {
2635         const char* state = isEnabledStop(code) ? "Enabled" : "Disabled";
2636         int32_t count = watched_stops_[code].count & ~kStopDisabledBit;
2637         // Don't print the state of unused breakpoints.
2638         if (count != 0) {
2639             if (watched_stops_[code].desc) {
2640                 printf("stop %i - 0x%x: \t%s, \tcounter = %i, \t%s\n",
2641                        code, code, state, count, watched_stops_[code].desc);
2642             } else {
2643                 printf("stop %i - 0x%x: \t%s, \tcounter = %i\n",
2644                        code, code, state, count);
2645             }
2646         }
2647     }
2648 }
2649 
2650 // Instruction types 0 and 1 are both rolled into one function because they only
2651 // differ in the handling of the shifter_operand.
2652 void
decodeType01(SimInstruction * instr)2653 Simulator::decodeType01(SimInstruction* instr)
2654 {
2655     int type = instr->typeValue();
2656     if (type == 0 && instr->isSpecialType0()) {
2657         // Multiply instruction or extra loads and stores.
2658         if (instr->bits(7, 4) == 9) {
2659             if (instr->bit(24) == 0) {
2660                 // Raw field decoding here. Multiply instructions have their Rd
2661                 // in funny places.
2662                 int rn = instr->rnValue();
2663                 int rm = instr->rmValue();
2664                 int rs = instr->rsValue();
2665                 int32_t rs_val = get_register(rs);
2666                 int32_t rm_val = get_register(rm);
2667                 if (instr->bit(23) == 0) {
2668                     if (instr->bit(21) == 0) {
2669                         // The MUL instruction description (A 4.1.33) refers to
2670                         // Rd as being the destination for the operation, but it
2671                         // confusingly uses the Rn field to encode it.
2672                         int rd = rn;  // Remap the rn field to the Rd register.
2673                         int32_t alu_out = rm_val * rs_val;
2674                         set_register(rd, alu_out);
2675                         if (instr->hasS())
2676                             setNZFlags(alu_out);
2677                     } else {
2678                         int rd = instr->rdValue();
2679                         int32_t acc_value = get_register(rd);
2680                         if (instr->bit(22) == 0) {
2681                             // The MLA instruction description (A 4.1.28) refers
2682                             // to the order of registers as "Rd, Rm, Rs,
2683                             // Rn". But confusingly it uses the Rn field to
2684                             // encode the Rd register and the Rd field to encode
2685                             // the Rn register.
2686                             int32_t mul_out = rm_val * rs_val;
2687                             int32_t result = acc_value + mul_out;
2688                             set_register(rn, result);
2689                         } else {
2690                             int32_t mul_out = rm_val * rs_val;
2691                             int32_t result = acc_value - mul_out;
2692                             set_register(rn, result);
2693                         }
2694                     }
2695                 } else {
2696                     // The signed/long multiply instructions use the terms RdHi
2697                     // and RdLo when referring to the target registers. They are
2698                     // mapped to the Rn and Rd fields as follows:
2699                     // RdLo == Rd
2700                     // RdHi == Rn (This is confusingly stored in variable rd here
2701                     //             because the mul instruction from above uses the
2702                     //             Rn field to encode the Rd register. Good luck figuring
2703                     //             this out without reading the ARM instruction manual
2704                     //             at a very detailed level.)
2705                     int rd_hi = rn;  // Remap the rn field to the RdHi register.
2706                     int rd_lo = instr->rdValue();
2707                     int32_t hi_res = 0;
2708                     int32_t lo_res = 0;
2709                     if (instr->bit(22) == 1) {
2710                         int64_t left_op  = static_cast<int32_t>(rm_val);
2711                         int64_t right_op = static_cast<int32_t>(rs_val);
2712                         uint64_t result = left_op * right_op;
2713                         hi_res = static_cast<int32_t>(result >> 32);
2714                         lo_res = static_cast<int32_t>(result & 0xffffffff);
2715                     } else {
2716                         // Unsigned multiply.
2717                         uint64_t left_op  = static_cast<uint32_t>(rm_val);
2718                         uint64_t right_op = static_cast<uint32_t>(rs_val);
2719                         uint64_t result = left_op * right_op;
2720                         hi_res = static_cast<int32_t>(result >> 32);
2721                         lo_res = static_cast<int32_t>(result & 0xffffffff);
2722                     }
2723                     set_register(rd_lo, lo_res);
2724                     set_register(rd_hi, hi_res);
2725                     if (instr->hasS())
2726                         MOZ_CRASH();
2727                 }
2728             } else {
2729                 if (instr->bits(disasm::ExclusiveOpHi, disasm::ExclusiveOpLo) == disasm::ExclusiveOpcode) {
2730                     // Load-exclusive / store-exclusive.
2731                     if (instr->bit(disasm::ExclusiveLoad)) {
2732                         int rn = instr->rnValue();
2733                         int rt = instr->rtValue();
2734                         int32_t address = get_register(rn);
2735                         switch (instr->bits(disasm::ExclusiveSizeHi, disasm::ExclusiveSizeLo)) {
2736                           case disasm::ExclusiveWord:
2737                             set_register(rt, readExW(address, instr));
2738                             break;
2739                           case disasm::ExclusiveDouble: {
2740                             MOZ_ASSERT((rt % 2) == 0);
2741                             int32_t hibits;
2742                             int32_t lobits = readExDW(address, &hibits);
2743                             set_register(rt, lobits);
2744                             set_register(rt+1, hibits);
2745                             break;
2746                           }
2747                           case disasm::ExclusiveByte:
2748                             set_register(rt, readExBU(address));
2749                             break;
2750                           case disasm::ExclusiveHalf:
2751                             set_register(rt, readExHU(address, instr));
2752                             break;
2753                         }
2754                     } else {
2755                         int rn = instr->rnValue();
2756                         int rd = instr->rdValue();
2757                         int rt = instr->bits(3,0);
2758                         int32_t address = get_register(rn);
2759                         int32_t value = get_register(rt);
2760                         int32_t result = 0;
2761                         switch (instr->bits(disasm::ExclusiveSizeHi, disasm::ExclusiveSizeLo)) {
2762                           case disasm::ExclusiveWord:
2763                             result = writeExW(address, value, instr);
2764                             break;
2765                           case disasm::ExclusiveDouble: {
2766                             MOZ_ASSERT((rt % 2) == 0);
2767                             int32_t value2 = get_register(rt+1);
2768                             result = writeExDW(address, value, value2);
2769                             break;
2770                           }
2771                           case disasm::ExclusiveByte:
2772                             result = writeExB(address, (uint8_t)value);
2773                             break;
2774                           case disasm::ExclusiveHalf:
2775                             result = writeExH(address, (uint16_t)value, instr);
2776                             break;
2777                         }
2778                         set_register(rd, result);
2779                     }
2780                 } else {
2781                     MOZ_CRASH(); // Not used atm
2782                 }
2783             }
2784         } else {
2785             // Extra load/store instructions.
2786             int rd = instr->rdValue();
2787             int rn = instr->rnValue();
2788             int32_t rn_val = get_register(rn);
2789             int32_t addr = 0;
2790             if (instr->bit(22) == 0) {
2791                 int rm = instr->rmValue();
2792                 int32_t rm_val = get_register(rm);
2793                 switch (instr->PUField()) {
2794                   case da_x:
2795                     MOZ_ASSERT(!instr->hasW());
2796                     addr = rn_val;
2797                     rn_val -= rm_val;
2798                     set_register(rn, rn_val);
2799                     break;
2800                   case ia_x:
2801                     MOZ_ASSERT(!instr->hasW());
2802                     addr = rn_val;
2803                     rn_val += rm_val;
2804                     set_register(rn, rn_val);
2805                     break;
2806                   case db_x:
2807                     rn_val -= rm_val;
2808                     addr = rn_val;
2809                     if (instr->hasW())
2810                         set_register(rn, rn_val);
2811                     break;
2812                   case ib_x:
2813                     rn_val += rm_val;
2814                     addr = rn_val;
2815                     if (instr->hasW())
2816                         set_register(rn, rn_val);
2817                     break;
2818                   default:
2819                     // The PU field is a 2-bit field.
2820                     MOZ_CRASH();
2821                     break;
2822                 }
2823             } else {
2824                 int32_t imm_val = (instr->immedHValue() << 4) | instr->immedLValue();
2825                 switch (instr->PUField()) {
2826                   case da_x:
2827                     MOZ_ASSERT(!instr->hasW());
2828                     addr = rn_val;
2829                     rn_val -= imm_val;
2830                     set_register(rn, rn_val);
2831                     break;
2832                   case ia_x:
2833                     MOZ_ASSERT(!instr->hasW());
2834                     addr = rn_val;
2835                     rn_val += imm_val;
2836                     set_register(rn, rn_val);
2837                     break;
2838                   case db_x:
2839                     rn_val -= imm_val;
2840                     addr = rn_val;
2841                     if (instr->hasW())
2842                         set_register(rn, rn_val);
2843                     break;
2844                   case ib_x:
2845                     rn_val += imm_val;
2846                     addr = rn_val;
2847                     if (instr->hasW())
2848                         set_register(rn, rn_val);
2849                     break;
2850                   default:
2851                     // The PU field is a 2-bit field.
2852                     MOZ_CRASH();
2853                     break;
2854                 }
2855             }
2856             if ((instr->bits(7, 4) & 0xd) == 0xd && instr->bit(20) == 0) {
2857                 MOZ_ASSERT((rd % 2) == 0);
2858                 if (instr->hasH()) {
2859                     // The strd instruction.
2860                     int32_t value1 = get_register(rd);
2861                     int32_t value2 = get_register(rd+1);
2862                     writeDW(addr, value1, value2);
2863                 } else {
2864                     // The ldrd instruction.
2865                     int* rn_data = readDW(addr);
2866                     set_dw_register(rd, rn_data);
2867                 }
2868             } else if (instr->hasH()) {
2869                 if (instr->hasSign()) {
2870                     if (instr->hasL()) {
2871                         int16_t val = readH(addr, instr);
2872                         set_register(rd, val);
2873                     } else {
2874                         int16_t val = get_register(rd);
2875                         writeH(addr, val, instr);
2876                     }
2877                 } else {
2878                     if (instr->hasL()) {
2879                         uint16_t val = readHU(addr, instr);
2880                         set_register(rd, val);
2881                     } else {
2882                         uint16_t val = get_register(rd);
2883                         writeH(addr, val, instr);
2884                     }
2885                 }
2886             } else {
2887                 // Signed byte loads.
2888                 MOZ_ASSERT(instr->hasSign());
2889                 MOZ_ASSERT(instr->hasL());
2890                 int8_t val = readB(addr);
2891                 set_register(rd, val);
2892             }
2893             return;
2894         }
2895     } else if ((type == 0) && instr->isMiscType0()) {
2896         if (instr->bits(7, 4) == 0) {
2897             if (instr->bit(21) == 0) {
2898                 // mrs
2899                 int rd = instr->rdValue();
2900                 uint32_t flags;
2901                 if (instr->bit(22) == 0) {
2902                     // CPSR. Note: The Q flag is not yet implemented!
2903                     flags = (n_flag_ << 31) |
2904                         (z_flag_ << 30) |
2905                         (c_flag_ << 29) |
2906                         (v_flag_ << 28);
2907                 } else {
2908                     // SPSR
2909                     MOZ_CRASH();
2910                 }
2911                 set_register(rd, flags);
2912             } else {
2913                 // msr
2914                 if (instr->bits(27, 23) == 2) {
2915                     // Register operand. For now we only emit mask 0b1100.
2916                     int rm = instr->rmValue();
2917                     mozilla::DebugOnly<uint32_t> mask = instr->bits(19, 16);
2918                     MOZ_ASSERT(mask == (3 << 2));
2919 
2920                     uint32_t flags = get_register(rm);
2921                     n_flag_ = (flags >> 31) & 1;
2922                     z_flag_ = (flags >> 30) & 1;
2923                     c_flag_ = (flags >> 29) & 1;
2924                     v_flag_ = (flags >> 28) & 1;
2925                 } else {
2926                     MOZ_CRASH();
2927                 }
2928             }
2929         } else if (instr->bits(22, 21) == 1) {
2930             int rm = instr->rmValue();
2931             switch (instr->bits(7, 4)) {
2932               case 1:   // BX
2933                 set_pc(get_register(rm));
2934                 break;
2935               case 3: { // BLX
2936                 uint32_t old_pc = get_pc();
2937                 set_pc(get_register(rm));
2938                 set_register(lr, old_pc + SimInstruction::kInstrSize);
2939                 break;
2940               }
2941               case 7: { // BKPT
2942                 fprintf(stderr, "Simulator hit BKPT.\n");
2943                 if (getenv("ARM_SIM_DEBUGGER")) {
2944                     ArmDebugger dbg(this);
2945                     dbg.debug();
2946                 } else {
2947                     fprintf(stderr, "Use ARM_SIM_DEBUGGER=1 to enter the builtin debugger.\n");
2948                     MOZ_CRASH("ARM simulator breakpoint");
2949                 }
2950                 break;
2951               }
2952               default:
2953                 MOZ_CRASH();
2954             }
2955         } else if (instr->bits(22, 21) == 3) {
2956             int rm = instr->rmValue();
2957             int rd = instr->rdValue();
2958             switch (instr->bits(7, 4)) {
2959               case 1: { // CLZ
2960                 uint32_t bits = get_register(rm);
2961                 int leading_zeros = 0;
2962                 if (bits == 0)
2963                     leading_zeros = 32;
2964                 else
2965                     leading_zeros = mozilla::CountLeadingZeroes32(bits);
2966                 set_register(rd, leading_zeros);
2967                 break;
2968               }
2969               default:
2970                 MOZ_CRASH();
2971                 break;
2972             }
2973         } else {
2974             printf("%08x\n", instr->instructionBits());
2975             MOZ_CRASH();
2976         }
2977     } else if ((type == 1) && instr->isNopType1()) {
2978         // NOP.
2979     } else {
2980         int rd = instr->rdValue();
2981         int rn = instr->rnValue();
2982         int32_t rn_val = get_register(rn);
2983         int32_t shifter_operand = 0;
2984         bool shifter_carry_out = 0;
2985         if (type == 0) {
2986             shifter_operand = getShiftRm(instr, &shifter_carry_out);
2987         } else {
2988             MOZ_ASSERT(instr->typeValue() == 1);
2989             shifter_operand = getImm(instr, &shifter_carry_out);
2990         }
2991         int32_t alu_out;
2992         switch (instr->opcodeField()) {
2993           case OpAnd:
2994             alu_out = rn_val & shifter_operand;
2995             set_register(rd, alu_out);
2996             if (instr->hasS()) {
2997                 setNZFlags(alu_out);
2998                 setCFlag(shifter_carry_out);
2999             }
3000             break;
3001           case OpEor:
3002             alu_out = rn_val ^ shifter_operand;
3003             set_register(rd, alu_out);
3004             if (instr->hasS()) {
3005                 setNZFlags(alu_out);
3006                 setCFlag(shifter_carry_out);
3007             }
3008             break;
3009           case OpSub:
3010             alu_out = rn_val - shifter_operand;
3011             set_register(rd, alu_out);
3012             if (instr->hasS()) {
3013                 setNZFlags(alu_out);
3014                 setCFlag(!borrowFrom(rn_val, shifter_operand));
3015                 setVFlag(overflowFrom(alu_out, rn_val, shifter_operand, false));
3016             }
3017             break;
3018           case OpRsb:
3019             alu_out = shifter_operand - rn_val;
3020             set_register(rd, alu_out);
3021             if (instr->hasS()) {
3022                 setNZFlags(alu_out);
3023                 setCFlag(!borrowFrom(shifter_operand, rn_val));
3024                 setVFlag(overflowFrom(alu_out, shifter_operand, rn_val, false));
3025             }
3026             break;
3027           case OpAdd:
3028             alu_out = rn_val + shifter_operand;
3029             set_register(rd, alu_out);
3030             if (instr->hasS()) {
3031                 setNZFlags(alu_out);
3032                 setCFlag(carryFrom(rn_val, shifter_operand));
3033                 setVFlag(overflowFrom(alu_out, rn_val, shifter_operand, true));
3034             }
3035             break;
3036           case OpAdc:
3037             alu_out = rn_val + shifter_operand + getCarry();
3038             set_register(rd, alu_out);
3039             if (instr->hasS()) {
3040                 setNZFlags(alu_out);
3041                 setCFlag(carryFrom(rn_val, shifter_operand, getCarry()));
3042                 setVFlag(overflowFrom(alu_out, rn_val, shifter_operand, true));
3043             }
3044             break;
3045           case OpSbc:
3046           case OpRsc:
3047             MOZ_CRASH();
3048             break;
3049           case OpTst:
3050             if (instr->hasS()) {
3051                 alu_out = rn_val & shifter_operand;
3052                 setNZFlags(alu_out);
3053                 setCFlag(shifter_carry_out);
3054             } else {
3055                 alu_out = instr->immedMovwMovtValue();
3056                 set_register(rd, alu_out);
3057             }
3058             break;
3059           case OpTeq:
3060             if (instr->hasS()) {
3061                 alu_out = rn_val ^ shifter_operand;
3062                 setNZFlags(alu_out);
3063                 setCFlag(shifter_carry_out);
3064             } else {
3065                 // Other instructions matching this pattern are handled in the
3066                 // miscellaneous instructions part above.
3067                 MOZ_CRASH();
3068             }
3069             break;
3070           case OpCmp:
3071             if (instr->hasS()) {
3072                 alu_out = rn_val - shifter_operand;
3073                 setNZFlags(alu_out);
3074                 setCFlag(!borrowFrom(rn_val, shifter_operand));
3075                 setVFlag(overflowFrom(alu_out, rn_val, shifter_operand, false));
3076             } else {
3077                 alu_out = (get_register(rd) & 0xffff) |
3078                     (instr->immedMovwMovtValue() << 16);
3079                 set_register(rd, alu_out);
3080             }
3081             break;
3082           case OpCmn:
3083             if (instr->hasS()) {
3084                 alu_out = rn_val + shifter_operand;
3085                 setNZFlags(alu_out);
3086                 setCFlag(carryFrom(rn_val, shifter_operand));
3087                 setVFlag(overflowFrom(alu_out, rn_val, shifter_operand, true));
3088             } else {
3089                 // Other instructions matching this pattern are handled in the
3090                 // miscellaneous instructions part above.
3091                 MOZ_CRASH();
3092             }
3093             break;
3094           case OpOrr:
3095             alu_out = rn_val | shifter_operand;
3096             set_register(rd, alu_out);
3097             if (instr->hasS()) {
3098                 setNZFlags(alu_out);
3099                 setCFlag(shifter_carry_out);
3100             }
3101             break;
3102           case OpMov:
3103             alu_out = shifter_operand;
3104             set_register(rd, alu_out);
3105             if (instr->hasS()) {
3106                 setNZFlags(alu_out);
3107                 setCFlag(shifter_carry_out);
3108             }
3109             break;
3110           case OpBic:
3111             alu_out = rn_val & ~shifter_operand;
3112             set_register(rd, alu_out);
3113             if (instr->hasS()) {
3114                 setNZFlags(alu_out);
3115                 setCFlag(shifter_carry_out);
3116             }
3117             break;
3118           case OpMvn:
3119             alu_out = ~shifter_operand;
3120             set_register(rd, alu_out);
3121             if (instr->hasS()) {
3122                 setNZFlags(alu_out);
3123                 setCFlag(shifter_carry_out);
3124             }
3125             break;
3126           default:
3127             MOZ_CRASH();
3128             break;
3129         }
3130     }
3131 }
3132 
3133 void
decodeType2(SimInstruction * instr)3134 Simulator::decodeType2(SimInstruction* instr)
3135 {
3136     int rd = instr->rdValue();
3137     int rn = instr->rnValue();
3138     int32_t rn_val = get_register(rn);
3139     int32_t im_val = instr->offset12Value();
3140     int32_t addr = 0;
3141     switch (instr->PUField()) {
3142       case da_x:
3143         MOZ_ASSERT(!instr->hasW());
3144         addr = rn_val;
3145         rn_val -= im_val;
3146         set_register(rn, rn_val);
3147         break;
3148       case ia_x:
3149         MOZ_ASSERT(!instr->hasW());
3150         addr = rn_val;
3151         rn_val += im_val;
3152         set_register(rn, rn_val);
3153         break;
3154       case db_x:
3155         rn_val -= im_val;
3156         addr = rn_val;
3157         if (instr->hasW())
3158             set_register(rn, rn_val);
3159         break;
3160       case ib_x:
3161         rn_val += im_val;
3162         addr = rn_val;
3163         if (instr->hasW())
3164             set_register(rn, rn_val);
3165         break;
3166       default:
3167         MOZ_CRASH();
3168         break;
3169     }
3170     if (instr->hasB()) {
3171         if (instr->hasL()) {
3172             uint8_t val = readBU(addr);
3173             set_register(rd, val);
3174         } else {
3175             uint8_t val = get_register(rd);
3176             writeB(addr, val);
3177         }
3178     } else {
3179         if (instr->hasL())
3180             set_register(rd, readW(addr, instr));
3181         else
3182             writeW(addr, get_register(rd), instr);
3183     }
3184 }
3185 
3186 static uint32_t
rotateBytes(uint32_t val,int32_t rotate)3187 rotateBytes(uint32_t val, int32_t rotate)
3188 {
3189     switch (rotate) {
3190       default:
3191         return val;
3192       case 1:
3193         return (val >> 8) | (val << 24);
3194       case 2:
3195         return (val >> 16) | (val << 16);
3196       case 3:
3197         return (val >> 24) | (val << 8);
3198     }
3199 }
3200 
3201 void
decodeType3(SimInstruction * instr)3202 Simulator::decodeType3(SimInstruction* instr)
3203 {
3204     int rd = instr->rdValue();
3205     int rn = instr->rnValue();
3206     int32_t rn_val = get_register(rn);
3207     bool shifter_carry_out = 0;
3208     int32_t shifter_operand = getShiftRm(instr, &shifter_carry_out);
3209     int32_t addr = 0;
3210     switch (instr->PUField()) {
3211       case da_x:
3212         MOZ_ASSERT(!instr->hasW());
3213         MOZ_CRASH();
3214         break;
3215       case ia_x: {
3216         if (instr->bit(4) == 0) {
3217             // Memop.
3218         } else {
3219             if (instr->bit(5) == 0) {
3220                 switch (instr->bits(22, 21)) {
3221                   case 0:
3222                     if (instr->bit(20) == 0) {
3223                         if (instr->bit(6) == 0) {
3224                             // Pkhbt.
3225                             uint32_t rn_val = get_register(rn);
3226                             uint32_t rm_val = get_register(instr->rmValue());
3227                             int32_t shift = instr->bits(11, 7);
3228                             rm_val <<= shift;
3229                             set_register(rd, (rn_val & 0xFFFF) | (rm_val & 0xFFFF0000U));
3230                         } else {
3231                             // Pkhtb.
3232                             uint32_t rn_val = get_register(rn);
3233                             int32_t rm_val = get_register(instr->rmValue());
3234                             int32_t shift = instr->bits(11, 7);
3235                             if (shift == 0)
3236                                 shift = 32;
3237                             rm_val >>= shift;
3238                             set_register(rd, (rn_val & 0xFFFF0000U) | (rm_val & 0xFFFF));
3239                         }
3240                     } else {
3241                         MOZ_CRASH();
3242                     }
3243                     break;
3244                   case 1:
3245                     MOZ_CRASH();
3246                     break;
3247                   case 2:
3248                     MOZ_CRASH();
3249                     break;
3250                   case 3: {
3251                     // Usat.
3252                       int32_t sat_pos = instr->bits(20, 16);
3253                       int32_t sat_val = (1 << sat_pos) - 1;
3254                       int32_t shift = instr->bits(11, 7);
3255                       int32_t shift_type = instr->bit(6);
3256                       int32_t rm_val = get_register(instr->rmValue());
3257                       if (shift_type == 0) // LSL
3258                           rm_val <<= shift;
3259                       else // ASR
3260                           rm_val >>= shift;
3261 
3262                       // If saturation occurs, the Q flag should be set in the
3263                       // CPSR. There is no Q flag yet, and no instruction (MRS)
3264                       // to read the CPSR directly.
3265                       if (rm_val > sat_val)
3266                           rm_val = sat_val;
3267                       else if (rm_val < 0)
3268                           rm_val = 0;
3269                       set_register(rd, rm_val);
3270                       break;
3271                   }
3272                 }
3273             } else {
3274                 switch (instr->bits(22, 21)) {
3275                   case 0:
3276                     MOZ_CRASH();
3277                     break;
3278                   case 1:
3279                     if (instr->bits(7,4) == 7 && instr->bits(19,16) == 15) {
3280                         uint32_t rm_val = rotateBytes(get_register(instr->rmValue()),
3281                                                       instr->bits(11, 10));
3282                         if (instr->bit(20)) {
3283                             // Sxth.
3284                             set_register(rd, (int32_t)(int16_t)(rm_val & 0xFFFF));
3285                         }
3286                         else {
3287                             // Sxtb.
3288                             set_register(rd, (int32_t)(int8_t)(rm_val & 0xFF));
3289                         }
3290                     } else {
3291                         MOZ_CRASH();
3292                     }
3293                     break;
3294                   case 2:
3295                     if ((instr->bit(20) == 0) && (instr->bits(9, 6) == 1)) {
3296                         if (instr->bits(19, 16) == 0xF) {
3297                             // Uxtb16.
3298                             uint32_t rm_val = rotateBytes(get_register(instr->rmValue()),
3299                                                           instr->bits(11, 10));
3300                             set_register(rd, (rm_val & 0xFF) | (rm_val & 0xFF0000));
3301                         } else {
3302                             MOZ_CRASH();
3303                         }
3304                     } else {
3305                         MOZ_CRASH();
3306                     }
3307                     break;
3308                   case 3:
3309                     if ((instr->bit(20) == 0) && (instr->bits(9, 6) == 1)) {
3310                         if (instr->bits(19, 16) == 0xF) {
3311                             // Uxtb.
3312                             uint32_t rm_val = rotateBytes(get_register(instr->rmValue()),
3313                                                           instr->bits(11, 10));
3314                             set_register(rd, (rm_val & 0xFF));
3315                         } else {
3316                             // Uxtab.
3317                             uint32_t rn_val = get_register(rn);
3318                             uint32_t rm_val = rotateBytes(get_register(instr->rmValue()),
3319                                                           instr->bits(11, 10));
3320                             set_register(rd, rn_val + (rm_val & 0xFF));
3321                         }
3322                     } else if ((instr->bit(20) == 1) && (instr->bits(9, 6) == 1)) {
3323                         if (instr->bits(19, 16) == 0xF) {
3324                             // Uxth.
3325                             uint32_t rm_val = rotateBytes(get_register(instr->rmValue()),
3326                                                           instr->bits(11, 10));
3327                             set_register(rd, (rm_val & 0xFFFF));
3328                         } else {
3329                             // Uxtah.
3330                             uint32_t rn_val = get_register(rn);
3331                             uint32_t rm_val = rotateBytes(get_register(instr->rmValue()),
3332                                                           instr->bits(11, 10));
3333                             set_register(rd, rn_val + (rm_val & 0xFFFF));
3334                         }
3335                     } else {
3336                         MOZ_CRASH();
3337                     }
3338                     break;
3339                 }
3340             }
3341             return;
3342         }
3343         break;
3344       }
3345       case db_x: { // sudiv
3346         if (instr->bit(22) == 0x0 && instr->bit(20) == 0x1 &&
3347             instr->bits(15,12) == 0x0f && instr->bits(7, 4) == 0x1) {
3348             if (!instr->hasW()) {
3349                 // sdiv (in V8 notation matching ARM ISA format) rn = rm/rs.
3350                 int rm = instr->rmValue();
3351                 int32_t rm_val = get_register(rm);
3352                 int rs = instr->rsValue();
3353                 int32_t rs_val = get_register(rs);
3354                 int32_t ret_val = 0;
3355                 MOZ_ASSERT(rs_val != 0);
3356                 if ((rm_val == INT32_MIN) && (rs_val == -1))
3357                     ret_val = INT32_MIN;
3358                 else
3359                     ret_val = rm_val / rs_val;
3360                 set_register(rn, ret_val);
3361                 return;
3362             } else {
3363                 // udiv (in V8 notation matching ARM ISA format) rn = rm/rs.
3364                 int rm = instr->rmValue();
3365                 uint32_t rm_val = get_register(rm);
3366                 int rs = instr->rsValue();
3367                 uint32_t rs_val = get_register(rs);
3368                 uint32_t ret_val = 0;
3369                 MOZ_ASSERT(rs_val != 0);
3370                 ret_val = rm_val / rs_val;
3371                 set_register(rn, ret_val);
3372                 return;
3373             }
3374         }
3375 
3376         addr = rn_val - shifter_operand;
3377         if (instr->hasW())
3378             set_register(rn, addr);
3379         break;
3380       }
3381       case ib_x: {
3382         if (instr->hasW() && (instr->bits(6, 4) == 0x5)) {
3383             uint32_t widthminus1 = static_cast<uint32_t>(instr->bits(20, 16));
3384             uint32_t lsbit = static_cast<uint32_t>(instr->bits(11, 7));
3385             uint32_t msbit = widthminus1 + lsbit;
3386             if (msbit <= 31) {
3387                 if (instr->bit(22)) {
3388                     // ubfx - unsigned bitfield extract.
3389                     uint32_t rm_val = static_cast<uint32_t>(get_register(instr->rmValue()));
3390                     uint32_t extr_val = rm_val << (31 - msbit);
3391                     extr_val = extr_val >> (31 - widthminus1);
3392                     set_register(instr->rdValue(), extr_val);
3393                 } else {
3394                     // sbfx - signed bitfield extract.
3395                     int32_t rm_val = get_register(instr->rmValue());
3396                     int32_t extr_val = rm_val << (31 - msbit);
3397                     extr_val = extr_val >> (31 - widthminus1);
3398                     set_register(instr->rdValue(), extr_val);
3399                 }
3400             } else {
3401                 MOZ_CRASH();
3402             }
3403             return;
3404         } else if (!instr->hasW() && (instr->bits(6, 4) == 0x1)) {
3405             uint32_t lsbit = static_cast<uint32_t>(instr->bits(11, 7));
3406             uint32_t msbit = static_cast<uint32_t>(instr->bits(20, 16));
3407             if (msbit >= lsbit) {
3408                 // bfc or bfi - bitfield clear/insert.
3409                 uint32_t rd_val =
3410                     static_cast<uint32_t>(get_register(instr->rdValue()));
3411                 uint32_t bitcount = msbit - lsbit + 1;
3412                 uint32_t mask = (1 << bitcount) - 1;
3413                 rd_val &= ~(mask << lsbit);
3414                 if (instr->rmValue() != 15) {
3415                     // bfi - bitfield insert.
3416                     uint32_t rm_val =
3417                         static_cast<uint32_t>(get_register(instr->rmValue()));
3418                     rm_val &= mask;
3419                     rd_val |= rm_val << lsbit;
3420                 }
3421                 set_register(instr->rdValue(), rd_val);
3422             } else {
3423                 MOZ_CRASH();
3424             }
3425             return;
3426         } else {
3427             addr = rn_val + shifter_operand;
3428             if (instr->hasW())
3429                 set_register(rn, addr);
3430         }
3431         break;
3432       }
3433       default:
3434         MOZ_CRASH();
3435         break;
3436     }
3437     if (instr->hasB()) {
3438         if (instr->hasL()) {
3439             uint8_t byte = readB(addr);
3440             set_register(rd, byte);
3441         } else {
3442             uint8_t byte = get_register(rd);
3443             writeB(addr, byte);
3444         }
3445     } else {
3446         if (instr->hasL())
3447             set_register(rd, readW(addr, instr));
3448         else
3449             writeW(addr, get_register(rd), instr);
3450     }
3451 }
3452 
3453 void
decodeType4(SimInstruction * instr)3454 Simulator::decodeType4(SimInstruction* instr)
3455 {
3456     // Only allowed to be set in privileged mode.
3457     MOZ_ASSERT(instr->bit(22) == 0);
3458     bool load = instr->hasL();
3459     handleRList(instr, load);
3460 }
3461 
3462 void
decodeType5(SimInstruction * instr)3463 Simulator::decodeType5(SimInstruction* instr)
3464 {
3465     int off = instr->sImmed24Value() << 2;
3466     intptr_t pc_address = get_pc();
3467     if (instr->hasLink())
3468         set_register(lr, pc_address + SimInstruction::kInstrSize);
3469     int pc_reg = get_register(pc);
3470     set_pc(pc_reg + off);
3471 }
3472 
3473 void
decodeType6(SimInstruction * instr)3474 Simulator::decodeType6(SimInstruction* instr)
3475 {
3476     decodeType6CoprocessorIns(instr);
3477 }
3478 
3479 void
decodeType7(SimInstruction * instr)3480 Simulator::decodeType7(SimInstruction* instr)
3481 {
3482     if (instr->bit(24) == 1)
3483         softwareInterrupt(instr);
3484     else if (instr->bit(4) == 1 && instr->bits(11,9) != 5)
3485         decodeType7CoprocessorIns(instr);
3486     else
3487         decodeTypeVFP(instr);
3488 }
3489 
3490 void
decodeType7CoprocessorIns(SimInstruction * instr)3491 Simulator::decodeType7CoprocessorIns(SimInstruction* instr)
3492 {
3493     if (instr->bit(20) == 0) {
3494         // MCR, MCR2
3495         if (instr->coprocessorValue() == 15) {
3496             int opc1 = instr->bits(23,21);
3497             int opc2 = instr->bits(7,5);
3498             int CRn = instr->bits(19,16);
3499             int CRm = instr->bits(3,0);
3500             if (opc1 == 0 && opc2 == 4 && CRn == 7 && CRm == 10) {
3501                 // ARMv6 DSB instruction.  We do not use DSB.
3502                 MOZ_CRASH("DSB not implemented");
3503             } else if (opc1 == 0 && opc2 == 5 && CRn == 7 && CRm == 10) {
3504                 // ARMv6 DMB instruction.
3505                 AtomicOperations::fenceSeqCst();
3506             }
3507             else if (opc1 == 0 && opc2 == 4 && CRn == 7 && CRm == 5) {
3508                 // ARMv6 ISB instruction.  We do not use ISB.
3509                 MOZ_CRASH("ISB not implemented");
3510             }
3511             else {
3512                 MOZ_CRASH();
3513             }
3514         } else {
3515             MOZ_CRASH();
3516         }
3517     } else {
3518         // MRC, MRC2
3519         MOZ_CRASH();
3520     }
3521 }
3522 
3523 void
decodeTypeVFP(SimInstruction * instr)3524 Simulator::decodeTypeVFP(SimInstruction* instr)
3525 {
3526     MOZ_ASSERT(instr->typeValue() == 7 && instr->bit(24) == 0);
3527     MOZ_ASSERT(instr->bits(11, 9) == 0x5);
3528 
3529     // Obtain double precision register codes.
3530     VFPRegPrecision precision = (instr->szValue() == 1) ? kDoublePrecision : kSinglePrecision;
3531     int vm = instr->VFPMRegValue(precision);
3532     int vd = instr->VFPDRegValue(precision);
3533     int vn = instr->VFPNRegValue(precision);
3534 
3535     if (instr->bit(4) == 0) {
3536         if (instr->opc1Value() == 0x7) {
3537             // Other data processing instructions.
3538             if ((instr->opc2Value() == 0x0) && (instr->opc3Value() == 0x1)) {
3539                 // vmov register to register.
3540                 if (instr->szValue() == 0x1) {
3541                     int m = instr->VFPMRegValue(kDoublePrecision);
3542                     int d = instr->VFPDRegValue(kDoublePrecision);
3543                     set_d_register_from_double(d, get_double_from_d_register(m));
3544                 } else {
3545                     int m = instr->VFPMRegValue(kSinglePrecision);
3546                     int d = instr->VFPDRegValue(kSinglePrecision);
3547                     set_s_register_from_float(d, get_float_from_s_register(m));
3548                 }
3549             } else if ((instr->opc2Value() == 0x0) && (instr->opc3Value() == 0x3)) {
3550                 // vabs
3551                 if (instr->szValue() == 0x1) {
3552                     double dm_value = get_double_from_d_register(vm);
3553                     double dd_value = std::fabs(dm_value);
3554                     dd_value = canonicalizeNaN(dd_value);
3555                     set_d_register_from_double(vd, dd_value);
3556                 } else {
3557                     float fm_value = get_float_from_s_register(vm);
3558                     float fd_value = std::fabs(fm_value);
3559                     fd_value = canonicalizeNaN(fd_value);
3560                     set_s_register_from_float(vd, fd_value);
3561                 }
3562             } else if ((instr->opc2Value() == 0x1) && (instr->opc3Value() == 0x1)) {
3563                 // vneg
3564                 if (instr->szValue() == 0x1) {
3565                     double dm_value = get_double_from_d_register(vm);
3566                     double dd_value = -dm_value;
3567                     dd_value = canonicalizeNaN(dd_value);
3568                     set_d_register_from_double(vd, dd_value);
3569                 } else {
3570                     float fm_value = get_float_from_s_register(vm);
3571                     float fd_value = -fm_value;
3572                     fd_value = canonicalizeNaN(fd_value);
3573                     set_s_register_from_float(vd, fd_value);
3574                 }
3575             } else if ((instr->opc2Value() == 0x7) && (instr->opc3Value() == 0x3)) {
3576                 decodeVCVTBetweenDoubleAndSingle(instr);
3577             } else if ((instr->opc2Value() == 0x8) && (instr->opc3Value() & 0x1)) {
3578                 decodeVCVTBetweenFloatingPointAndInteger(instr);
3579             } else if ((instr->opc2Value() == 0xA) && (instr->opc3Value() == 0x3) &&
3580                        (instr->bit(8) == 1)) {
3581                 // vcvt.f64.s32 Dd, Dd, #<fbits>.
3582                 int fraction_bits = 32 - ((instr->bits(3, 0) << 1) | instr->bit(5));
3583                 int fixed_value = get_sinteger_from_s_register(vd * 2);
3584                 double divide = 1 << fraction_bits;
3585                 set_d_register_from_double(vd, fixed_value / divide);
3586             } else if (((instr->opc2Value() >> 1) == 0x6) &&
3587                        (instr->opc3Value() & 0x1)) {
3588                 decodeVCVTBetweenFloatingPointAndInteger(instr);
3589             } else if (((instr->opc2Value() == 0x4) || (instr->opc2Value() == 0x5)) &&
3590                        (instr->opc3Value() & 0x1)) {
3591                 decodeVCMP(instr);
3592             } else if (((instr->opc2Value() == 0x1)) && (instr->opc3Value() == 0x3)) {
3593                 // vsqrt
3594                 if (instr->szValue() == 0x1) {
3595                     double dm_value = get_double_from_d_register(vm);
3596                     double dd_value = std::sqrt(dm_value);
3597                     dd_value = canonicalizeNaN(dd_value);
3598                     set_d_register_from_double(vd, dd_value);
3599                 } else {
3600                     float fm_value = get_float_from_s_register(vm);
3601                     float fd_value = std::sqrt(fm_value);
3602                     fd_value = canonicalizeNaN(fd_value);
3603                     set_s_register_from_float(vd, fd_value);
3604                 }
3605             } else if (instr->opc3Value() == 0x0) {
3606                 // vmov immediate.
3607                 if (instr->szValue() == 0x1) {
3608                     set_d_register_from_double(vd, instr->doubleImmedVmov());
3609                 } else {
3610                     // vmov.f32 immediate.
3611                     set_s_register_from_float(vd, instr->float32ImmedVmov());
3612                 }
3613             } else {
3614                 decodeVCVTBetweenFloatingPointAndIntegerFrac(instr);
3615             }
3616         } else if (instr->opc1Value() == 0x3) {
3617             if (instr->szValue() != 0x1) {
3618                 if (instr->opc3Value() & 0x1) {
3619                     // vsub
3620                     float fn_value = get_float_from_s_register(vn);
3621                     float fm_value = get_float_from_s_register(vm);
3622                     float fd_value = fn_value - fm_value;
3623                     fd_value = canonicalizeNaN(fd_value);
3624                     set_s_register_from_float(vd, fd_value);
3625                 } else {
3626                     // vadd
3627                     float fn_value = get_float_from_s_register(vn);
3628                     float fm_value = get_float_from_s_register(vm);
3629                     float fd_value = fn_value + fm_value;
3630                     fd_value = canonicalizeNaN(fd_value);
3631                     set_s_register_from_float(vd, fd_value);
3632                 }
3633             } else {
3634                 if (instr->opc3Value() & 0x1) {
3635                     // vsub
3636                     double dn_value = get_double_from_d_register(vn);
3637                     double dm_value = get_double_from_d_register(vm);
3638                     double dd_value = dn_value - dm_value;
3639                     dd_value = canonicalizeNaN(dd_value);
3640                     set_d_register_from_double(vd, dd_value);
3641                 } else {
3642                     // vadd
3643                     double dn_value = get_double_from_d_register(vn);
3644                     double dm_value = get_double_from_d_register(vm);
3645                     double dd_value = dn_value + dm_value;
3646                     dd_value = canonicalizeNaN(dd_value);
3647                     set_d_register_from_double(vd, dd_value);
3648                 }
3649             }
3650         } else if ((instr->opc1Value() == 0x2) && !(instr->opc3Value() & 0x1)) {
3651             // vmul
3652             if (instr->szValue() != 0x1) {
3653                 float fn_value = get_float_from_s_register(vn);
3654                 float fm_value = get_float_from_s_register(vm);
3655                 float fd_value = fn_value * fm_value;
3656                 fd_value = canonicalizeNaN(fd_value);
3657                 set_s_register_from_float(vd, fd_value);
3658             } else {
3659                 double dn_value = get_double_from_d_register(vn);
3660                 double dm_value = get_double_from_d_register(vm);
3661                 double dd_value = dn_value * dm_value;
3662                 dd_value = canonicalizeNaN(dd_value);
3663                 set_d_register_from_double(vd, dd_value);
3664             }
3665         } else if ((instr->opc1Value() == 0x0)) {
3666             // vmla, vmls
3667             const bool is_vmls = (instr->opc3Value() & 0x1);
3668 
3669             if (instr->szValue() != 0x1)
3670                 MOZ_CRASH("Not used by V8.");
3671 
3672             const double dd_val = get_double_from_d_register(vd);
3673             const double dn_val = get_double_from_d_register(vn);
3674             const double dm_val = get_double_from_d_register(vm);
3675 
3676             // Note: we do the mul and add/sub in separate steps to avoid
3677             // getting a result with too high precision.
3678             set_d_register_from_double(vd, dn_val * dm_val);
3679             if (is_vmls) {
3680                 set_d_register_from_double(vd,
3681                                            canonicalizeNaN(dd_val - get_double_from_d_register(vd)));
3682             } else {
3683                 set_d_register_from_double(vd,
3684                                            canonicalizeNaN(dd_val + get_double_from_d_register(vd)));
3685             }
3686         } else if ((instr->opc1Value() == 0x4) && !(instr->opc3Value() & 0x1)) {
3687             // vdiv
3688             if (instr->szValue() != 0x1) {
3689                 float fn_value = get_float_from_s_register(vn);
3690                 float fm_value = get_float_from_s_register(vm);
3691                 float fd_value = fn_value / fm_value;
3692                 div_zero_vfp_flag_ = (fm_value == 0);
3693                 fd_value = canonicalizeNaN(fd_value);
3694                 set_s_register_from_float(vd, fd_value);
3695             } else {
3696                 double dn_value = get_double_from_d_register(vn);
3697                 double dm_value = get_double_from_d_register(vm);
3698                 double dd_value = dn_value / dm_value;
3699                 div_zero_vfp_flag_ = (dm_value == 0);
3700                 dd_value = canonicalizeNaN(dd_value);
3701                 set_d_register_from_double(vd, dd_value);
3702             }
3703         } else {
3704             MOZ_CRASH();
3705         }
3706     } else {
3707         if (instr->VCValue() == 0x0 && instr->VAValue() == 0x0) {
3708             decodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr);
3709         } else if ((instr->VLValue() == 0x0) &&
3710                    (instr->VCValue() == 0x1) &&
3711                    (instr->bit(23) == 0x0)) {
3712             // vmov (ARM core register to scalar).
3713             int vd = instr->bits(19, 16) | (instr->bit(7) << 4);
3714             double dd_value = get_double_from_d_register(vd);
3715             int32_t data[2];
3716             memcpy(data, &dd_value, 8);
3717             data[instr->bit(21)] = get_register(instr->rtValue());
3718             memcpy(&dd_value, data, 8);
3719             set_d_register_from_double(vd, dd_value);
3720         } else if ((instr->VLValue() == 0x1) &&
3721                    (instr->VCValue() == 0x1) &&
3722                    (instr->bit(23) == 0x0)) {
3723             // vmov (scalar to ARM core register).
3724             int vn = instr->bits(19, 16) | (instr->bit(7) << 4);
3725             double dn_value = get_double_from_d_register(vn);
3726             int32_t data[2];
3727             memcpy(data, &dn_value, 8);
3728             set_register(instr->rtValue(), data[instr->bit(21)]);
3729         } else if ((instr->VLValue() == 0x1) &&
3730                    (instr->VCValue() == 0x0) &&
3731                    (instr->VAValue() == 0x7) &&
3732                    (instr->bits(19, 16) == 0x1)) {
3733             // vmrs
3734             uint32_t rt = instr->rtValue();
3735             if (rt == 0xF) {
3736                 copy_FPSCR_to_APSR();
3737             } else {
3738                 // Emulate FPSCR from the Simulator flags.
3739                 uint32_t fpscr = (n_flag_FPSCR_ << 31) |
3740                     (z_flag_FPSCR_ << 30) |
3741                     (c_flag_FPSCR_ << 29) |
3742                     (v_flag_FPSCR_ << 28) |
3743                     (FPSCR_default_NaN_mode_ << 25) |
3744                     (inexact_vfp_flag_ << 4) |
3745                     (underflow_vfp_flag_ << 3) |
3746                     (overflow_vfp_flag_ << 2) |
3747                     (div_zero_vfp_flag_ << 1) |
3748                     (inv_op_vfp_flag_ << 0) |
3749                     (FPSCR_rounding_mode_);
3750                 set_register(rt, fpscr);
3751             }
3752         } else if ((instr->VLValue() == 0x0) &&
3753                    (instr->VCValue() == 0x0) &&
3754                    (instr->VAValue() == 0x7) &&
3755                    (instr->bits(19, 16) == 0x1)) {
3756             // vmsr
3757             uint32_t rt = instr->rtValue();
3758             if (rt == pc) {
3759                 MOZ_CRASH();
3760             } else {
3761                 uint32_t rt_value = get_register(rt);
3762                 n_flag_FPSCR_ = (rt_value >> 31) & 1;
3763                 z_flag_FPSCR_ = (rt_value >> 30) & 1;
3764                 c_flag_FPSCR_ = (rt_value >> 29) & 1;
3765                 v_flag_FPSCR_ = (rt_value >> 28) & 1;
3766                 FPSCR_default_NaN_mode_ = (rt_value >> 25) & 1;
3767                 inexact_vfp_flag_ = (rt_value >> 4) & 1;
3768                 underflow_vfp_flag_ = (rt_value >> 3) & 1;
3769                 overflow_vfp_flag_ = (rt_value >> 2) & 1;
3770                 div_zero_vfp_flag_ = (rt_value >> 1) & 1;
3771                 inv_op_vfp_flag_ = (rt_value >> 0) & 1;
3772                 FPSCR_rounding_mode_ =
3773                     static_cast<VFPRoundingMode>((rt_value) & kVFPRoundingModeMask);
3774             }
3775         } else {
3776             MOZ_CRASH();
3777         }
3778     }
3779 }
3780 
3781 void
decodeVMOVBetweenCoreAndSinglePrecisionRegisters(SimInstruction * instr)3782 Simulator::decodeVMOVBetweenCoreAndSinglePrecisionRegisters(SimInstruction* instr)
3783 {
3784     MOZ_ASSERT(instr->bit(4) == 1 &&
3785                instr->VCValue() == 0x0 &&
3786                instr->VAValue() == 0x0);
3787 
3788     int t = instr->rtValue();
3789     int n = instr->VFPNRegValue(kSinglePrecision);
3790     bool to_arm_register = (instr->VLValue() == 0x1);
3791     if (to_arm_register) {
3792         int32_t int_value = get_sinteger_from_s_register(n);
3793         set_register(t, int_value);
3794     } else {
3795         int32_t rs_val = get_register(t);
3796         set_s_register_from_sinteger(n, rs_val);
3797     }
3798 }
3799 
3800 void
decodeVCMP(SimInstruction * instr)3801 Simulator::decodeVCMP(SimInstruction* instr)
3802 {
3803     MOZ_ASSERT((instr->bit(4) == 0) && (instr->opc1Value() == 0x7));
3804     MOZ_ASSERT(((instr->opc2Value() == 0x4) || (instr->opc2Value() == 0x5)) &&
3805                (instr->opc3Value() & 0x1));
3806     // Comparison.
3807 
3808     VFPRegPrecision precision = kSinglePrecision;
3809     if (instr->szValue() == 1)
3810         precision = kDoublePrecision;
3811 
3812     int d = instr->VFPDRegValue(precision);
3813     int m = 0;
3814     if (instr->opc2Value() == 0x4)
3815         m = instr->VFPMRegValue(precision);
3816 
3817     if (precision == kDoublePrecision) {
3818         double dd_value = get_double_from_d_register(d);
3819         double dm_value = 0.0;
3820         if (instr->opc2Value() == 0x4) {
3821             dm_value = get_double_from_d_register(m);
3822         }
3823 
3824         // Raise exceptions for quiet NaNs if necessary.
3825         if (instr->bit(7) == 1) {
3826             if (mozilla::IsNaN(dd_value))
3827                 inv_op_vfp_flag_ = true;
3828         }
3829         compute_FPSCR_Flags(dd_value, dm_value);
3830     } else {
3831         float fd_value = get_float_from_s_register(d);
3832         float fm_value = 0.0;
3833         if (instr->opc2Value() == 0x4)
3834             fm_value = get_float_from_s_register(m);
3835 
3836         // Raise exceptions for quiet NaNs if necessary.
3837         if (instr->bit(7) == 1) {
3838             if (mozilla::IsNaN(fd_value))
3839                 inv_op_vfp_flag_ = true;
3840         }
3841         compute_FPSCR_Flags(fd_value, fm_value);
3842     }
3843 }
3844 
3845 void
decodeVCVTBetweenDoubleAndSingle(SimInstruction * instr)3846 Simulator::decodeVCVTBetweenDoubleAndSingle(SimInstruction* instr)
3847 {
3848     MOZ_ASSERT(instr->bit(4) == 0 && instr->opc1Value() == 0x7);
3849     MOZ_ASSERT(instr->opc2Value() == 0x7 && instr->opc3Value() == 0x3);
3850 
3851     VFPRegPrecision dst_precision = kDoublePrecision;
3852     VFPRegPrecision src_precision = kSinglePrecision;
3853     if (instr->szValue() == 1) {
3854         dst_precision = kSinglePrecision;
3855         src_precision = kDoublePrecision;
3856     }
3857 
3858     int dst = instr->VFPDRegValue(dst_precision);
3859     int src = instr->VFPMRegValue(src_precision);
3860 
3861     if (dst_precision == kSinglePrecision) {
3862         double val = get_double_from_d_register(src);
3863         set_s_register_from_float(dst, static_cast<float>(val));
3864     } else {
3865         float val = get_float_from_s_register(src);
3866         set_d_register_from_double(dst, static_cast<double>(val));
3867     }
3868 }
3869 
3870 static bool
get_inv_op_vfp_flag(VFPRoundingMode mode,double val,bool unsigned_)3871 get_inv_op_vfp_flag(VFPRoundingMode mode, double val, bool unsigned_)
3872 {
3873     MOZ_ASSERT(mode == SimRN || mode == SimRM || mode == SimRZ);
3874     double max_uint = static_cast<double>(0xffffffffu);
3875     double max_int = static_cast<double>(INT32_MAX);
3876     double min_int = static_cast<double>(INT32_MIN);
3877 
3878     // Check for NaN.
3879     if (val != val)
3880         return true;
3881 
3882     // Check for overflow. This code works because 32bit integers can be exactly
3883     // represented by ieee-754 64bit floating-point values.
3884     switch (mode) {
3885       case SimRN:
3886         return  unsigned_ ? (val >= (max_uint + 0.5)) ||
3887                             (val < -0.5)
3888                           : (val >= (max_int + 0.5)) ||
3889                             (val < (min_int - 0.5));
3890       case SimRM:
3891         return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3892                             (val < 0)
3893                           : (val >= (max_int + 1.0)) ||
3894                             (val < min_int);
3895       case SimRZ:
3896         return  unsigned_ ? (val >= (max_uint + 1.0)) ||
3897                             (val <= -1)
3898                           : (val >= (max_int + 1.0)) ||
3899                             (val <= (min_int - 1.0));
3900       default:
3901         MOZ_CRASH();
3902         return true;
3903     }
3904 }
3905 
3906 // We call this function only if we had a vfp invalid exception.
3907 // It returns the correct saturated value.
3908 static int
VFPConversionSaturate(double val,bool unsigned_res)3909 VFPConversionSaturate(double val, bool unsigned_res)
3910 {
3911     if (val != val) // NaN.
3912         return 0;
3913     if (unsigned_res)
3914         return (val < 0) ? 0 : 0xffffffffu;
3915     return (val < 0) ? INT32_MIN : INT32_MAX;
3916 }
3917 
3918 void
decodeVCVTBetweenFloatingPointAndInteger(SimInstruction * instr)3919 Simulator::decodeVCVTBetweenFloatingPointAndInteger(SimInstruction* instr)
3920 {
3921     MOZ_ASSERT((instr->bit(4) == 0) && (instr->opc1Value() == 0x7) &&
3922                (instr->bits(27, 23) == 0x1D));
3923     MOZ_ASSERT(((instr->opc2Value() == 0x8) && (instr->opc3Value() & 0x1)) ||
3924                (((instr->opc2Value() >> 1) == 0x6) && (instr->opc3Value() & 0x1)));
3925 
3926     // Conversion between floating-point and integer.
3927     bool to_integer = (instr->bit(18) == 1);
3928 
3929     VFPRegPrecision src_precision = (instr->szValue() == 1) ? kDoublePrecision : kSinglePrecision;
3930 
3931     if (to_integer) {
3932         // We are playing with code close to the C++ standard's limits below,
3933         // hence the very simple code and heavy checks.
3934         //
3935         // Note: C++ defines default type casting from floating point to integer
3936         // as (close to) rounding toward zero ("fractional part discarded").
3937 
3938         int dst = instr->VFPDRegValue(kSinglePrecision);
3939         int src = instr->VFPMRegValue(src_precision);
3940 
3941         // Bit 7 in vcvt instructions indicates if we should use the FPSCR
3942         // rounding mode or the default Round to Zero mode.
3943         VFPRoundingMode mode = (instr->bit(7) != 1) ? FPSCR_rounding_mode_ : SimRZ;
3944         MOZ_ASSERT(mode == SimRM || mode == SimRZ || mode == SimRN);
3945 
3946         bool unsigned_integer = (instr->bit(16) == 0);
3947         bool double_precision = (src_precision == kDoublePrecision);
3948 
3949         double val = double_precision
3950                      ? get_double_from_d_register(src)
3951                      : get_float_from_s_register(src);
3952 
3953         int temp = unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
3954 
3955         inv_op_vfp_flag_ = get_inv_op_vfp_flag(mode, val, unsigned_integer);
3956 
3957         double abs_diff = unsigned_integer
3958                           ? std::fabs(val - static_cast<uint32_t>(temp))
3959                           : std::fabs(val - temp);
3960 
3961         inexact_vfp_flag_ = (abs_diff != 0);
3962 
3963         if (inv_op_vfp_flag_) {
3964             temp = VFPConversionSaturate(val, unsigned_integer);
3965         } else {
3966             switch (mode) {
3967               case SimRN: {
3968                 int val_sign = (val > 0) ? 1 : -1;
3969                 if (abs_diff > 0.5) {
3970                     temp += val_sign;
3971                 } else if (abs_diff == 0.5) {
3972                     // Round to even if exactly halfway.
3973                     temp = ((temp % 2) == 0) ? temp : temp + val_sign;
3974                 }
3975                 break;
3976               }
3977 
3978               case SimRM:
3979                 temp = temp > val ? temp - 1 : temp;
3980                   break;
3981 
3982               case SimRZ:
3983                 // Nothing to do.
3984                 break;
3985 
3986               default:
3987                 MOZ_CRASH();
3988             }
3989         }
3990 
3991         // Update the destination register.
3992         set_s_register_from_sinteger(dst, temp);
3993     } else {
3994         bool unsigned_integer = (instr->bit(7) == 0);
3995         int dst = instr->VFPDRegValue(src_precision);
3996         int src = instr->VFPMRegValue(kSinglePrecision);
3997 
3998         int val = get_sinteger_from_s_register(src);
3999 
4000         if (src_precision == kDoublePrecision) {
4001             if (unsigned_integer)
4002                 set_d_register_from_double(dst, static_cast<double>(static_cast<uint32_t>(val)));
4003             else
4004                 set_d_register_from_double(dst, static_cast<double>(val));
4005         } else {
4006             if (unsigned_integer)
4007                 set_s_register_from_float(dst, static_cast<float>(static_cast<uint32_t>(val)));
4008             else
4009                 set_s_register_from_float(dst, static_cast<float>(val));
4010         }
4011     }
4012 }
4013 
4014 // A VFPv3 specific instruction.
4015 void
decodeVCVTBetweenFloatingPointAndIntegerFrac(SimInstruction * instr)4016 Simulator::decodeVCVTBetweenFloatingPointAndIntegerFrac(SimInstruction* instr)
4017 {
4018     MOZ_ASSERT(instr->bits(27, 24) == 0xE && instr->opc1Value() == 0x7 && instr->bit(19) == 1 &&
4019                instr->bit(17) == 1 && instr->bits(11,9) == 0x5 && instr->bit(6) == 1 &&
4020                instr->bit(4) == 0);
4021 
4022     int size = (instr->bit(7) == 1) ? 32 : 16;
4023 
4024     int fraction_bits = size - ((instr->bits(3, 0) << 1) | instr->bit(5));
4025     double mult = 1 << fraction_bits;
4026 
4027     MOZ_ASSERT(size == 32); // Only handling size == 32 for now.
4028 
4029     // Conversion between floating-point and integer.
4030     bool to_fixed = (instr->bit(18) == 1);
4031 
4032     VFPRegPrecision precision = (instr->szValue() == 1) ? kDoublePrecision : kSinglePrecision;
4033 
4034     if (to_fixed) {
4035         // We are playing with code close to the C++ standard's limits below,
4036         // hence the very simple code and heavy checks.
4037         //
4038         // Note: C++ defines default type casting from floating point to integer
4039         // as (close to) rounding toward zero ("fractional part discarded").
4040 
4041         int dst = instr->VFPDRegValue(precision);
4042 
4043         bool unsigned_integer = (instr->bit(16) == 1);
4044         bool double_precision = (precision == kDoublePrecision);
4045 
4046         double val = double_precision
4047                      ? get_double_from_d_register(dst)
4048                      : get_float_from_s_register(dst);
4049 
4050         // Scale value by specified number of fraction bits.
4051         val *= mult;
4052 
4053         // Rounding down towards zero. No need to account for the rounding error
4054         // as this instruction always rounds down towards zero. See SimRZ below.
4055         int temp = unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val);
4056 
4057         inv_op_vfp_flag_ = get_inv_op_vfp_flag(SimRZ, val, unsigned_integer);
4058 
4059         double abs_diff = unsigned_integer
4060                           ? std::fabs(val - static_cast<uint32_t>(temp))
4061                           : std::fabs(val - temp);
4062 
4063         inexact_vfp_flag_ = (abs_diff != 0);
4064 
4065         if (inv_op_vfp_flag_)
4066             temp = VFPConversionSaturate(val, unsigned_integer);
4067 
4068         // Update the destination register.
4069         if (double_precision) {
4070             uint32_t dbl[2];
4071             dbl[0] = temp; dbl[1] = 0;
4072             set_d_register(dst, dbl);
4073         } else {
4074             set_s_register_from_sinteger(dst, temp);
4075         }
4076     } else {
4077         MOZ_CRASH();  // Not implemented, fixed to float.
4078     }
4079 }
4080 
4081 void
decodeType6CoprocessorIns(SimInstruction * instr)4082 Simulator::decodeType6CoprocessorIns(SimInstruction* instr)
4083 {
4084     MOZ_ASSERT(instr->typeValue() == 6);
4085 
4086     if (instr->coprocessorValue() == 0xA) {
4087         switch (instr->opcodeValue()) {
4088           case 0x8:
4089           case 0xA:
4090           case 0xC:
4091           case 0xE: {  // Load and store single precision float to memory.
4092             int rn = instr->rnValue();
4093             int vd = instr->VFPDRegValue(kSinglePrecision);
4094             int offset = instr->immed8Value();
4095             if (!instr->hasU())
4096                 offset = -offset;
4097 
4098             int32_t address = get_register(rn) + 4 * offset;
4099             if (instr->hasL()) {
4100                 // Load double from memory: vldr.
4101                 set_s_register_from_sinteger(vd, readW(address, instr));
4102             } else {
4103                 // Store double to memory: vstr.
4104                 writeW(address, get_sinteger_from_s_register(vd), instr);
4105             }
4106             break;
4107           }
4108           case 0x4:
4109           case 0x5:
4110           case 0x6:
4111           case 0x7:
4112           case 0x9:
4113           case 0xB:
4114             // Load/store multiple single from memory: vldm/vstm.
4115             handleVList(instr);
4116             break;
4117           default:
4118             MOZ_CRASH();
4119         }
4120     } else if (instr->coprocessorValue() == 0xB) {
4121         switch (instr->opcodeValue()) {
4122           case 0x2:
4123             // Load and store double to two GP registers
4124             if (instr->bits(7, 6) != 0 || instr->bit(4) != 1) {
4125                 MOZ_CRASH();  // Not used atm.
4126             } else {
4127                 int rt = instr->rtValue();
4128                 int rn = instr->rnValue();
4129                 int vm = instr->VFPMRegValue(kDoublePrecision);
4130                 if (instr->hasL()) {
4131                     int32_t data[2];
4132                     double d = get_double_from_d_register(vm);
4133                     memcpy(data, &d, 8);
4134                     set_register(rt, data[0]);
4135                     set_register(rn, data[1]);
4136                 } else {
4137                     int32_t data[] = { get_register(rt), get_register(rn) };
4138                     double d;
4139                     memcpy(&d, data, 8);
4140                     set_d_register_from_double(vm, d);
4141                 }
4142             }
4143             break;
4144           case 0x8:
4145           case 0xA:
4146           case 0xC:
4147           case 0xE: {  // Load and store double to memory.
4148             int rn = instr->rnValue();
4149             int vd = instr->VFPDRegValue(kDoublePrecision);
4150             int offset = instr->immed8Value();
4151             if (!instr->hasU())
4152                 offset = -offset;
4153             int32_t address = get_register(rn) + 4 * offset;
4154             if (instr->hasL()) {
4155                 // Load double from memory: vldr.
4156                 int32_t data[] = {
4157                     readW(address, instr),
4158                     readW(address + 4, instr)
4159                 };
4160                 double val;
4161                 memcpy(&val, data, 8);
4162                 set_d_register_from_double(vd, val);
4163             } else {
4164                 // Store double to memory: vstr.
4165                 int32_t data[2];
4166                 double val = get_double_from_d_register(vd);
4167                 memcpy(data, &val, 8);
4168                 writeW(address, data[0], instr);
4169                 writeW(address + 4, data[1], instr);
4170             }
4171             break;
4172           }
4173           case 0x4:
4174           case 0x5:
4175           case 0x6:
4176           case 0x7:
4177           case 0x9:
4178           case 0xB:
4179             // Load/store multiple double from memory: vldm/vstm.
4180             handleVList(instr);
4181             break;
4182           default:
4183             MOZ_CRASH();
4184         }
4185     } else {
4186         MOZ_CRASH();
4187     }
4188 }
4189 
4190 void
decodeSpecialCondition(SimInstruction * instr)4191 Simulator::decodeSpecialCondition(SimInstruction* instr)
4192 {
4193     switch (instr->specialValue()) {
4194       case 5:
4195         if (instr->bits(18, 16) == 0 && instr->bits(11, 6) == 0x28 && instr->bit(4) == 1) {
4196             // vmovl signed
4197             if ((instr->vdValue() & 1) != 0)
4198                 MOZ_CRASH("Undefined behavior");
4199             int Vd = (instr->bit(22) << 3) | (instr->vdValue() >> 1);
4200             int Vm = (instr->bit(5) << 4) | instr->vmValue();
4201             int imm3 = instr->bits(21, 19);
4202             if (imm3 != 1 && imm3 != 2 && imm3 != 4)
4203                 MOZ_CRASH();
4204             int esize = 8 * imm3;
4205             int elements = 64 / esize;
4206             int8_t from[8];
4207             get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
4208             int16_t to[8];
4209             int e = 0;
4210             while (e < elements) {
4211                 to[e] = from[e];
4212                 e++;
4213             }
4214             set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
4215         } else {
4216             MOZ_CRASH();
4217         }
4218         break;
4219       case 7:
4220         if (instr->bits(18, 16) == 0 && instr->bits(11, 6) == 0x28 && instr->bit(4) == 1) {
4221             // vmovl unsigned.
4222             if ((instr->vdValue() & 1) != 0)
4223                 MOZ_CRASH("Undefined behavior");
4224             int Vd = (instr->bit(22) << 3) | (instr->vdValue() >> 1);
4225             int Vm = (instr->bit(5) << 4) | instr->vmValue();
4226             int imm3 = instr->bits(21, 19);
4227             if (imm3 != 1 && imm3 != 2 && imm3 != 4)
4228                 MOZ_CRASH();
4229             int esize = 8 * imm3;
4230             int elements = 64 / esize;
4231             uint8_t from[8];
4232             get_d_register(Vm, reinterpret_cast<uint64_t*>(from));
4233             uint16_t to[8];
4234             int e = 0;
4235             while (e < elements) {
4236                 to[e] = from[e];
4237                 e++;
4238             }
4239             set_q_register(Vd, reinterpret_cast<uint64_t*>(to));
4240         } else {
4241             MOZ_CRASH();
4242         }
4243         break;
4244       case 8:
4245         if (instr->bits(21, 20) == 0) {
4246             // vst1
4247             int Vd = (instr->bit(22) << 4) | instr->vdValue();
4248             int Rn = instr->vnValue();
4249             int type = instr->bits(11, 8);
4250             int Rm = instr->vmValue();
4251             int32_t address = get_register(Rn);
4252             int regs = 0;
4253             switch (type) {
4254               case nlt_1:
4255                 regs = 1;
4256                 break;
4257               case nlt_2:
4258                 regs = 2;
4259                 break;
4260               case nlt_3:
4261                 regs = 3;
4262                 break;
4263               case nlt_4:
4264                 regs = 4;
4265                 break;
4266               default:
4267                 MOZ_CRASH();
4268                 break;
4269             }
4270             int r = 0;
4271             while (r < regs) {
4272                 uint32_t data[2];
4273                 get_d_register(Vd + r, data);
4274                 writeW(address, data[0], instr);
4275                 writeW(address + 4, data[1], instr);
4276                 address += 8;
4277                 r++;
4278             }
4279             if (Rm != 15) {
4280                 if (Rm == 13)
4281                     set_register(Rn, address);
4282                 else
4283                     set_register(Rn, get_register(Rn) + get_register(Rm));
4284             }
4285         } else if (instr->bits(21, 20) == 2) {
4286             // vld1
4287             int Vd = (instr->bit(22) << 4) | instr->vdValue();
4288             int Rn = instr->vnValue();
4289             int type = instr->bits(11, 8);
4290             int Rm = instr->vmValue();
4291             int32_t address = get_register(Rn);
4292             int regs = 0;
4293             switch (type) {
4294               case nlt_1:
4295                 regs = 1;
4296                 break;
4297               case nlt_2:
4298                 regs = 2;
4299                 break;
4300               case nlt_3:
4301                 regs = 3;
4302                 break;
4303               case nlt_4:
4304                 regs = 4;
4305                 break;
4306               default:
4307                 MOZ_CRASH();
4308                 break;
4309             }
4310             int r = 0;
4311             while (r < regs) {
4312                 uint32_t data[2];
4313                 data[0] = readW(address, instr);
4314                 data[1] = readW(address + 4, instr);
4315                 set_d_register(Vd + r, data);
4316                 address += 8;
4317                 r++;
4318             }
4319             if (Rm != 15) {
4320                 if (Rm == 13)
4321                     set_register(Rn, address);
4322                 else
4323                     set_register(Rn, get_register(Rn) + get_register(Rm));
4324             }
4325         } else {
4326             MOZ_CRASH();
4327         }
4328         break;
4329       case 0xA:
4330         if (instr->bits(31,20) == 0xf57) {
4331             switch (instr->bits(7,4)) {
4332               case 5: // DMB
4333                 AtomicOperations::fenceSeqCst();
4334                 break;
4335               case 4: // DSB
4336                 // We do not use DSB.
4337                 MOZ_CRASH("DSB unimplemented");
4338               case 6: // ISB
4339                 // We do not use ISB.
4340                 MOZ_CRASH("ISB unimplemented");
4341               default:
4342                 MOZ_CRASH();
4343             }
4344         } else {
4345             MOZ_CRASH();
4346         }
4347         break;
4348       case 0xB:
4349         if (instr->bits(22, 20) == 5 && instr->bits(15, 12) == 0xf) {
4350             // pld: ignore instruction.
4351         } else {
4352             MOZ_CRASH();
4353         }
4354         break;
4355       case 0x1C:
4356       case 0x1D:
4357         if (instr->bit(4) == 1 && instr->bits(11,9) != 5) {
4358             // MCR, MCR2, MRC, MRC2 with cond == 15
4359             decodeType7CoprocessorIns(instr);
4360         } else {
4361             MOZ_CRASH();
4362         }
4363         break;
4364       default:
4365         MOZ_CRASH();
4366     }
4367 }
4368 
4369 // Executes the current instruction.
4370 void
instructionDecode(SimInstruction * instr)4371 Simulator::instructionDecode(SimInstruction* instr)
4372 {
4373     if (Simulator::ICacheCheckingEnabled) {
4374         AutoLockSimulatorCache als(this);
4375         CheckICacheLocked(icache(), instr);
4376     }
4377 
4378     pc_modified_ = false;
4379 
4380     static const uint32_t kSpecialCondition = 15 << 28;
4381     if (instr->conditionField() == kSpecialCondition) {
4382         decodeSpecialCondition(instr);
4383     } else if (conditionallyExecute(instr)) {
4384         switch (instr->typeValue()) {
4385           case 0:
4386           case 1:
4387             decodeType01(instr);
4388             break;
4389           case 2:
4390             decodeType2(instr);
4391             break;
4392           case 3:
4393             decodeType3(instr);
4394             break;
4395           case 4:
4396             decodeType4(instr);
4397             break;
4398           case 5:
4399             decodeType5(instr);
4400             break;
4401           case 6:
4402             decodeType6(instr);
4403             break;
4404           case 7:
4405             decodeType7(instr);
4406             break;
4407           default:
4408             MOZ_CRASH();
4409             break;
4410         }
4411         // If the instruction is a non taken conditional stop, we need to skip
4412         // the inlined message address.
4413     } else if (instr->isStop()) {
4414         set_pc(get_pc() + 2 * SimInstruction::kInstrSize);
4415     }
4416     if (!pc_modified_)
4417         set_register(pc, reinterpret_cast<int32_t>(instr) + SimInstruction::kInstrSize);
4418 }
4419 
4420 void
enable_single_stepping(SingleStepCallback cb,void * arg)4421 Simulator::enable_single_stepping(SingleStepCallback cb, void* arg)
4422 {
4423     single_stepping_ = true;
4424     single_step_callback_ = cb;
4425     single_step_callback_arg_ = arg;
4426     single_step_callback_(single_step_callback_arg_, this, (void*)get_pc());
4427 }
4428 
4429 void
disable_single_stepping()4430 Simulator::disable_single_stepping()
4431 {
4432     if (!single_stepping_)
4433         return;
4434     single_step_callback_(single_step_callback_arg_, this, (void*)get_pc());
4435     single_stepping_ = false;
4436     single_step_callback_ = nullptr;
4437     single_step_callback_arg_ = nullptr;
4438 }
4439 
4440 template<bool EnableStopSimAt>
4441 void
execute()4442 Simulator::execute()
4443 {
4444     if (single_stepping_)
4445         single_step_callback_(single_step_callback_arg_, this, nullptr);
4446 
4447     // Get the PC to simulate. Cannot use the accessor here as we need the raw
4448     // PC value and not the one used as input to arithmetic instructions.
4449     int program_counter = get_pc();
4450 
4451     while (program_counter != end_sim_pc) {
4452         if (EnableStopSimAt && (icount_ == Simulator::StopSimAt)) {
4453             fprintf(stderr, "\nStopped simulation at icount %lld\n", icount_);
4454             ArmDebugger dbg(this);
4455             dbg.debug();
4456         } else {
4457             if (single_stepping_)
4458                 single_step_callback_(single_step_callback_arg_, this, (void*)program_counter);
4459             SimInstruction* instr = reinterpret_cast<SimInstruction*>(program_counter);
4460             instructionDecode(instr);
4461             icount_++;
4462 
4463             int32_t rpc = resume_pc_;
4464             if (MOZ_UNLIKELY(rpc != 0)) {
4465                 // AsmJS signal handler ran and we have to adjust the pc.
4466                 JSRuntime::innermostAsmJSActivation()->setResumePC((void*)get_pc());
4467                 set_pc(rpc);
4468                 resume_pc_ = 0;
4469             }
4470         }
4471         program_counter = get_pc();
4472     }
4473 
4474     if (single_stepping_)
4475         single_step_callback_(single_step_callback_arg_, this, nullptr);
4476 }
4477 
4478 void
callInternal(uint8_t * entry)4479 Simulator::callInternal(uint8_t* entry)
4480 {
4481     // Prepare to execute the code at entry.
4482     set_register(pc, reinterpret_cast<int32_t>(entry));
4483 
4484     // Put down marker for end of simulation. The simulator will stop simulation
4485     // when the PC reaches this value. By saving the "end simulation" value into
4486     // the LR the simulation stops when returning to this call point.
4487     set_register(lr, end_sim_pc);
4488 
4489     // Remember the values of callee-saved registers. The code below assumes
4490     // that r9 is not used as sb (static base) in simulator code and therefore
4491     // is regarded as a callee-saved register.
4492     int32_t r4_val = get_register(r4);
4493     int32_t r5_val = get_register(r5);
4494     int32_t r6_val = get_register(r6);
4495     int32_t r7_val = get_register(r7);
4496     int32_t r8_val = get_register(r8);
4497     int32_t r9_val = get_register(r9);
4498     int32_t r10_val = get_register(r10);
4499     int32_t r11_val = get_register(r11);
4500 
4501     // Remember d8 to d15 which are callee-saved.
4502     uint64_t d8_val;
4503     get_d_register(d8, &d8_val);
4504     uint64_t d9_val;
4505     get_d_register(d9, &d9_val);
4506     uint64_t d10_val;
4507     get_d_register(d10, &d10_val);
4508     uint64_t d11_val;
4509     get_d_register(d11, &d11_val);
4510     uint64_t d12_val;
4511     get_d_register(d12, &d12_val);
4512     uint64_t d13_val;
4513     get_d_register(d13, &d13_val);
4514     uint64_t d14_val;
4515     get_d_register(d14, &d14_val);
4516     uint64_t d15_val;
4517     get_d_register(d15, &d15_val);
4518 
4519     // Set up the callee-saved registers with a known value. To be able to check
4520     // that they are preserved properly across JS execution.
4521     int32_t callee_saved_value = uint32_t(icount_);
4522     uint64_t callee_saved_value_d = uint64_t(icount_);
4523 
4524     if (!skipCalleeSavedRegsCheck) {
4525         set_register(r4, callee_saved_value);
4526         set_register(r5, callee_saved_value);
4527         set_register(r6, callee_saved_value);
4528         set_register(r7, callee_saved_value);
4529         set_register(r8, callee_saved_value);
4530         set_register(r9, callee_saved_value);
4531         set_register(r10, callee_saved_value);
4532         set_register(r11, callee_saved_value);
4533 
4534         set_d_register(d8, &callee_saved_value_d);
4535         set_d_register(d9, &callee_saved_value_d);
4536         set_d_register(d10, &callee_saved_value_d);
4537         set_d_register(d11, &callee_saved_value_d);
4538         set_d_register(d12, &callee_saved_value_d);
4539         set_d_register(d13, &callee_saved_value_d);
4540         set_d_register(d14, &callee_saved_value_d);
4541         set_d_register(d15, &callee_saved_value_d);
4542 
4543     }
4544     // Start the simulation.
4545     if (Simulator::StopSimAt != -1L)
4546         execute<true>();
4547     else
4548         execute<false>();
4549 
4550     if (!skipCalleeSavedRegsCheck) {
4551         // Check that the callee-saved registers have been preserved.
4552         MOZ_ASSERT(callee_saved_value == get_register(r4));
4553         MOZ_ASSERT(callee_saved_value == get_register(r5));
4554         MOZ_ASSERT(callee_saved_value == get_register(r6));
4555         MOZ_ASSERT(callee_saved_value == get_register(r7));
4556         MOZ_ASSERT(callee_saved_value == get_register(r8));
4557         MOZ_ASSERT(callee_saved_value == get_register(r9));
4558         MOZ_ASSERT(callee_saved_value == get_register(r10));
4559         MOZ_ASSERT(callee_saved_value == get_register(r11));
4560 
4561         uint64_t value;
4562         get_d_register(d8, &value);
4563         MOZ_ASSERT(callee_saved_value_d == value);
4564         get_d_register(d9, &value);
4565         MOZ_ASSERT(callee_saved_value_d == value);
4566         get_d_register(d10, &value);
4567         MOZ_ASSERT(callee_saved_value_d == value);
4568         get_d_register(d11, &value);
4569         MOZ_ASSERT(callee_saved_value_d == value);
4570         get_d_register(d12, &value);
4571         MOZ_ASSERT(callee_saved_value_d == value);
4572         get_d_register(d13, &value);
4573         MOZ_ASSERT(callee_saved_value_d == value);
4574         get_d_register(d14, &value);
4575         MOZ_ASSERT(callee_saved_value_d == value);
4576         get_d_register(d15, &value);
4577         MOZ_ASSERT(callee_saved_value_d == value);
4578 
4579         // Restore callee-saved registers with the original value.
4580         set_register(r4, r4_val);
4581         set_register(r5, r5_val);
4582         set_register(r6, r6_val);
4583         set_register(r7, r7_val);
4584         set_register(r8, r8_val);
4585         set_register(r9, r9_val);
4586         set_register(r10, r10_val);
4587         set_register(r11, r11_val);
4588 
4589         set_d_register(d8, &d8_val);
4590         set_d_register(d9, &d9_val);
4591         set_d_register(d10, &d10_val);
4592         set_d_register(d11, &d11_val);
4593         set_d_register(d12, &d12_val);
4594         set_d_register(d13, &d13_val);
4595         set_d_register(d14, &d14_val);
4596         set_d_register(d15, &d15_val);
4597     }
4598 }
4599 
4600 int32_t
call(uint8_t * entry,int argument_count,...)4601 Simulator::call(uint8_t* entry, int argument_count, ...)
4602 {
4603     va_list parameters;
4604     va_start(parameters, argument_count);
4605 
4606     // First four arguments passed in registers.
4607     MOZ_ASSERT(argument_count >= 1);
4608     set_register(r0, va_arg(parameters, int32_t));
4609     if (argument_count >= 2)
4610         set_register(r1, va_arg(parameters, int32_t));
4611     if (argument_count >= 3)
4612         set_register(r2, va_arg(parameters, int32_t));
4613     if (argument_count >= 4)
4614         set_register(r3, va_arg(parameters, int32_t));
4615 
4616     // Remaining arguments passed on stack.
4617     int original_stack = get_register(sp);
4618     int entry_stack = original_stack;
4619     if (argument_count >= 4)
4620         entry_stack -= (argument_count - 4) * sizeof(int32_t);
4621 
4622     entry_stack &= ~ABIStackAlignment;
4623 
4624     // Store remaining arguments on stack, from low to high memory.
4625     intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
4626     for (int i = 4; i < argument_count; i++)
4627         stack_argument[i - 4] = va_arg(parameters, int32_t);
4628     va_end(parameters);
4629     set_register(sp, entry_stack);
4630 
4631     callInternal(entry);
4632 
4633     // Pop stack passed arguments.
4634     MOZ_ASSERT(entry_stack == get_register(sp));
4635     set_register(sp, original_stack);
4636 
4637     int32_t result = get_register(r0);
4638     return result;
4639 }
4640 
4641 Simulator*
Current()4642 Simulator::Current()
4643 {
4644     return TlsPerThreadData.get()->simulator();
4645 }
4646 
4647 } // namespace jit
4648 } // namespace js
4649 
4650 js::jit::Simulator*
simulator() const4651 JSRuntime::simulator() const
4652 {
4653     return simulator_;
4654 }
4655 
4656 uintptr_t*
addressOfSimulatorStackLimit()4657 JSRuntime::addressOfSimulatorStackLimit()
4658 {
4659     return simulator_->addressOfStackLimit();
4660 }
4661 
4662 js::jit::Simulator*
simulator() const4663 js::PerThreadData::simulator() const
4664 {
4665     return runtime_->simulator();
4666 }
4667