1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jit_arm_MacroAssembler_arm_h
8 #define jit_arm_MacroAssembler_arm_h
9 
10 #include "mozilla/DebugOnly.h"
11 
12 #include "jsopcode.h"
13 
14 #include "jit/arm/Assembler-arm.h"
15 #include "jit/AtomicOp.h"
16 #include "jit/IonCaches.h"
17 #include "jit/JitFrames.h"
18 #include "jit/MoveResolver.h"
19 
20 using mozilla::DebugOnly;
21 
22 namespace js {
23 namespace jit {
24 
25 static Register CallReg = ip;
26 static const int defaultShift = 3;
27 JS_STATIC_ASSERT(1 << defaultShift == sizeof(JS::Value));
28 
29 // MacroAssemblerARM is inheriting form Assembler defined in
30 // Assembler-arm.{h,cpp}
31 class MacroAssemblerARM : public Assembler
32 {
33   private:
34     // Perform a downcast. Should be removed by Bug 996602.
35     MacroAssembler& asMasm();
36     const MacroAssembler& asMasm() const;
37 
38   protected:
39     // On ARM, some instructions require a second scratch register. This
40     // register defaults to lr, since it's non-allocatable (as it can be
41     // clobbered by some instructions). Allow the baseline compiler to override
42     // this though, since baseline IC stubs rely on lr holding the return
43     // address.
44     Register secondScratchReg_;
45 
46   public:
47     // Higher level tag testing code.
48     // TODO: Can probably remove the Operand versions.
ToPayload(Operand base)49     Operand ToPayload(Operand base) const {
50         return Operand(Register::FromCode(base.base()), base.disp());
51     }
ToPayload(const Address & base)52     Address ToPayload(const Address& base) const {
53         return base;
54     }
55 
56   protected:
ToType(Operand base)57     Operand ToType(Operand base) const {
58         return Operand(Register::FromCode(base.base()), base.disp() + sizeof(void*));
59     }
ToType(const Address & base)60     Address ToType(const Address& base) const {
61         return ToType(Operand(base)).toAddress();
62     }
63 
ToPayloadAfterStackPush(const Address & base)64     Address ToPayloadAfterStackPush(const Address& base) const {
65         // If we are based on StackPointer, pass over the type tag just pushed.
66         if (base.base == StackPointer)
67             return Address(base.base, base.offset + sizeof(void *));
68         return ToPayload(base);
69     }
70 
71   public:
MacroAssemblerARM()72     MacroAssemblerARM()
73       : secondScratchReg_(lr)
74     { }
75 
setSecondScratchReg(Register reg)76     void setSecondScratchReg(Register reg) {
77         MOZ_ASSERT(reg != ScratchRegister);
78         secondScratchReg_ = reg;
79     }
80 
81     void convertBoolToInt32(Register source, Register dest);
82     void convertInt32ToDouble(Register src, FloatRegister dest);
83     void convertInt32ToDouble(const Address& src, FloatRegister dest);
84     void convertInt32ToDouble(const BaseIndex& src, FloatRegister dest);
85     void convertUInt32ToFloat32(Register src, FloatRegister dest);
86     void convertUInt32ToDouble(Register src, FloatRegister dest);
87     void convertDoubleToFloat32(FloatRegister src, FloatRegister dest,
88                                 Condition c = Always);
89     void branchTruncateDouble(FloatRegister src, Register dest, Label* fail);
90     void convertDoubleToInt32(FloatRegister src, Register dest, Label* fail,
91                               bool negativeZeroCheck = true);
92     void convertFloat32ToInt32(FloatRegister src, Register dest, Label* fail,
93                                bool negativeZeroCheck = true);
94 
95     void convertFloat32ToDouble(FloatRegister src, FloatRegister dest);
96     void branchTruncateFloat32(FloatRegister src, Register dest, Label* fail);
97     void convertInt32ToFloat32(Register src, FloatRegister dest);
98     void convertInt32ToFloat32(const Address& src, FloatRegister dest);
99 
100     void addDouble(FloatRegister src, FloatRegister dest);
101     void subDouble(FloatRegister src, FloatRegister dest);
102     void mulDouble(FloatRegister src, FloatRegister dest);
103     void divDouble(FloatRegister src, FloatRegister dest);
104 
105     void negateDouble(FloatRegister reg);
106     void inc64(AbsoluteAddress dest);
107 
108     // Somewhat direct wrappers for the low-level assembler funcitons
109     // bitops. Attempt to encode a virtual alu instruction using two real
110     // instructions.
111   private:
112     bool alu_dbl(Register src1, Imm32 imm, Register dest, ALUOp op,
113                  SBit s, Condition c);
114 
115   public:
116     void ma_alu(Register src1, Operand2 op2, Register dest, ALUOp op,
117                 SBit s = LeaveCC, Condition c = Always);
118     void ma_alu(Register src1, Imm32 imm, Register dest,
119                 ALUOp op,
120                 SBit s =  LeaveCC, Condition c = Always);
121 
122     void ma_alu(Register src1, Operand op2, Register dest, ALUOp op,
123                 SBit s = LeaveCC, Condition c = Always);
124     void ma_nop();
125 
126     void ma_movPatchable(Imm32 imm, Register dest, Assembler::Condition c,
127                          RelocStyle rs);
128     void ma_movPatchable(ImmPtr imm, Register dest, Assembler::Condition c,
129                          RelocStyle rs);
130 
131     static void ma_mov_patch(Imm32 imm, Register dest, Assembler::Condition c,
132                              RelocStyle rs, Instruction* i);
133     static void ma_mov_patch(ImmPtr imm, Register dest, Assembler::Condition c,
134                              RelocStyle rs, Instruction* i);
135 
136     // These should likely be wrapped up as a set of macros or something like
137     // that. I cannot think of a good reason to explicitly have all of this
138     // code.
139 
140     // ALU based ops
141     // mov
142     void ma_mov(Register src, Register dest,
143                 SBit s = LeaveCC, Condition c = Always);
144 
145     void ma_mov(Imm32 imm, Register dest,
146                 SBit s = LeaveCC, Condition c = Always);
147     void ma_mov(ImmWord imm, Register dest,
148                 SBit s = LeaveCC, Condition c = Always);
149 
150     void ma_mov(ImmGCPtr ptr, Register dest);
151 
152     // Shifts (just a move with a shifting op2)
153     void ma_lsl(Imm32 shift, Register src, Register dst);
154     void ma_lsr(Imm32 shift, Register src, Register dst);
155     void ma_asr(Imm32 shift, Register src, Register dst);
156     void ma_ror(Imm32 shift, Register src, Register dst);
157     void ma_rol(Imm32 shift, Register src, Register dst);
158     // Shifts (just a move with a shifting op2)
159     void ma_lsl(Register shift, Register src, Register dst);
160     void ma_lsr(Register shift, Register src, Register dst);
161     void ma_asr(Register shift, Register src, Register dst);
162     void ma_ror(Register shift, Register src, Register dst);
163     void ma_rol(Register shift, Register src, Register dst);
164 
165     // Move not (dest <- ~src)
166     void ma_mvn(Imm32 imm, Register dest,
167                 SBit s = LeaveCC, Condition c = Always);
168 
169 
170     void ma_mvn(Register src1, Register dest,
171                 SBit s = LeaveCC, Condition c = Always);
172 
173     // Negate (dest <- -src) implemented as rsb dest, src, 0
174     void ma_neg(Register src, Register dest,
175                 SBit s = LeaveCC, Condition c = Always);
176 
177     // And
178     void ma_and(Register src, Register dest,
179                 SBit s = LeaveCC, Condition c = Always);
180 
181     void ma_and(Register src1, Register src2, Register dest,
182                 SBit s = LeaveCC, Condition c = Always);
183 
184     void ma_and(Imm32 imm, Register dest,
185                 SBit s = LeaveCC, Condition c = Always);
186 
187     void ma_and(Imm32 imm, Register src1, Register dest,
188                 SBit s = LeaveCC, Condition c = Always);
189 
190 
191 
192     // Bit clear (dest <- dest & ~imm) or (dest <- src1 & ~src2)
193     void ma_bic(Imm32 imm, Register dest,
194                 SBit s = LeaveCC, Condition c = Always);
195 
196     // Exclusive or
197     void ma_eor(Register src, Register dest,
198                 SBit s = LeaveCC, Condition c = Always);
199 
200     void ma_eor(Register src1, Register src2, Register dest,
201                 SBit s = LeaveCC, Condition c = Always);
202 
203     void ma_eor(Imm32 imm, Register dest,
204                 SBit s = LeaveCC, Condition c = Always);
205 
206     void ma_eor(Imm32 imm, Register src1, Register dest,
207                 SBit s = LeaveCC, Condition c = Always);
208 
209 
210     // Or
211     void ma_orr(Register src, Register dest,
212                 SBit s = LeaveCC, Condition c = Always);
213 
214     void ma_orr(Register src1, Register src2, Register dest,
215                 SBit s = LeaveCC, Condition c = Always);
216 
217     void ma_orr(Imm32 imm, Register dest,
218                 SBit s = LeaveCC, Condition c = Always);
219 
220     void ma_orr(Imm32 imm, Register src1, Register dest,
221                 SBit s = LeaveCC, Condition c = Always);
222 
223 
224     // Arithmetic based ops.
225     // Add with carry:
226     void ma_adc(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always);
227     void ma_adc(Register src, Register dest, SBit s = LeaveCC, Condition c = Always);
228     void ma_adc(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always);
229 
230     // Add:
231     void ma_add(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always);
232     void ma_add(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always);
233     void ma_add(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always);
234     void ma_add(Register src1, Operand op, Register dest, SBit s = LeaveCC, Condition c = Always);
235     void ma_add(Register src1, Imm32 op, Register dest, SBit s = LeaveCC, Condition c = Always);
236 
237     // Subtract with carry:
238     void ma_sbc(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always);
239     void ma_sbc(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always);
240     void ma_sbc(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always);
241 
242     // Subtract:
243     void ma_sub(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always);
244     void ma_sub(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always);
245     void ma_sub(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always);
246     void ma_sub(Register src1, Operand op, Register dest, SBit s = LeaveCC, Condition c = Always);
247     void ma_sub(Register src1, Imm32 op, Register dest, SBit s = LeaveCC, Condition c = Always);
248 
249     // Reverse subtract:
250     void ma_rsb(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always);
251     void ma_rsb(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always);
252     void ma_rsb(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always);
253     void ma_rsb(Register src1, Imm32 op2, Register dest, SBit s = LeaveCC, Condition c = Always);
254 
255     // Reverse subtract with carry:
256     void ma_rsc(Imm32 imm, Register dest, SBit s = LeaveCC, Condition c = Always);
257     void ma_rsc(Register src1, Register dest, SBit s = LeaveCC, Condition c = Always);
258     void ma_rsc(Register src1, Register src2, Register dest, SBit s = LeaveCC, Condition c = Always);
259 
260     // Compares/tests.
261     // Compare negative (sets condition codes as src1 + src2 would):
262     void ma_cmn(Register src1, Imm32 imm, Condition c = Always);
263     void ma_cmn(Register src1, Register src2, Condition c = Always);
264     void ma_cmn(Register src1, Operand op, Condition c = Always);
265 
266     // Compare (src - src2):
267     void ma_cmp(Register src1, Imm32 imm, Condition c = Always);
268     void ma_cmp(Register src1, ImmWord ptr, Condition c = Always);
269     void ma_cmp(Register src1, ImmGCPtr ptr, Condition c = Always);
270     void ma_cmp(Register src1, Operand op, Condition c = Always);
271     void ma_cmp(Register src1, Register src2, Condition c = Always);
272 
273 
274     // Test for equality, (src1 ^ src2):
275     void ma_teq(Register src1, Imm32 imm, Condition c = Always);
276     void ma_teq(Register src1, Register src2, Condition c = Always);
277     void ma_teq(Register src1, Operand op, Condition c = Always);
278 
279 
280     // Test (src1 & src2):
281     void ma_tst(Register src1, Imm32 imm, Condition c = Always);
282     void ma_tst(Register src1, Register src2, Condition c = Always);
283     void ma_tst(Register src1, Operand op, Condition c = Always);
284 
285     // Multiplies. For now, there are only two that we care about.
286     void ma_mul(Register src1, Register src2, Register dest);
287     void ma_mul(Register src1, Imm32 imm, Register dest);
288     Condition ma_check_mul(Register src1, Register src2, Register dest, Condition cond);
289     Condition ma_check_mul(Register src1, Imm32 imm, Register dest, Condition cond);
290 
291     // Fast mod, uses scratch registers, and thus needs to be in the assembler
292     // implicitly assumes that we can overwrite dest at the beginning of the
293     // sequence.
294     void ma_mod_mask(Register src, Register dest, Register hold, Register tmp,
295                      int32_t shift);
296 
297     // Mod - depends on integer divide instructions being supported.
298     void ma_smod(Register num, Register div, Register dest);
299     void ma_umod(Register num, Register div, Register dest);
300 
301     // Division - depends on integer divide instructions being supported.
302     void ma_sdiv(Register num, Register div, Register dest, Condition cond = Always);
303     void ma_udiv(Register num, Register div, Register dest, Condition cond = Always);
304     // Misc operations
305     void ma_clz(Register src, Register dest, Condition cond = Always);
306     // Memory:
307     // Shortcut for when we know we're transferring 32 bits of data.
308     void ma_dtr(LoadStore ls, Register rn, Imm32 offset, Register rt,
309                 Index mode = Offset, Condition cc = Always);
310 
311     void ma_dtr(LoadStore ls, Register rn, Register rm, Register rt,
312                 Index mode = Offset, Condition cc = Always);
313 
314 
315     void ma_str(Register rt, DTRAddr addr, Index mode = Offset, Condition cc = Always);
316     void ma_str(Register rt, const Address& addr, Index mode = Offset, Condition cc = Always);
317     void ma_dtr(LoadStore ls, Register rt, const Address& addr, Index mode, Condition cc);
318 
319     void ma_ldr(DTRAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
320     void ma_ldr(const Address& addr, Register rt, Index mode = Offset, Condition cc = Always);
321 
322     void ma_ldrb(DTRAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
323     void ma_ldrh(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
324     void ma_ldrsh(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
325     void ma_ldrsb(EDtrAddr addr, Register rt, Index mode = Offset, Condition cc = Always);
326     void ma_ldrd(EDtrAddr addr, Register rt, DebugOnly<Register> rt2, Index mode = Offset, Condition cc = Always);
327     void ma_strb(Register rt, DTRAddr addr, Index mode = Offset, Condition cc = Always);
328     void ma_strh(Register rt, EDtrAddr addr, Index mode = Offset, Condition cc = Always);
329     void ma_strd(Register rt, DebugOnly<Register> rt2, EDtrAddr addr, Index mode = Offset, Condition cc = Always);
330     // Specialty for moving N bits of data, where n == 8,16,32,64.
331     BufferOffset ma_dataTransferN(LoadStore ls, int size, bool IsSigned,
332                           Register rn, Register rm, Register rt,
333                           Index mode = Offset, Condition cc = Always, unsigned scale = TimesOne);
334 
335     BufferOffset ma_dataTransferN(LoadStore ls, int size, bool IsSigned,
336                           Register rn, Imm32 offset, Register rt,
337                           Index mode = Offset, Condition cc = Always);
338     void ma_pop(Register r);
339     void ma_push(Register r);
340 
341     void ma_vpop(VFPRegister r);
342     void ma_vpush(VFPRegister r);
343 
344     // Barriers.
345     void ma_dmb(BarrierOption option=BarrierSY);
346     void ma_dsb(BarrierOption option=BarrierSY);
347 
348     // Branches when done from within arm-specific code.
349     BufferOffset ma_b(Label* dest, Condition c = Always);
350     void ma_b(void* target, Condition c = Always);
351     void ma_bx(Register dest, Condition c = Always);
352 
353     // This is almost NEVER necessary, we'll basically never be calling a label
354     // except, possibly in the crazy bailout-table case.
355     void ma_bl(Label* dest, Condition c = Always);
356 
357     void ma_blx(Register dest, Condition c = Always);
358 
359     // VFP/ALU:
360     void ma_vadd(FloatRegister src1, FloatRegister src2, FloatRegister dst);
361     void ma_vsub(FloatRegister src1, FloatRegister src2, FloatRegister dst);
362 
363     void ma_vmul(FloatRegister src1, FloatRegister src2, FloatRegister dst);
364     void ma_vdiv(FloatRegister src1, FloatRegister src2, FloatRegister dst);
365 
366     void ma_vneg(FloatRegister src, FloatRegister dest, Condition cc = Always);
367     void ma_vmov(FloatRegister src, FloatRegister dest, Condition cc = Always);
368     void ma_vmov_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
369     void ma_vabs(FloatRegister src, FloatRegister dest, Condition cc = Always);
370     void ma_vabs_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
371 
372     void ma_vsqrt(FloatRegister src, FloatRegister dest, Condition cc = Always);
373     void ma_vsqrt_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
374 
375     void ma_vimm(double value, FloatRegister dest, Condition cc = Always);
376     void ma_vimm_f32(float value, FloatRegister dest, Condition cc = Always);
377 
378     void ma_vcmp(FloatRegister src1, FloatRegister src2, Condition cc = Always);
379     void ma_vcmp_f32(FloatRegister src1, FloatRegister src2, Condition cc = Always);
380     void ma_vcmpz(FloatRegister src1, Condition cc = Always);
381     void ma_vcmpz_f32(FloatRegister src1, Condition cc = Always);
382 
383     void ma_vadd_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
384     void ma_vsub_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
385 
386     void ma_vmul_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
387     void ma_vdiv_f32(FloatRegister src1, FloatRegister src2, FloatRegister dst);
388 
389     void ma_vneg_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
390 
391     // Source is F64, dest is I32:
392     void ma_vcvt_F64_I32(FloatRegister src, FloatRegister dest, Condition cc = Always);
393     void ma_vcvt_F64_U32(FloatRegister src, FloatRegister dest, Condition cc = Always);
394 
395     // Source is I32, dest is F64:
396     void ma_vcvt_I32_F64(FloatRegister src, FloatRegister dest, Condition cc = Always);
397     void ma_vcvt_U32_F64(FloatRegister src, FloatRegister dest, Condition cc = Always);
398 
399     // Source is F32, dest is I32:
400     void ma_vcvt_F32_I32(FloatRegister src, FloatRegister dest, Condition cc = Always);
401     void ma_vcvt_F32_U32(FloatRegister src, FloatRegister dest, Condition cc = Always);
402 
403     // Source is I32, dest is F32:
404     void ma_vcvt_I32_F32(FloatRegister src, FloatRegister dest, Condition cc = Always);
405     void ma_vcvt_U32_F32(FloatRegister src, FloatRegister dest, Condition cc = Always);
406 
407 
408     // Transfer (do not coerce) a float into a gpr.
409     void ma_vxfer(VFPRegister src, Register dest, Condition cc = Always);
410     // Transfer (do not coerce) a double into a couple of gpr.
411     void ma_vxfer(VFPRegister src, Register dest1, Register dest2, Condition cc = Always);
412 
413     // Transfer (do not coerce) a gpr into a float
414     void ma_vxfer(Register src, FloatRegister dest, Condition cc = Always);
415     // Transfer (do not coerce) a couple of gpr into a double
416     void ma_vxfer(Register src1, Register src2, FloatRegister dest, Condition cc = Always);
417 
418     BufferOffset ma_vdtr(LoadStore ls, const Address& addr, VFPRegister dest, Condition cc = Always);
419 
420 
421     BufferOffset ma_vldr(VFPAddr addr, VFPRegister dest, Condition cc = Always);
422     BufferOffset ma_vldr(const Address& addr, VFPRegister dest, Condition cc = Always);
423     BufferOffset ma_vldr(VFPRegister src, Register base, Register index, int32_t shift = defaultShift, Condition cc = Always);
424 
425     BufferOffset ma_vstr(VFPRegister src, VFPAddr addr, Condition cc = Always);
426     BufferOffset ma_vstr(VFPRegister src, const Address& addr, Condition cc = Always);
427 
428     BufferOffset ma_vstr(VFPRegister src, Register base, Register index, int32_t shift,
429                          int32_t offset, Condition cc = Always);
430 
431     void ma_call(ImmPtr dest);
432 
433     // Float registers can only be loaded/stored in continuous runs when using
434     // vstm/vldm. This function breaks set into continuous runs and loads/stores
435     // them at [rm]. rm will be modified and left in a state logically suitable
436     // for the next load/store. Returns the offset from [dm] for the logical
437     // next load/store.
transferMultipleByRuns(FloatRegisterSet set,LoadStore ls,Register rm,DTMMode mode)438     int32_t transferMultipleByRuns(FloatRegisterSet set, LoadStore ls,
439                                    Register rm, DTMMode mode)
440     {
441         if (mode == IA) {
442             return transferMultipleByRunsImpl
443                 <FloatRegisterForwardIterator>(set, ls, rm, mode, 1);
444         }
445         if (mode == DB) {
446             return transferMultipleByRunsImpl
447                 <FloatRegisterBackwardIterator>(set, ls, rm, mode, -1);
448         }
449         MOZ_CRASH("Invalid data transfer addressing mode");
450     }
451 
452 private:
453     // Implementation for transferMultipleByRuns so we can use different
454     // iterators for forward/backward traversals. The sign argument should be 1
455     // if we traverse forwards, -1 if we traverse backwards.
456     template<typename RegisterIterator> int32_t
transferMultipleByRunsImpl(FloatRegisterSet set,LoadStore ls,Register rm,DTMMode mode,int32_t sign)457     transferMultipleByRunsImpl(FloatRegisterSet set, LoadStore ls,
458                                Register rm, DTMMode mode, int32_t sign)
459     {
460         MOZ_ASSERT(sign == 1 || sign == -1);
461 
462         int32_t delta = sign * sizeof(float);
463         int32_t offset = 0;
464         // Build up a new set, which is the sum of all of the single and double
465         // registers. This set can have up to 48 registers in it total
466         // s0-s31 and d16-d31
467         FloatRegisterSet mod = set.reduceSetForPush();
468 
469         RegisterIterator iter(mod);
470         while (iter.more()) {
471             startFloatTransferM(ls, rm, mode, WriteBack);
472             int32_t reg = (*iter).code();
473             do {
474                 offset += delta;
475                 if ((*iter).isDouble())
476                     offset += delta;
477                 transferFloatReg(*iter);
478             } while ((++iter).more() && int32_t((*iter).code()) == (reg += sign));
479             finishFloatTransfer();
480         }
481         return offset;
482     }
483 };
484 
485 class MacroAssembler;
486 
487 class MacroAssemblerARMCompat : public MacroAssemblerARM
488 {
489   private:
490     // Perform a downcast. Should be removed by Bug 996602.
491     MacroAssembler& asMasm();
492     const MacroAssembler& asMasm() const;
493 
494   public:
MacroAssemblerARMCompat()495     MacroAssemblerARMCompat()
496     { }
497 
498   public:
499 
500     // Jumps + other functions that should be called from non-arm specific
501     // code. Basically, an x86 front end on top of the ARM code.
j(Condition code,Label * dest)502     void j(Condition code , Label* dest)
503     {
504         as_b(dest, code);
505     }
j(Label * dest)506     void j(Label* dest)
507     {
508         as_b(dest, Always);
509     }
510 
mov(Register src,Register dest)511     void mov(Register src, Register dest) {
512         ma_mov(src, dest);
513     }
mov(ImmWord imm,Register dest)514     void mov(ImmWord imm, Register dest) {
515         ma_mov(Imm32(imm.value), dest);
516     }
mov(ImmPtr imm,Register dest)517     void mov(ImmPtr imm, Register dest) {
518         mov(ImmWord(uintptr_t(imm.value)), dest);
519     }
mov(Register src,Address dest)520     void mov(Register src, Address dest) {
521         MOZ_CRASH("NYI-IC");
522     }
mov(Address src,Register dest)523     void mov(Address src, Register dest) {
524         MOZ_CRASH("NYI-IC");
525     }
526 
branch(JitCode * c)527     void branch(JitCode* c) {
528         BufferOffset bo = m_buffer.nextOffset();
529         addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
530         RelocStyle rs;
531         if (HasMOVWT())
532             rs = L_MOVWT;
533         else
534             rs = L_LDR;
535 
536         ScratchRegisterScope scratch(asMasm());
537         ma_movPatchable(ImmPtr(c->raw()), scratch, Always, rs);
538         ma_bx(scratch);
539     }
branch(const Register reg)540     void branch(const Register reg) {
541         ma_bx(reg);
542     }
nop()543     void nop() {
544         ma_nop();
545     }
shortJumpSizedNop()546     void shortJumpSizedNop() {
547         ma_nop();
548     }
ret()549     void ret() {
550         ma_pop(pc);
551     }
retn(Imm32 n)552     void retn(Imm32 n) {
553         // pc <- [sp]; sp += n
554         ma_dtr(IsLoad, sp, n, pc, PostIndex);
555     }
push(Imm32 imm)556     void push(Imm32 imm) {
557         ScratchRegisterScope scratch(asMasm());
558         ma_mov(imm, scratch);
559         ma_push(scratch);
560     }
push(ImmWord imm)561     void push(ImmWord imm) {
562         push(Imm32(imm.value));
563     }
push(ImmGCPtr imm)564     void push(ImmGCPtr imm) {
565         ScratchRegisterScope scratch(asMasm());
566         ma_mov(imm, scratch);
567         ma_push(scratch);
568     }
push(const Address & addr)569     void push(const Address& addr) {
570         ScratchRegisterScope scratch(asMasm());
571         ma_ldr(addr, scratch);
572         ma_push(scratch);
573     }
push(Register reg)574     void push(Register reg) {
575         ma_push(reg);
576     }
push(FloatRegister reg)577     void push(FloatRegister reg) {
578         ma_vpush(VFPRegister(reg));
579     }
pushWithPadding(Register reg,const Imm32 extraSpace)580     void pushWithPadding(Register reg, const Imm32 extraSpace) {
581         Imm32 totSpace = Imm32(extraSpace.value + 4);
582         ma_dtr(IsStore, sp, totSpace, reg, PreIndex);
583     }
pushWithPadding(Imm32 imm,const Imm32 extraSpace)584     void pushWithPadding(Imm32 imm, const Imm32 extraSpace) {
585         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
586         Imm32 totSpace = Imm32(extraSpace.value + 4);
587         // ma_dtr may need the scratch register to adjust the stack, so use the
588         // second scratch register.
589         ma_mov(imm, scratch2);
590         ma_dtr(IsStore, sp, totSpace, scratch2, PreIndex);
591     }
592 
pop(Register reg)593     void pop(Register reg) {
594         ma_pop(reg);
595     }
pop(FloatRegister reg)596     void pop(FloatRegister reg) {
597         ma_vpop(VFPRegister(reg));
598     }
599 
popN(Register reg,Imm32 extraSpace)600     void popN(Register reg, Imm32 extraSpace) {
601         Imm32 totSpace = Imm32(extraSpace.value + 4);
602         ma_dtr(IsLoad, sp, totSpace, reg, PostIndex);
603     }
604 
605     CodeOffset toggledJump(Label* label);
606 
607     // Emit a BLX or NOP instruction. ToggleCall can be used to patch this
608     // instruction.
609     CodeOffset toggledCall(JitCode* target, bool enabled);
610 
pushWithPatch(ImmWord imm)611     CodeOffset pushWithPatch(ImmWord imm) {
612         ScratchRegisterScope scratch(asMasm());
613         CodeOffset label = movWithPatch(imm, scratch);
614         ma_push(scratch);
615         return label;
616     }
617 
movWithPatch(ImmWord imm,Register dest)618     CodeOffset movWithPatch(ImmWord imm, Register dest) {
619         CodeOffset label = CodeOffset(currentOffset());
620         ma_movPatchable(Imm32(imm.value), dest, Always, HasMOVWT() ? L_MOVWT : L_LDR);
621         return label;
622     }
movWithPatch(ImmPtr imm,Register dest)623     CodeOffset movWithPatch(ImmPtr imm, Register dest) {
624         return movWithPatch(ImmWord(uintptr_t(imm.value)), dest);
625     }
626 
jump(Label * label)627     void jump(Label* label) {
628         as_b(label);
629     }
jump(JitCode * code)630     void jump(JitCode* code) {
631         branch(code);
632     }
jump(Register reg)633     void jump(Register reg) {
634         ma_bx(reg);
635     }
jump(const Address & addr)636     void jump(const Address& addr) {
637         ScratchRegisterScope scratch(asMasm());
638         ma_ldr(addr, scratch);
639         ma_bx(scratch);
640     }
641 
neg32(Register reg)642     void neg32(Register reg) {
643         ma_neg(reg, reg, SetCC);
644     }
negl(Register reg)645     void negl(Register reg) {
646         ma_neg(reg, reg, SetCC);
647     }
test32(Register lhs,Register rhs)648     void test32(Register lhs, Register rhs) {
649         ma_tst(lhs, rhs);
650     }
test32(Register lhs,Imm32 imm)651     void test32(Register lhs, Imm32 imm) {
652         ma_tst(lhs, imm);
653     }
test32(const Address & addr,Imm32 imm)654     void test32(const Address& addr, Imm32 imm) {
655         ScratchRegisterScope scratch(asMasm());
656         ma_ldr(addr, scratch);
657         ma_tst(scratch, imm);
658     }
testPtr(Register lhs,Register rhs)659     void testPtr(Register lhs, Register rhs) {
660         test32(lhs, rhs);
661     }
662 
663     // Returns the register containing the type tag.
splitTagForTest(const ValueOperand & value)664     Register splitTagForTest(const ValueOperand& value) {
665         return value.typeReg();
666     }
667 
668     // Higher level tag testing code.
669     Condition testInt32(Condition cond, const ValueOperand& value);
670     Condition testBoolean(Condition cond, const ValueOperand& value);
671     Condition testDouble(Condition cond, const ValueOperand& value);
672     Condition testNull(Condition cond, const ValueOperand& value);
673     Condition testUndefined(Condition cond, const ValueOperand& value);
674     Condition testString(Condition cond, const ValueOperand& value);
675     Condition testSymbol(Condition cond, const ValueOperand& value);
676     Condition testObject(Condition cond, const ValueOperand& value);
677     Condition testNumber(Condition cond, const ValueOperand& value);
678     Condition testMagic(Condition cond, const ValueOperand& value);
679 
680     Condition testPrimitive(Condition cond, const ValueOperand& value);
681 
682     // Register-based tests.
683     Condition testInt32(Condition cond, Register tag);
684     Condition testBoolean(Condition cond, Register tag);
685     Condition testNull(Condition cond, Register tag);
686     Condition testUndefined(Condition cond, Register tag);
687     Condition testString(Condition cond, Register tag);
688     Condition testSymbol(Condition cond, Register tag);
689     Condition testObject(Condition cond, Register tag);
690     Condition testDouble(Condition cond, Register tag);
691     Condition testNumber(Condition cond, Register tag);
692     Condition testMagic(Condition cond, Register tag);
693     Condition testPrimitive(Condition cond, Register tag);
694 
695     Condition testGCThing(Condition cond, const Address& address);
696     Condition testMagic(Condition cond, const Address& address);
697     Condition testInt32(Condition cond, const Address& address);
698     Condition testDouble(Condition cond, const Address& address);
699     Condition testBoolean(Condition cond, const Address& address);
700     Condition testNull(Condition cond, const Address& address);
701     Condition testUndefined(Condition cond, const Address& address);
702     Condition testString(Condition cond, const Address& address);
703     Condition testSymbol(Condition cond, const Address& address);
704     Condition testObject(Condition cond, const Address& address);
705     Condition testNumber(Condition cond, const Address& address);
706 
707     Condition testUndefined(Condition cond, const BaseIndex& src);
708     Condition testNull(Condition cond, const BaseIndex& src);
709     Condition testBoolean(Condition cond, const BaseIndex& src);
710     Condition testString(Condition cond, const BaseIndex& src);
711     Condition testSymbol(Condition cond, const BaseIndex& src);
712     Condition testInt32(Condition cond, const BaseIndex& src);
713     Condition testObject(Condition cond, const BaseIndex& src);
714     Condition testDouble(Condition cond, const BaseIndex& src);
715     Condition testMagic(Condition cond, const BaseIndex& src);
716     Condition testGCThing(Condition cond, const BaseIndex& src);
717 
718     template <typename T>
branchTestGCThing(Condition cond,const T & t,Label * label)719     void branchTestGCThing(Condition cond, const T& t, Label* label) {
720         Condition c = testGCThing(cond, t);
721         ma_b(label, c);
722     }
723     template <typename T>
branchTestPrimitive(Condition cond,const T & t,Label * label)724     void branchTestPrimitive(Condition cond, const T& t, Label* label) {
725         Condition c = testPrimitive(cond, t);
726         ma_b(label, c);
727     }
728 
729     void branchTestValue(Condition cond, const ValueOperand& value, const Value& v, Label* label);
730     void branchTestValue(Condition cond, const Address& valaddr, const ValueOperand& value,
731                          Label* label);
732 
733     // Unboxing code.
734     void unboxNonDouble(const ValueOperand& operand, Register dest);
735     void unboxNonDouble(const Address& src, Register dest);
736     void unboxNonDouble(const BaseIndex& src, Register dest);
unboxInt32(const ValueOperand & src,Register dest)737     void unboxInt32(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
unboxInt32(const Address & src,Register dest)738     void unboxInt32(const Address& src, Register dest) { unboxNonDouble(src, dest); }
unboxBoolean(const ValueOperand & src,Register dest)739     void unboxBoolean(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
unboxBoolean(const Address & src,Register dest)740     void unboxBoolean(const Address& src, Register dest) { unboxNonDouble(src, dest); }
unboxString(const ValueOperand & src,Register dest)741     void unboxString(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
unboxString(const Address & src,Register dest)742     void unboxString(const Address& src, Register dest) { unboxNonDouble(src, dest); }
unboxSymbol(const ValueOperand & src,Register dest)743     void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
unboxSymbol(const Address & src,Register dest)744     void unboxSymbol(const Address& src, Register dest) { unboxNonDouble(src, dest); }
unboxObject(const ValueOperand & src,Register dest)745     void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
unboxObject(const Address & src,Register dest)746     void unboxObject(const Address& src, Register dest) { unboxNonDouble(src, dest); }
unboxObject(const BaseIndex & src,Register dest)747     void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); }
748     void unboxDouble(const ValueOperand& src, FloatRegister dest);
749     void unboxDouble(const Address& src, FloatRegister dest);
750     void unboxValue(const ValueOperand& src, AnyRegister dest);
751     void unboxPrivate(const ValueOperand& src, Register dest);
752 
notBoolean(const ValueOperand & val)753     void notBoolean(const ValueOperand& val) {
754         ma_eor(Imm32(1), val.payloadReg());
755     }
756 
757     // Boxing code.
758     void boxDouble(FloatRegister src, const ValueOperand& dest);
759     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
760 
761     // Extended unboxing API. If the payload is already in a register, returns
762     // that register. Otherwise, provides a move to the given scratch register,
763     // and returns that.
764     Register extractObject(const Address& address, Register scratch);
extractObject(const ValueOperand & value,Register scratch)765     Register extractObject(const ValueOperand& value, Register scratch) {
766         return value.payloadReg();
767     }
extractInt32(const ValueOperand & value,Register scratch)768     Register extractInt32(const ValueOperand& value, Register scratch) {
769         return value.payloadReg();
770     }
extractBoolean(const ValueOperand & value,Register scratch)771     Register extractBoolean(const ValueOperand& value, Register scratch) {
772         return value.payloadReg();
773     }
774     Register extractTag(const Address& address, Register scratch);
775     Register extractTag(const BaseIndex& address, Register scratch);
extractTag(const ValueOperand & value,Register scratch)776     Register extractTag(const ValueOperand& value, Register scratch) {
777         return value.typeReg();
778     }
779 
780     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
781     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
782     void loadInt32OrDouble(const Address& src, FloatRegister dest);
783     void loadInt32OrDouble(Register base, Register index,
784                            FloatRegister dest, int32_t shift = defaultShift);
785     void loadConstantDouble(double dp, FloatRegister dest);
786     // Treat the value as a boolean, and set condition codes accordingly.
787     Condition testInt32Truthy(bool truthy, const ValueOperand& operand);
788     Condition testBooleanTruthy(bool truthy, const ValueOperand& operand);
789     Condition testDoubleTruthy(bool truthy, FloatRegister reg);
790     Condition testStringTruthy(bool truthy, const ValueOperand& value);
791 
792     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest);
793     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
794     void loadConstantFloat32(float f, FloatRegister dest);
795 
796     template<typename T>
branchTestInt32(Condition cond,const T & t,Label * label)797     void branchTestInt32(Condition cond, const T & t, Label* label) {
798         Condition c = testInt32(cond, t);
799         ma_b(label, c);
800     }
801     template<typename T>
branchTestBoolean(Condition cond,const T & t,Label * label)802     void branchTestBoolean(Condition cond, const T & t, Label* label) {
803         Condition c = testBoolean(cond, t);
804         ma_b(label, c);
805     }
branch32(Condition cond,Register lhs,Register rhs,Label * label)806     void branch32(Condition cond, Register lhs, Register rhs, Label* label) {
807         ma_cmp(lhs, rhs);
808         ma_b(label, cond);
809     }
branch32(Condition cond,Register lhs,Imm32 imm,Label * label)810     void branch32(Condition cond, Register lhs, Imm32 imm, Label* label) {
811         ma_cmp(lhs, imm);
812         ma_b(label, cond);
813     }
branch32(Condition cond,const Operand & lhs,Register rhs,Label * label)814     void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) {
815         if (lhs.getTag() == Operand::OP2) {
816             branch32(cond, lhs.toReg(), rhs, label);
817         } else {
818             ScratchRegisterScope scratch(asMasm());
819             ma_ldr(lhs.toAddress(), scratch);
820             branch32(cond, scratch, rhs, label);
821         }
822     }
branch32(Condition cond,const Operand & lhs,Imm32 rhs,Label * label)823     void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) {
824         if (lhs.getTag() == Operand::OP2) {
825             branch32(cond, lhs.toReg(), rhs, label);
826         } else {
827             // branch32 will use ScratchRegister.
828             AutoRegisterScope scratch(asMasm(), secondScratchReg_);
829             ma_ldr(lhs.toAddress(), scratch);
830             branch32(cond, scratch, rhs, label);
831         }
832     }
branch32(Condition cond,const Address & lhs,Register rhs,Label * label)833     void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) {
834         ScratchRegisterScope scratch(asMasm());
835         load32(lhs, scratch);
836         branch32(cond, scratch, rhs, label);
837     }
branch32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)838     void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) {
839         // branch32 will use ScratchRegister.
840         AutoRegisterScope scratch(asMasm(), secondScratchReg_);
841         load32(lhs, scratch);
842         branch32(cond, scratch, rhs, label);
843     }
branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)844     void branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label) {
845         // branch32 will use ScratchRegister.
846         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
847         load32(lhs, scratch2);
848         branch32(cond, scratch2, rhs, label);
849     }
branchPtr(Condition cond,const Address & lhs,Register rhs,Label * label)850     void branchPtr(Condition cond, const Address& lhs, Register rhs, Label* label) {
851         branch32(cond, lhs, rhs, label);
852     }
853 
branchPrivatePtr(Condition cond,const Address & lhs,ImmPtr ptr,Label * label)854     void branchPrivatePtr(Condition cond, const Address& lhs, ImmPtr ptr, Label* label) {
855         branchPtr(cond, lhs, ptr, label);
856     }
857 
branchPrivatePtr(Condition cond,const Address & lhs,Register ptr,Label * label)858     void branchPrivatePtr(Condition cond, const Address& lhs, Register ptr, Label* label) {
859         branchPtr(cond, lhs, ptr, label);
860     }
861 
branchPrivatePtr(Condition cond,Register lhs,ImmWord ptr,Label * label)862     void branchPrivatePtr(Condition cond, Register lhs, ImmWord ptr, Label* label) {
863         branchPtr(cond, lhs, ptr, label);
864     }
865 
866     template<typename T>
branchTestDouble(Condition cond,const T & t,Label * label)867     void branchTestDouble(Condition cond, const T & t, Label* label) {
868         Condition c = testDouble(cond, t);
869         ma_b(label, c);
870     }
871     template<typename T>
branchTestNull(Condition cond,const T & t,Label * label)872     void branchTestNull(Condition cond, const T & t, Label* label) {
873         Condition c = testNull(cond, t);
874         ma_b(label, c);
875     }
876     template<typename T>
branchTestObject(Condition cond,const T & t,Label * label)877     void branchTestObject(Condition cond, const T & t, Label* label) {
878         Condition c = testObject(cond, t);
879         ma_b(label, c);
880     }
881     template<typename T>
branchTestString(Condition cond,const T & t,Label * label)882     void branchTestString(Condition cond, const T & t, Label* label) {
883         Condition c = testString(cond, t);
884         ma_b(label, c);
885     }
886     template<typename T>
branchTestSymbol(Condition cond,const T & t,Label * label)887     void branchTestSymbol(Condition cond, const T & t, Label* label) {
888         Condition c = testSymbol(cond, t);
889         ma_b(label, c);
890     }
891     template<typename T>
branchTestUndefined(Condition cond,const T & t,Label * label)892     void branchTestUndefined(Condition cond, const T & t, Label* label) {
893         Condition c = testUndefined(cond, t);
894         ma_b(label, c);
895     }
896     template <typename T>
branchTestNumber(Condition cond,const T & t,Label * label)897     void branchTestNumber(Condition cond, const T& t, Label* label) {
898         cond = testNumber(cond, t);
899         ma_b(label, cond);
900     }
901     template <typename T>
branchTestMagic(Condition cond,const T & t,Label * label)902     void branchTestMagic(Condition cond, const T& t, Label* label) {
903         cond = testMagic(cond, t);
904         ma_b(label, cond);
905     }
branchTestMagicValue(Condition cond,const ValueOperand & val,JSWhyMagic why,Label * label)906     void branchTestMagicValue(Condition cond, const ValueOperand& val, JSWhyMagic why,
907                               Label* label) {
908         MOZ_ASSERT(cond == Equal || cond == NotEqual);
909         branchTestValue(cond, val, MagicValue(why), label);
910     }
branchTestInt32Truthy(bool truthy,const ValueOperand & operand,Label * label)911     void branchTestInt32Truthy(bool truthy, const ValueOperand& operand, Label* label) {
912         Condition c = testInt32Truthy(truthy, operand);
913         ma_b(label, c);
914     }
branchTestBooleanTruthy(bool truthy,const ValueOperand & operand,Label * label)915     void branchTestBooleanTruthy(bool truthy, const ValueOperand& operand, Label* label) {
916         Condition c = testBooleanTruthy(truthy, operand);
917         ma_b(label, c);
918     }
branchTestDoubleTruthy(bool truthy,FloatRegister reg,Label * label)919     void branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label) {
920         Condition c = testDoubleTruthy(truthy, reg);
921         ma_b(label, c);
922     }
branchTestStringTruthy(bool truthy,const ValueOperand & value,Label * label)923     void branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label) {
924         Condition c = testStringTruthy(truthy, value);
925         ma_b(label, c);
926     }
branchTest32(Condition cond,Register lhs,Register rhs,Label * label)927     void branchTest32(Condition cond, Register lhs, Register rhs, Label* label) {
928         MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
929         // x86 likes test foo, foo rather than cmp foo, #0.
930         // Convert the former into the latter.
931         if (lhs == rhs && (cond == Zero || cond == NonZero))
932             ma_cmp(lhs, Imm32(0));
933         else
934             ma_tst(lhs, rhs);
935         ma_b(label, cond);
936     }
branchTest32(Condition cond,Register lhs,Imm32 imm,Label * label)937     void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) {
938         MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
939         ma_tst(lhs, imm);
940         ma_b(label, cond);
941     }
branchTest32(Condition cond,const Address & address,Imm32 imm,Label * label)942     void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
943         // branchTest32 will use ScratchRegister.
944         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
945         load32(address, scratch2);
946         branchTest32(cond, scratch2, imm, label);
947     }
branchTest32(Condition cond,AbsoluteAddress address,Imm32 imm,Label * label)948     void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
949         // branchTest32 will use ScratchRegister.
950         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
951         load32(address, scratch2);
952         branchTest32(cond, scratch2, imm, label);
953     }
branchTestPtr(Condition cond,Register lhs,Register rhs,Label * label)954     void branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label) {
955         branchTest32(cond, lhs, rhs, label);
956     }
branchTestPtr(Condition cond,Register lhs,const Imm32 rhs,Label * label)957     void branchTestPtr(Condition cond, Register lhs, const Imm32 rhs, Label* label) {
958         branchTest32(cond, lhs, rhs, label);
959     }
branchTestPtr(Condition cond,const Address & lhs,Imm32 imm,Label * label)960     void branchTestPtr(Condition cond, const Address& lhs, Imm32 imm, Label* label) {
961         branchTest32(cond, lhs, imm, label);
962     }
branchPtr(Condition cond,Register lhs,Register rhs,Label * label)963     void branchPtr(Condition cond, Register lhs, Register rhs, Label* label) {
964         branch32(cond, lhs, rhs, label);
965     }
branchPtr(Condition cond,Register lhs,ImmGCPtr ptr,Label * label)966     void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label* label) {
967         ScratchRegisterScope scratch(asMasm());
968         movePtr(ptr, scratch);
969         branchPtr(cond, lhs, scratch, label);
970     }
branchPtr(Condition cond,Register lhs,ImmWord imm,Label * label)971     void branchPtr(Condition cond, Register lhs, ImmWord imm, Label* label) {
972         branch32(cond, lhs, Imm32(imm.value), label);
973     }
branchPtr(Condition cond,Register lhs,ImmPtr imm,Label * label)974     void branchPtr(Condition cond, Register lhs, ImmPtr imm, Label* label) {
975         branchPtr(cond, lhs, ImmWord(uintptr_t(imm.value)), label);
976     }
branchPtr(Condition cond,Register lhs,wasm::SymbolicAddress imm,Label * label)977     void branchPtr(Condition cond, Register lhs, wasm::SymbolicAddress imm, Label* label) {
978         ScratchRegisterScope scratch(asMasm());
979         movePtr(imm, scratch);
980         branchPtr(cond, lhs, scratch, label);
981     }
branchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)982     void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
983         branch32(cond, lhs, imm, label);
984     }
decBranchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)985     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
986         subPtr(imm, lhs);
987         branch32(cond, lhs, Imm32(0), label);
988     }
989     void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label);
990     void moveValue(const Value& val, Register type, Register data);
991 
992     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond = Always,
993                                  Label* documentation = nullptr);
backedgeJump(RepatchLabel * label,Label * documentation)994     CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation) {
995         return jumpWithPatch(label, Always, documentation);
996     }
997     template <typename T>
branchPtrWithPatch(Condition cond,Register reg,T ptr,RepatchLabel * label)998     CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) {
999         ma_cmp(reg, ptr);
1000         return jumpWithPatch(label, cond);
1001     }
1002     template <typename T>
branchPtrWithPatch(Condition cond,Address addr,T ptr,RepatchLabel * label)1003     CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) {
1004         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1005         ma_ldr(addr, scratch2);
1006         ma_cmp(scratch2, ptr);
1007         return jumpWithPatch(label, cond);
1008     }
branchPtr(Condition cond,Address addr,ImmGCPtr ptr,Label * label)1009     void branchPtr(Condition cond, Address addr, ImmGCPtr ptr, Label* label) {
1010         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1011         ma_ldr(addr, scratch2);
1012         ma_cmp(scratch2, ptr);
1013         ma_b(label, cond);
1014     }
branchPtr(Condition cond,Address addr,ImmWord ptr,Label * label)1015     void branchPtr(Condition cond, Address addr, ImmWord ptr, Label* label) {
1016         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1017         ma_ldr(addr, scratch2);
1018         ma_cmp(scratch2, ptr);
1019         ma_b(label, cond);
1020     }
branchPtr(Condition cond,Address addr,ImmPtr ptr,Label * label)1021     void branchPtr(Condition cond, Address addr, ImmPtr ptr, Label* label) {
1022         branchPtr(cond, addr, ImmWord(uintptr_t(ptr.value)), label);
1023     }
branchPtr(Condition cond,AbsoluteAddress addr,Register ptr,Label * label)1024     void branchPtr(Condition cond, AbsoluteAddress addr, Register ptr, Label* label) {
1025         ScratchRegisterScope scratch(asMasm());
1026         loadPtr(addr, scratch);
1027         ma_cmp(scratch, ptr);
1028         ma_b(label, cond);
1029     }
branchPtr(Condition cond,AbsoluteAddress addr,ImmWord ptr,Label * label)1030     void branchPtr(Condition cond, AbsoluteAddress addr, ImmWord ptr, Label* label) {
1031         ScratchRegisterScope scratch(asMasm());
1032         loadPtr(addr, scratch);
1033         ma_cmp(scratch, ptr);
1034         ma_b(label, cond);
1035     }
branchPtr(Condition cond,wasm::SymbolicAddress addr,Register ptr,Label * label)1036     void branchPtr(Condition cond, wasm::SymbolicAddress addr, Register ptr, Label* label) {
1037         ScratchRegisterScope scratch(asMasm());
1038         loadPtr(addr, scratch);
1039         ma_cmp(scratch, ptr);
1040         ma_b(label, cond);
1041     }
branch32(Condition cond,AbsoluteAddress lhs,Imm32 rhs,Label * label)1042     void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) {
1043         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1044         loadPtr(lhs, scratch2); // ma_cmp will use the scratch register.
1045         ma_cmp(scratch2, rhs);
1046         ma_b(label, cond);
1047     }
branch32(Condition cond,AbsoluteAddress lhs,Register rhs,Label * label)1048     void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label* label) {
1049         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1050         loadPtr(lhs, scratch2); // ma_cmp will use the scratch register.
1051         ma_cmp(scratch2, rhs);
1052         ma_b(label, cond);
1053     }
branch32(Condition cond,wasm::SymbolicAddress addr,Imm32 imm,Label * label)1054     void branch32(Condition cond, wasm::SymbolicAddress addr, Imm32 imm, Label* label) {
1055         ScratchRegisterScope scratch(asMasm());
1056         loadPtr(addr, scratch);
1057         ma_cmp(scratch, imm);
1058         ma_b(label, cond);
1059     }
1060 
loadUnboxedValue(Address address,MIRType type,AnyRegister dest)1061     void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
1062         if (dest.isFloat())
1063             loadInt32OrDouble(address, dest.fpu());
1064         else
1065             ma_ldr(address, dest.gpr());
1066     }
1067 
loadUnboxedValue(BaseIndex address,MIRType type,AnyRegister dest)1068     void loadUnboxedValue(BaseIndex address, MIRType type, AnyRegister dest) {
1069         if (dest.isFloat())
1070             loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale);
1071         else
1072             load32(address, dest.gpr());
1073     }
1074 
1075     template <typename T>
1076     void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest,
1077                            MIRType slotType);
1078 
1079     template <typename T>
storeUnboxedPayload(ValueOperand value,T address,size_t nbytes)1080     void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) {
1081         switch (nbytes) {
1082           case 4:
1083             storePtr(value.payloadReg(), address);
1084             return;
1085           case 1:
1086             store8(value.payloadReg(), address);
1087             return;
1088           default: MOZ_CRASH("Bad payload width");
1089         }
1090     }
1091 
1092     void moveValue(const Value& val, const ValueOperand& dest);
1093 
moveValue(const ValueOperand & src,const ValueOperand & dest)1094     void moveValue(const ValueOperand& src, const ValueOperand& dest) {
1095         Register s0 = src.typeReg(), d0 = dest.typeReg(),
1096                  s1 = src.payloadReg(), d1 = dest.payloadReg();
1097 
1098         // Either one or both of the source registers could be the same as a
1099         // destination register.
1100         if (s1 == d0) {
1101             if (s0 == d1) {
1102                 // If both are, this is just a swap of two registers.
1103                 ScratchRegisterScope scratch(asMasm());
1104                 MOZ_ASSERT(d1 != scratch);
1105                 MOZ_ASSERT(d0 != scratch);
1106                 ma_mov(d1, scratch);
1107                 ma_mov(d0, d1);
1108                 ma_mov(scratch, d0);
1109                 return;
1110             }
1111             // If only one is, copy that source first.
1112             mozilla::Swap(s0, s1);
1113             mozilla::Swap(d0, d1);
1114         }
1115 
1116         if (s0 != d0)
1117             ma_mov(s0, d0);
1118         if (s1 != d1)
1119             ma_mov(s1, d1);
1120     }
1121 
1122     void storeValue(ValueOperand val, const Address& dst);
1123     void storeValue(ValueOperand val, const BaseIndex& dest);
storeValue(JSValueType type,Register reg,BaseIndex dest)1124     void storeValue(JSValueType type, Register reg, BaseIndex dest) {
1125         ScratchRegisterScope scratch(asMasm());
1126         ma_alu(dest.base, lsl(dest.index, dest.scale), scratch, OpAdd);
1127         storeValue(type, reg, Address(scratch, dest.offset));
1128     }
storeValue(JSValueType type,Register reg,Address dest)1129     void storeValue(JSValueType type, Register reg, Address dest) {
1130         ma_str(reg, dest);
1131         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1132         ma_mov(ImmTag(JSVAL_TYPE_TO_TAG(type)), scratch2);
1133         ma_str(scratch2, Address(dest.base, dest.offset + 4));
1134     }
storeValue(const Value & val,const Address & dest)1135     void storeValue(const Value& val, const Address& dest) {
1136         AutoRegisterScope scratch2(asMasm(), secondScratchReg_);
1137         jsval_layout jv = JSVAL_TO_IMPL(val);
1138         ma_mov(Imm32(jv.s.tag), scratch2);
1139         ma_str(scratch2, ToType(dest));
1140         if (val.isMarkable())
1141             ma_mov(ImmGCPtr(reinterpret_cast<gc::Cell*>(val.toGCThing())), scratch2);
1142         else
1143             ma_mov(Imm32(jv.s.payload.i32), scratch2);
1144         ma_str(scratch2, ToPayload(dest));
1145     }
storeValue(const Value & val,BaseIndex dest)1146     void storeValue(const Value& val, BaseIndex dest) {
1147         ScratchRegisterScope scratch(asMasm());
1148         ma_alu(dest.base, lsl(dest.index, dest.scale), scratch, OpAdd);
1149         storeValue(val, Address(scratch, dest.offset));
1150     }
1151 
1152     void loadValue(Address src, ValueOperand val);
loadValue(Operand dest,ValueOperand val)1153     void loadValue(Operand dest, ValueOperand val) {
1154         loadValue(dest.toAddress(), val);
1155     }
1156     void loadValue(const BaseIndex& addr, ValueOperand val);
1157     void tagValue(JSValueType type, Register payload, ValueOperand dest);
1158 
1159     void pushValue(ValueOperand val);
1160     void popValue(ValueOperand val);
pushValue(const Value & val)1161     void pushValue(const Value& val) {
1162         jsval_layout jv = JSVAL_TO_IMPL(val);
1163         push(Imm32(jv.s.tag));
1164         if (val.isMarkable())
1165             push(ImmGCPtr(reinterpret_cast<gc::Cell*>(val.toGCThing())));
1166         else
1167             push(Imm32(jv.s.payload.i32));
1168     }
pushValue(JSValueType type,Register reg)1169     void pushValue(JSValueType type, Register reg) {
1170         push(ImmTag(JSVAL_TYPE_TO_TAG(type)));
1171         ma_push(reg);
1172     }
1173     void pushValue(const Address& addr);
1174 
1175     void storePayload(const Value& val, const Address& dest);
1176     void storePayload(Register src, const Address& dest);
1177     void storePayload(const Value& val, const BaseIndex& dest);
1178     void storePayload(Register src, const BaseIndex& dest);
1179     void storeTypeTag(ImmTag tag, const Address& dest);
1180     void storeTypeTag(ImmTag tag, const BaseIndex& dest);
1181 
1182     void handleFailureWithHandlerTail(void* handler);
1183 
1184     /////////////////////////////////////////////////////////////////
1185     // Common interface.
1186     /////////////////////////////////////////////////////////////////
1187   public:
1188     void add32(Register src, Register dest);
1189     void add32(Imm32 imm, Register dest);
1190     void add32(Imm32 imm, const Address& dest);
1191     template <typename T>
branchAdd32(Condition cond,T src,Register dest,Label * label)1192     void branchAdd32(Condition cond, T src, Register dest, Label* label) {
1193         add32(src, dest);
1194         j(cond, label);
1195     }
1196     template <typename T>
branchSub32(Condition cond,T src,Register dest,Label * label)1197     void branchSub32(Condition cond, T src, Register dest, Label* label) {
1198         ma_sub(src, dest, SetCC);
1199         j(cond, label);
1200     }
1201 
1202     void addPtr(Register src, Register dest);
1203     void addPtr(const Address& src, Register dest);
add64(Imm32 imm,Register64 dest)1204     void add64(Imm32 imm, Register64 dest) {
1205         ma_add(imm, dest.low, SetCC);
1206         ma_adc(Imm32(0), dest.high, LeaveCC);
1207     }
1208     void not32(Register reg);
1209 
1210     void move32(Imm32 imm, Register dest);
1211     void move32(Register src, Register dest);
1212 
1213     void movePtr(Register src, Register dest);
1214     void movePtr(ImmWord imm, Register dest);
1215     void movePtr(ImmPtr imm, Register dest);
1216     void movePtr(wasm::SymbolicAddress imm, Register dest);
1217     void movePtr(ImmGCPtr imm, Register dest);
move64(Register64 src,Register64 dest)1218     void move64(Register64 src, Register64 dest) {
1219         move32(src.low, dest.low);
1220         move32(src.high, dest.high);
1221     }
1222 
1223     void load8SignExtend(const Address& address, Register dest);
1224     void load8SignExtend(const BaseIndex& src, Register dest);
1225 
1226     void load8ZeroExtend(const Address& address, Register dest);
1227     void load8ZeroExtend(const BaseIndex& src, Register dest);
1228 
1229     void load16SignExtend(const Address& address, Register dest);
1230     void load16SignExtend(const BaseIndex& src, Register dest);
1231 
1232     void load16ZeroExtend(const Address& address, Register dest);
1233     void load16ZeroExtend(const BaseIndex& src, Register dest);
1234 
1235     void load32(const Address& address, Register dest);
1236     void load32(const BaseIndex& address, Register dest);
1237     void load32(AbsoluteAddress address, Register dest);
load64(const Address & address,Register64 dest)1238     void load64(const Address& address, Register64 dest) {
1239         load32(address, dest.low);
1240         load32(Address(address.base, address.offset + 4), dest.high);
1241     }
1242 
1243     void loadPtr(const Address& address, Register dest);
1244     void loadPtr(const BaseIndex& src, Register dest);
1245     void loadPtr(AbsoluteAddress address, Register dest);
1246     void loadPtr(wasm::SymbolicAddress address, Register dest);
1247 
branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)1248     void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) {
1249         MOZ_ASSERT(cond == Assembler::NotEqual,
1250                    "other condition codes not supported");
1251 
1252         branch32(cond, lhs, val.firstHalf(), label);
1253         branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), val.secondHalf(), label);
1254     }
1255 
branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)1256     void branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch,
1257                   Label* label)
1258     {
1259         MOZ_ASSERT(cond == Assembler::NotEqual,
1260                    "other condition codes not supported");
1261         MOZ_ASSERT(lhs.base != scratch);
1262         MOZ_ASSERT(rhs.base != scratch);
1263 
1264         load32(rhs, scratch);
1265         branch32(cond, lhs, scratch, label);
1266 
1267         load32(Address(rhs.base, rhs.offset + sizeof(uint32_t)), scratch);
1268         branch32(cond, Address(lhs.base, lhs.offset + sizeof(uint32_t)), scratch, label);
1269     }
1270 
1271     void loadPrivate(const Address& address, Register dest);
1272 
loadInt32x1(const Address & addr,FloatRegister dest)1273     void loadInt32x1(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x1(const BaseIndex & addr,FloatRegister dest)1274     void loadInt32x1(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x2(const Address & addr,FloatRegister dest)1275     void loadInt32x2(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x2(const BaseIndex & addr,FloatRegister dest)1276     void loadInt32x2(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x3(const Address & src,FloatRegister dest)1277     void loadInt32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x3(const BaseIndex & src,FloatRegister dest)1278     void loadInt32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeInt32x1(FloatRegister src,const Address & dest)1279     void storeInt32x1(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeInt32x1(FloatRegister src,const BaseIndex & dest)1280     void storeInt32x1(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
storeInt32x2(FloatRegister src,const Address & dest)1281     void storeInt32x2(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeInt32x2(FloatRegister src,const BaseIndex & dest)1282     void storeInt32x2(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
storeInt32x3(FloatRegister src,const Address & dest)1283     void storeInt32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeInt32x3(FloatRegister src,const BaseIndex & dest)1284     void storeInt32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
loadAlignedInt32x4(const Address & addr,FloatRegister dest)1285     void loadAlignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeAlignedInt32x4(FloatRegister src,Address addr)1286     void storeAlignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
loadUnalignedInt32x4(const Address & addr,FloatRegister dest)1287     void loadUnalignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadUnalignedInt32x4(const BaseIndex & addr,FloatRegister dest)1288     void loadUnalignedInt32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeUnalignedInt32x4(FloatRegister src,Address addr)1289     void storeUnalignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
storeUnalignedInt32x4(FloatRegister src,BaseIndex addr)1290     void storeUnalignedInt32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); }
1291 
loadFloat32x3(const Address & src,FloatRegister dest)1292     void loadFloat32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadFloat32x3(const BaseIndex & src,FloatRegister dest)1293     void loadFloat32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeFloat32x3(FloatRegister src,const Address & dest)1294     void storeFloat32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeFloat32x3(FloatRegister src,const BaseIndex & dest)1295     void storeFloat32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
loadAlignedFloat32x4(const Address & addr,FloatRegister dest)1296     void loadAlignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeAlignedFloat32x4(FloatRegister src,Address addr)1297     void storeAlignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
loadUnalignedFloat32x4(const Address & addr,FloatRegister dest)1298     void loadUnalignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadUnalignedFloat32x4(const BaseIndex & addr,FloatRegister dest)1299     void loadUnalignedFloat32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeUnalignedFloat32x4(FloatRegister src,Address addr)1300     void storeUnalignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
storeUnalignedFloat32x4(FloatRegister src,BaseIndex addr)1301     void storeUnalignedFloat32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); }
1302 
1303     void loadDouble(const Address& addr, FloatRegister dest);
1304     void loadDouble(const BaseIndex& src, FloatRegister dest);
1305 
1306     // Load a float value into a register, then expand it to a double.
1307     void loadFloatAsDouble(const Address& addr, FloatRegister dest);
1308     void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest);
1309 
1310     void loadFloat32(const Address& addr, FloatRegister dest);
1311     void loadFloat32(const BaseIndex& src, FloatRegister dest);
1312 
1313     void store8(Register src, const Address& address);
1314     void store8(Imm32 imm, const Address& address);
1315     void store8(Register src, const BaseIndex& address);
1316     void store8(Imm32 imm, const BaseIndex& address);
1317 
1318     void store16(Register src, const Address& address);
1319     void store16(Imm32 imm, const Address& address);
1320     void store16(Register src, const BaseIndex& address);
1321     void store16(Imm32 imm, const BaseIndex& address);
1322 
1323     void store32(Register src, AbsoluteAddress address);
1324     void store32(Register src, const Address& address);
1325     void store32(Register src, const BaseIndex& address);
1326     void store32(Imm32 src, const Address& address);
1327     void store32(Imm32 src, const BaseIndex& address);
1328 
1329     void store32_NoSecondScratch(Imm32 src, const Address& address);
1330 
store64(Register64 src,Address address)1331     void store64(Register64 src, Address address) {
1332         store32(src.low, address);
1333         store32(src.high, Address(address.base, address.offset + 4));
1334     }
1335 
1336     template <typename T> void storePtr(ImmWord imm, T address);
1337     template <typename T> void storePtr(ImmPtr imm, T address);
1338     template <typename T> void storePtr(ImmGCPtr imm, T address);
1339     void storePtr(Register src, const Address& address);
1340     void storePtr(Register src, const BaseIndex& address);
1341     void storePtr(Register src, AbsoluteAddress dest);
storeDouble(FloatRegister src,Address addr)1342     void storeDouble(FloatRegister src, Address addr) {
1343         ma_vstr(src, addr);
1344     }
storeDouble(FloatRegister src,BaseIndex addr)1345     void storeDouble(FloatRegister src, BaseIndex addr) {
1346         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
1347         ma_vstr(src, addr.base, addr.index, scale, addr.offset);
1348     }
moveDouble(FloatRegister src,FloatRegister dest)1349     void moveDouble(FloatRegister src, FloatRegister dest) {
1350         ma_vmov(src, dest);
1351     }
1352 
storeFloat32(FloatRegister src,const Address & addr)1353     void storeFloat32(FloatRegister src, const Address& addr) {
1354         ma_vstr(VFPRegister(src).singleOverlay(), addr);
1355     }
storeFloat32(FloatRegister src,const BaseIndex & addr)1356     void storeFloat32(FloatRegister src, const BaseIndex& addr) {
1357         uint32_t scale = Imm32::ShiftOf(addr.scale).value;
1358         ma_vstr(VFPRegister(src).singleOverlay(), addr.base, addr.index, scale, addr.offset);
1359     }
1360 
1361   private:
1362     template<typename T>
1363     Register computePointer(const T& src, Register r);
1364 
1365     template<typename T>
1366     void compareExchangeARMv6(int nbytes, bool signExtend, const T& mem, Register oldval,
1367                               Register newval, Register output);
1368 
1369     template<typename T>
1370     void compareExchangeARMv7(int nbytes, bool signExtend, const T& mem, Register oldval,
1371                               Register newval, Register output);
1372 
1373     template<typename T>
1374     void compareExchange(int nbytes, bool signExtend, const T& address, Register oldval,
1375                          Register newval, Register output);
1376 
1377     template<typename T>
1378     void atomicExchangeARMv6(int nbytes, bool signExtend, const T& mem, Register value,
1379                              Register output);
1380 
1381     template<typename T>
1382     void atomicExchangeARMv7(int nbytes, bool signExtend, const T& mem, Register value,
1383                              Register output);
1384 
1385     template<typename T>
1386     void atomicExchange(int nbytes, bool signExtend, const T& address, Register value,
1387                         Register output);
1388 
1389     template<typename T>
1390     void atomicFetchOpARMv6(int nbytes, bool signExtend, AtomicOp op, const Register& value,
1391                             const T& mem, Register flagTemp, Register output);
1392 
1393     template<typename T>
1394     void atomicFetchOpARMv7(int nbytes, bool signExtend, AtomicOp op, const Register& value,
1395                             const T& mem, Register flagTemp, Register output);
1396 
1397     template<typename T>
1398     void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Imm32& value,
1399                        const T& address, Register flagTemp, Register output);
1400 
1401     template<typename T>
1402     void atomicFetchOp(int nbytes, bool signExtend, AtomicOp op, const Register& value,
1403                        const T& address, Register flagTemp, Register output);
1404 
1405     template<typename T>
1406     void atomicEffectOpARMv6(int nbytes, AtomicOp op, const Register& value, const T& address,
1407                              Register flagTemp);
1408 
1409     template<typename T>
1410     void atomicEffectOpARMv7(int nbytes, AtomicOp op, const Register& value, const T& address,
1411                              Register flagTemp);
1412 
1413     template<typename T>
1414     void atomicEffectOp(int nbytes, AtomicOp op, const Imm32& value, const T& address,
1415                              Register flagTemp);
1416 
1417     template<typename T>
1418     void atomicEffectOp(int nbytes, AtomicOp op, const Register& value, const T& address,
1419                              Register flagTemp);
1420 
1421   public:
1422     // T in {Address,BaseIndex}
1423     // S in {Imm32,Register}
1424 
1425     template<typename T>
compareExchange8SignExtend(const T & mem,Register oldval,Register newval,Register output)1426     void compareExchange8SignExtend(const T& mem, Register oldval, Register newval, Register output)
1427     {
1428         compareExchange(1, true, mem, oldval, newval, output);
1429     }
1430     template<typename T>
compareExchange8ZeroExtend(const T & mem,Register oldval,Register newval,Register output)1431     void compareExchange8ZeroExtend(const T& mem, Register oldval, Register newval, Register output)
1432     {
1433         compareExchange(1, false, mem, oldval, newval, output);
1434     }
1435     template<typename T>
compareExchange16SignExtend(const T & mem,Register oldval,Register newval,Register output)1436     void compareExchange16SignExtend(const T& mem, Register oldval, Register newval, Register output)
1437     {
1438         compareExchange(2, true, mem, oldval, newval, output);
1439     }
1440     template<typename T>
compareExchange16ZeroExtend(const T & mem,Register oldval,Register newval,Register output)1441     void compareExchange16ZeroExtend(const T& mem, Register oldval, Register newval, Register output)
1442     {
1443         compareExchange(2, false, mem, oldval, newval, output);
1444     }
1445     template<typename T>
compareExchange32(const T & mem,Register oldval,Register newval,Register output)1446     void compareExchange32(const T& mem, Register oldval, Register newval, Register output)  {
1447         compareExchange(4, false, mem, oldval, newval, output);
1448     }
1449 
1450     template<typename T>
atomicExchange8SignExtend(const T & mem,Register value,Register output)1451     void atomicExchange8SignExtend(const T& mem, Register value, Register output)
1452     {
1453         atomicExchange(1, true, mem, value, output);
1454     }
1455     template<typename T>
atomicExchange8ZeroExtend(const T & mem,Register value,Register output)1456     void atomicExchange8ZeroExtend(const T& mem, Register value, Register output)
1457     {
1458         atomicExchange(1, false, mem, value, output);
1459     }
1460     template<typename T>
atomicExchange16SignExtend(const T & mem,Register value,Register output)1461     void atomicExchange16SignExtend(const T& mem, Register value, Register output)
1462     {
1463         atomicExchange(2, true, mem, value, output);
1464     }
1465     template<typename T>
atomicExchange16ZeroExtend(const T & mem,Register value,Register output)1466     void atomicExchange16ZeroExtend(const T& mem, Register value, Register output)
1467     {
1468         atomicExchange(2, false, mem, value, output);
1469     }
1470     template<typename T>
atomicExchange32(const T & mem,Register value,Register output)1471     void atomicExchange32(const T& mem, Register value, Register output) {
1472         atomicExchange(4, false, mem, value, output);
1473     }
1474 
1475     template<typename T, typename S>
atomicFetchAdd8SignExtend(const S & value,const T & mem,Register temp,Register output)1476     void atomicFetchAdd8SignExtend(const S& value, const T& mem, Register temp, Register output) {
1477         atomicFetchOp(1, true, AtomicFetchAddOp, value, mem, temp, output);
1478     }
1479     template<typename T, typename S>
atomicFetchAdd8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1480     void atomicFetchAdd8ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1481         atomicFetchOp(1, false, AtomicFetchAddOp, value, mem, temp, output);
1482     }
1483     template<typename T, typename S>
atomicFetchAdd16SignExtend(const S & value,const T & mem,Register temp,Register output)1484     void atomicFetchAdd16SignExtend(const S& value, const T& mem, Register temp, Register output) {
1485         atomicFetchOp(2, true, AtomicFetchAddOp, value, mem, temp, output);
1486     }
1487     template<typename T, typename S>
atomicFetchAdd16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1488     void atomicFetchAdd16ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1489         atomicFetchOp(2, false, AtomicFetchAddOp, value, mem, temp, output);
1490     }
1491     template<typename T, typename S>
atomicFetchAdd32(const S & value,const T & mem,Register temp,Register output)1492     void atomicFetchAdd32(const S& value, const T& mem, Register temp, Register output) {
1493         atomicFetchOp(4, false, AtomicFetchAddOp, value, mem, temp, output);
1494     }
1495     template <typename T, typename S>
atomicAdd8(const S & value,const T & mem,Register flagTemp)1496     void atomicAdd8(const S& value, const T& mem, Register flagTemp) {
1497         atomicEffectOp(1, AtomicFetchAddOp, value, mem, flagTemp);
1498     }
1499     template <typename T, typename S>
atomicAdd16(const S & value,const T & mem,Register flagTemp)1500     void atomicAdd16(const S& value, const T& mem, Register flagTemp) {
1501         atomicEffectOp(2, AtomicFetchAddOp, value, mem, flagTemp);
1502     }
1503     template <typename T, typename S>
atomicAdd32(const S & value,const T & mem,Register flagTemp)1504     void atomicAdd32(const S& value, const T& mem, Register flagTemp) {
1505         atomicEffectOp(4, AtomicFetchAddOp, value, mem, flagTemp);
1506     }
1507 
1508     template<typename T, typename S>
atomicFetchSub8SignExtend(const S & value,const T & mem,Register temp,Register output)1509     void atomicFetchSub8SignExtend(const S& value, const T& mem, Register temp, Register output) {
1510         atomicFetchOp(1, true, AtomicFetchSubOp, value, mem, temp, output);
1511     }
1512     template<typename T, typename S>
atomicFetchSub8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1513     void atomicFetchSub8ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1514         atomicFetchOp(1, false, AtomicFetchSubOp, value, mem, temp, output);
1515     }
1516     template<typename T, typename S>
atomicFetchSub16SignExtend(const S & value,const T & mem,Register temp,Register output)1517     void atomicFetchSub16SignExtend(const S& value, const T& mem, Register temp, Register output) {
1518         atomicFetchOp(2, true, AtomicFetchSubOp, value, mem, temp, output);
1519     }
1520     template<typename T, typename S>
atomicFetchSub16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1521     void atomicFetchSub16ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1522         atomicFetchOp(2, false, AtomicFetchSubOp, value, mem, temp, output);
1523     }
1524     template<typename T, typename S>
atomicFetchSub32(const S & value,const T & mem,Register temp,Register output)1525     void atomicFetchSub32(const S& value, const T& mem, Register temp, Register output) {
1526         atomicFetchOp(4, false, AtomicFetchSubOp, value, mem, temp, output);
1527     }
1528     template <typename T, typename S>
atomicSub8(const S & value,const T & mem,Register flagTemp)1529     void atomicSub8(const S& value, const T& mem, Register flagTemp) {
1530         atomicEffectOp(1, AtomicFetchSubOp, value, mem, flagTemp);
1531     }
1532     template <typename T, typename S>
atomicSub16(const S & value,const T & mem,Register flagTemp)1533     void atomicSub16(const S& value, const T& mem, Register flagTemp) {
1534         atomicEffectOp(2, AtomicFetchSubOp, value, mem, flagTemp);
1535     }
1536     template <typename T, typename S>
atomicSub32(const S & value,const T & mem,Register flagTemp)1537     void atomicSub32(const S& value, const T& mem, Register flagTemp) {
1538         atomicEffectOp(4, AtomicFetchSubOp, value, mem, flagTemp);
1539     }
1540 
1541     template<typename T, typename S>
atomicFetchAnd8SignExtend(const S & value,const T & mem,Register temp,Register output)1542     void atomicFetchAnd8SignExtend(const S& value, const T& mem, Register temp, Register output) {
1543         atomicFetchOp(1, true, AtomicFetchAndOp, value, mem, temp, output);
1544     }
1545     template<typename T, typename S>
atomicFetchAnd8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1546     void atomicFetchAnd8ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1547         atomicFetchOp(1, false, AtomicFetchAndOp, value, mem, temp, output);
1548     }
1549     template<typename T, typename S>
atomicFetchAnd16SignExtend(const S & value,const T & mem,Register temp,Register output)1550     void atomicFetchAnd16SignExtend(const S& value, const T& mem, Register temp, Register output) {
1551         atomicFetchOp(2, true, AtomicFetchAndOp, value, mem, temp, output);
1552     }
1553     template<typename T, typename S>
atomicFetchAnd16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1554     void atomicFetchAnd16ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1555         atomicFetchOp(2, false, AtomicFetchAndOp, value, mem, temp, output);
1556     }
1557     template<typename T, typename S>
atomicFetchAnd32(const S & value,const T & mem,Register temp,Register output)1558     void atomicFetchAnd32(const S& value, const T& mem, Register temp, Register output) {
1559         atomicFetchOp(4, false, AtomicFetchAndOp, value, mem, temp, output);
1560     }
1561     template <typename T, typename S>
atomicAnd8(const S & value,const T & mem,Register flagTemp)1562     void atomicAnd8(const S& value, const T& mem, Register flagTemp) {
1563         atomicEffectOp(1, AtomicFetchAndOp, value, mem, flagTemp);
1564     }
1565     template <typename T, typename S>
atomicAnd16(const S & value,const T & mem,Register flagTemp)1566     void atomicAnd16(const S& value, const T& mem, Register flagTemp) {
1567         atomicEffectOp(2, AtomicFetchAndOp, value, mem, flagTemp);
1568     }
1569     template <typename T, typename S>
atomicAnd32(const S & value,const T & mem,Register flagTemp)1570     void atomicAnd32(const S& value, const T& mem, Register flagTemp) {
1571         atomicEffectOp(4, AtomicFetchAndOp, value, mem, flagTemp);
1572     }
1573 
1574     template<typename T, typename S>
atomicFetchOr8SignExtend(const S & value,const T & mem,Register temp,Register output)1575     void atomicFetchOr8SignExtend(const S& value, const T& mem, Register temp, Register output) {
1576         atomicFetchOp(1, true, AtomicFetchOrOp, value, mem, temp, output);
1577     }
1578     template<typename T, typename S>
atomicFetchOr8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1579     void atomicFetchOr8ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1580         atomicFetchOp(1, false, AtomicFetchOrOp, value, mem, temp, output);
1581     }
1582     template<typename T, typename S>
atomicFetchOr16SignExtend(const S & value,const T & mem,Register temp,Register output)1583     void atomicFetchOr16SignExtend(const S& value, const T& mem, Register temp, Register output) {
1584         atomicFetchOp(2, true, AtomicFetchOrOp, value, mem, temp, output);
1585     }
1586     template<typename T, typename S>
atomicFetchOr16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1587     void atomicFetchOr16ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1588         atomicFetchOp(2, false, AtomicFetchOrOp, value, mem, temp, output);
1589     }
1590     template<typename T, typename S>
atomicFetchOr32(const S & value,const T & mem,Register temp,Register output)1591     void atomicFetchOr32(const S& value, const T& mem, Register temp, Register output) {
1592         atomicFetchOp(4, false, AtomicFetchOrOp, value, mem, temp, output);
1593     }
1594     template <typename T, typename S>
atomicOr8(const S & value,const T & mem,Register flagTemp)1595     void atomicOr8(const S& value, const T& mem, Register flagTemp) {
1596         atomicEffectOp(1, AtomicFetchOrOp, value, mem, flagTemp);
1597     }
1598     template <typename T, typename S>
atomicOr16(const S & value,const T & mem,Register flagTemp)1599     void atomicOr16(const S& value, const T& mem, Register flagTemp) {
1600         atomicEffectOp(2, AtomicFetchOrOp, value, mem, flagTemp);
1601     }
1602     template <typename T, typename S>
atomicOr32(const S & value,const T & mem,Register flagTemp)1603     void atomicOr32(const S& value, const T& mem, Register flagTemp) {
1604         atomicEffectOp(4, AtomicFetchOrOp, value, mem, flagTemp);
1605     }
1606 
1607     template<typename T, typename S>
atomicFetchXor8SignExtend(const S & value,const T & mem,Register temp,Register output)1608     void atomicFetchXor8SignExtend(const S& value, const T& mem, Register temp, Register output) {
1609         atomicFetchOp(1, true, AtomicFetchXorOp, value, mem, temp, output);
1610     }
1611     template<typename T, typename S>
atomicFetchXor8ZeroExtend(const S & value,const T & mem,Register temp,Register output)1612     void atomicFetchXor8ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1613         atomicFetchOp(1, false, AtomicFetchXorOp, value, mem, temp, output);
1614     }
1615     template<typename T, typename S>
atomicFetchXor16SignExtend(const S & value,const T & mem,Register temp,Register output)1616     void atomicFetchXor16SignExtend(const S& value, const T& mem, Register temp, Register output) {
1617         atomicFetchOp(2, true, AtomicFetchXorOp, value, mem, temp, output);
1618     }
1619     template<typename T, typename S>
atomicFetchXor16ZeroExtend(const S & value,const T & mem,Register temp,Register output)1620     void atomicFetchXor16ZeroExtend(const S& value, const T& mem, Register temp, Register output) {
1621         atomicFetchOp(2, false, AtomicFetchXorOp, value, mem, temp, output);
1622     }
1623     template<typename T, typename S>
atomicFetchXor32(const S & value,const T & mem,Register temp,Register output)1624     void atomicFetchXor32(const S& value, const T& mem, Register temp, Register output) {
1625         atomicFetchOp(4, false, AtomicFetchXorOp, value, mem, temp, output);
1626     }
1627     template <typename T, typename S>
atomicXor8(const S & value,const T & mem,Register flagTemp)1628     void atomicXor8(const S& value, const T& mem, Register flagTemp) {
1629         atomicEffectOp(1, AtomicFetchXorOp, value, mem, flagTemp);
1630     }
1631     template <typename T, typename S>
atomicXor16(const S & value,const T & mem,Register flagTemp)1632     void atomicXor16(const S& value, const T& mem, Register flagTemp) {
1633         atomicEffectOp(2, AtomicFetchXorOp, value, mem, flagTemp);
1634     }
1635     template <typename T, typename S>
atomicXor32(const S & value,const T & mem,Register flagTemp)1636     void atomicXor32(const S& value, const T& mem, Register flagTemp) {
1637         atomicEffectOp(4, AtomicFetchXorOp, value, mem, flagTemp);
1638     }
1639 
1640     template<typename T>
1641     void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register oldval, Register newval,
1642                                         Register temp, AnyRegister output);
1643 
1644     template<typename T>
1645     void atomicExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register value,
1646                                        Register temp, AnyRegister output);
1647 
clampIntToUint8(Register reg)1648     void clampIntToUint8(Register reg) {
1649         // Look at (reg >> 8) if it is 0, then reg shouldn't be clamped if it is
1650         // <0, then we want to clamp to 0, otherwise, we wish to clamp to 255
1651         ScratchRegisterScope scratch(asMasm());
1652         as_mov(scratch, asr(reg, 8), SetCC);
1653         ma_mov(Imm32(0xff), reg, LeaveCC, NotEqual);
1654         ma_mov(Imm32(0), reg, LeaveCC, Signed);
1655     }
1656 
incrementInt32Value(const Address & addr)1657     void incrementInt32Value(const Address& addr) {
1658         add32(Imm32(1), ToPayload(addr));
1659     }
1660 
1661     void cmp32(Register lhs, Imm32 rhs);
1662     void cmp32(Register lhs, Register rhs);
1663     void cmp32(const Operand& lhs, Imm32 rhs);
1664     void cmp32(const Operand& lhs, Register rhs);
1665 
1666     void cmpPtr(Register lhs, Register rhs);
1667     void cmpPtr(Register lhs, ImmWord rhs);
1668     void cmpPtr(Register lhs, ImmPtr rhs);
1669     void cmpPtr(Register lhs, ImmGCPtr rhs);
1670     void cmpPtr(Register lhs, Imm32 rhs);
1671     void cmpPtr(const Address& lhs, Register rhs);
1672     void cmpPtr(const Address& lhs, ImmWord rhs);
1673     void cmpPtr(const Address& lhs, ImmPtr rhs);
1674     void cmpPtr(const Address& lhs, ImmGCPtr rhs);
1675     void cmpPtr(const Address& lhs, Imm32 rhs);
1676 
1677     void subPtr(Imm32 imm, const Register dest);
1678     void subPtr(const Address& addr, const Register dest);
1679     void subPtr(Register src, Register dest);
1680     void subPtr(Register src, const Address& dest);
1681     void addPtr(Imm32 imm, const Register dest);
1682     void addPtr(Imm32 imm, const Address& dest);
addPtr(ImmWord imm,const Register dest)1683     void addPtr(ImmWord imm, const Register dest) {
1684         addPtr(Imm32(imm.value), dest);
1685     }
addPtr(ImmPtr imm,const Register dest)1686     void addPtr(ImmPtr imm, const Register dest) {
1687         addPtr(ImmWord(uintptr_t(imm.value)), dest);
1688     }
mulBy3(const Register & src,const Register & dest)1689     void mulBy3(const Register& src, const Register& dest) {
1690         as_add(dest, src, lsl(src, 1));
1691     }
mul64(Imm64 imm,const Register64 & dest)1692     void mul64(Imm64 imm, const Register64& dest) {
1693         // LOW32  = LOW(LOW(dest) * LOW(imm));
1694         // HIGH32 = LOW(HIGH(dest) * LOW(imm)) [multiply imm into upper bits]
1695         //        + LOW(LOW(dest) * HIGH(imm)) [multiply dest into upper bits]
1696         //        + HIGH(LOW(dest) * LOW(imm)) [carry]
1697 
1698         // HIGH(dest) = LOW(HIGH(dest) * LOW(imm));
1699         ma_mov(Imm32(imm.value & 0xFFFFFFFFL), ScratchRegister);
1700         as_mul(dest.high, dest.high, ScratchRegister);
1701 
1702         // high:low = LOW(dest) * LOW(imm);
1703         as_umull(secondScratchReg_, ScratchRegister, dest.low, ScratchRegister);
1704 
1705         // HIGH(dest) += high;
1706         as_add(dest.high, dest.high, O2Reg(secondScratchReg_));
1707 
1708         // HIGH(dest) += LOW(LOW(dest) * HIGH(imm));
1709         if (((imm.value >> 32) & 0xFFFFFFFFL) == 5)
1710             as_add(secondScratchReg_, dest.low, lsl(dest.low, 2));
1711         else
1712             MOZ_CRASH("Not supported imm");
1713         as_add(dest.high, dest.high, O2Reg(secondScratchReg_));
1714 
1715         // LOW(dest) = low;
1716         ma_mov(ScratchRegister, dest.low);
1717     }
1718 
1719     void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)1720     void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
1721         movePtr(imm, ScratchRegister);
1722         loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
1723         mulDouble(ScratchDoubleReg, dest);
1724     }
1725 
1726     void setStackArg(Register reg, uint32_t arg);
1727 
1728     void breakpoint();
1729     // Conditional breakpoint.
1730     void breakpoint(Condition cc);
1731 
1732     // Trigger the simulator's interactive read-eval-print loop.
1733     // The message will be printed at the stopping point.
1734     // (On non-simulator builds, does nothing.)
1735     void simulatorStop(const char* msg);
1736 
1737     void compareDouble(FloatRegister lhs, FloatRegister rhs);
1738     void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
1739                       Label* label);
1740 
1741     void compareFloat(FloatRegister lhs, FloatRegister rhs);
1742     void branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
1743                      Label* label);
1744 
1745     void checkStackAlignment();
1746 
1747     // If source is a double, load it into dest. If source is int32, convert it
1748     // to double. Else, branch to failure.
1749     void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
1750 
1751     void
emitSet(Assembler::Condition cond,Register dest)1752     emitSet(Assembler::Condition cond, Register dest)
1753     {
1754         ma_mov(Imm32(0), dest);
1755         ma_mov(Imm32(1), dest, LeaveCC, cond);
1756     }
1757 
1758     template <typename T1, typename T2>
cmpPtrSet(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1759     void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest)
1760     {
1761         cmpPtr(lhs, rhs);
1762         emitSet(cond, dest);
1763     }
1764     template <typename T1, typename T2>
cmp32Set(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1765     void cmp32Set(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest)
1766     {
1767         cmp32(lhs, rhs);
1768         emitSet(cond, dest);
1769     }
1770 
testNullSet(Condition cond,const ValueOperand & value,Register dest)1771     void testNullSet(Condition cond, const ValueOperand& value, Register dest) {
1772         cond = testNull(cond, value);
1773         emitSet(cond, dest);
1774     }
1775 
testObjectSet(Condition cond,const ValueOperand & value,Register dest)1776     void testObjectSet(Condition cond, const ValueOperand& value, Register dest) {
1777         cond = testObject(cond, value);
1778         emitSet(cond, dest);
1779     }
1780 
testUndefinedSet(Condition cond,const ValueOperand & value,Register dest)1781     void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest) {
1782         cond = testUndefined(cond, value);
1783         emitSet(cond, dest);
1784     }
1785 
1786   protected:
1787     bool buildOOLFakeExitFrame(void* fakeReturnAddr);
1788 
1789   public:
labelForPatch()1790     CodeOffset labelForPatch() {
1791         return CodeOffset(nextOffset().getOffset());
1792     }
1793 
computeEffectiveAddress(const Address & address,Register dest)1794     void computeEffectiveAddress(const Address& address, Register dest) {
1795         ma_add(address.base, Imm32(address.offset), dest, LeaveCC);
1796     }
computeEffectiveAddress(const BaseIndex & address,Register dest)1797     void computeEffectiveAddress(const BaseIndex& address, Register dest) {
1798         ma_alu(address.base, lsl(address.index, address.scale), dest, OpAdd, LeaveCC);
1799         if (address.offset)
1800             ma_add(dest, Imm32(address.offset), dest, LeaveCC);
1801     }
1802     void floor(FloatRegister input, Register output, Label* handleNotAnInt);
1803     void floorf(FloatRegister input, Register output, Label* handleNotAnInt);
1804     void ceil(FloatRegister input, Register output, Label* handleNotAnInt);
1805     void ceilf(FloatRegister input, Register output, Label* handleNotAnInt);
1806     void round(FloatRegister input, Register output, Label* handleNotAnInt, FloatRegister tmp);
1807     void roundf(FloatRegister input, Register output, Label* handleNotAnInt, FloatRegister tmp);
1808 
clampCheck(Register r,Label * handleNotAnInt)1809     void clampCheck(Register r, Label* handleNotAnInt) {
1810         // Check explicitly for r == INT_MIN || r == INT_MAX
1811         // This is the instruction sequence that gcc generated for this
1812         // operation.
1813         ScratchRegisterScope scratch(asMasm());
1814         ma_sub(r, Imm32(0x80000001), scratch);
1815         ma_cmn(scratch, Imm32(3));
1816         ma_b(handleNotAnInt, Above);
1817     }
1818 
memIntToValue(Address Source,Address Dest)1819     void memIntToValue(Address Source, Address Dest) {
1820         load32(Source, lr);
1821         storeValue(JSVAL_TYPE_INT32, lr, Dest);
1822     }
1823 
lea(Operand addr,Register dest)1824     void lea(Operand addr, Register dest) {
1825         ma_add(addr.baseReg(), Imm32(addr.disp()), dest);
1826     }
1827 
abiret()1828     void abiret() {
1829         as_bx(lr);
1830     }
1831 
ma_storeImm(Imm32 c,const Address & dest)1832     void ma_storeImm(Imm32 c, const Address& dest) {
1833         ma_mov(c, lr);
1834         ma_str(lr, dest);
1835     }
ma_BoundsCheck(Register bounded)1836     BufferOffset ma_BoundsCheck(Register bounded) {
1837         return as_cmp(bounded, Imm8(0));
1838     }
1839 
moveFloat32(FloatRegister src,FloatRegister dest)1840     void moveFloat32(FloatRegister src, FloatRegister dest) {
1841         as_vmov(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay());
1842     }
1843 
1844     void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
1845     void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label* label);
1846 
loadAsmJSActivation(Register dest)1847     void loadAsmJSActivation(Register dest) {
1848         loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
1849     }
loadAsmJSHeapRegisterFromGlobalData()1850     void loadAsmJSHeapRegisterFromGlobalData() {
1851         loadPtr(Address(GlobalReg, wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias), HeapReg);
1852     }
1853     // Instrumentation for entering and leaving the profiler.
1854     void profilerEnterFrame(Register framePtr, Register scratch);
1855     void profilerExitFrame();
1856 };
1857 
1858 typedef MacroAssemblerARMCompat MacroAssemblerSpecific;
1859 
1860 } // namespace jit
1861 } // namespace js
1862 
1863 #endif /* jit_arm_MacroAssembler_arm_h */
1864