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_mips64_MacroAssembler_mips64_h
8 #define jit_mips64_MacroAssembler_mips64_h
9 
10 #include "jsopcode.h"
11 
12 #include "jit/AtomicOp.h"
13 #include "jit/IonCaches.h"
14 #include "jit/JitFrames.h"
15 #include "jit/mips-shared/MacroAssembler-mips-shared.h"
16 #include "jit/MoveResolver.h"
17 
18 namespace js {
19 namespace jit {
20 
21 enum LiFlags
22 {
23     Li64 = 0,
24     Li48 = 1,
25 };
26 
27 struct ImmShiftedTag : public ImmWord
28 {
ImmShiftedTagImmShiftedTag29     explicit ImmShiftedTag(JSValueShiftedTag shtag)
30       : ImmWord((uintptr_t)shtag)
31     { }
32 
ImmShiftedTagImmShiftedTag33     explicit ImmShiftedTag(JSValueType type)
34       : ImmWord(uintptr_t(JSValueShiftedTag(JSVAL_TYPE_TO_SHIFTED_TAG(type))))
35     { }
36 };
37 
38 struct ImmTag : public Imm32
39 {
ImmTagImmTag40     ImmTag(JSValueTag mask)
41       : Imm32(int32_t(mask))
42     { }
43 };
44 
45 static const ValueOperand JSReturnOperand = ValueOperand(JSReturnReg);
46 
47 static const int defaultShift = 3;
48 static_assert(1 << defaultShift == sizeof(JS::Value), "The defaultShift is wrong");
49 
50 class MacroAssemblerMIPS64 : public MacroAssemblerMIPSShared
51 {
52   public:
53     using MacroAssemblerMIPSShared::ma_b;
54     using MacroAssemblerMIPSShared::ma_li;
55     using MacroAssemblerMIPSShared::ma_ss;
56     using MacroAssemblerMIPSShared::ma_sd;
57     using MacroAssemblerMIPSShared::ma_load;
58     using MacroAssemblerMIPSShared::ma_store;
59     using MacroAssemblerMIPSShared::ma_cmp_set;
60     using MacroAssemblerMIPSShared::ma_subTestOverflow;
61 
62     void ma_li(Register dest, CodeOffset* label);
63     void ma_li(Register dest, ImmWord imm);
64     void ma_liPatchable(Register dest, ImmPtr imm);
65     void ma_liPatchable(Register dest, ImmWord imm, LiFlags flags = Li48);
66 
67     // Shift operations
68     void ma_dsll(Register rd, Register rt, Imm32 shift);
69     void ma_dsrl(Register rd, Register rt, Imm32 shift);
70     void ma_dsra(Register rd, Register rt, Imm32 shift);
71     void ma_dror(Register rd, Register rt, Imm32 shift);
72     void ma_drol(Register rd, Register rt, Imm32 shift);
73 
74     void ma_dsll(Register rd, Register rt, Register shift);
75     void ma_dsrl(Register rd, Register rt, Register shift);
76     void ma_dsra(Register rd, Register rt, Register shift);
77     void ma_dror(Register rd, Register rt, Register shift);
78     void ma_drol(Register rd, Register rt, Register shift);
79 
80     void ma_dins(Register rt, Register rs, Imm32 pos, Imm32 size);
81     void ma_dext(Register rt, Register rs, Imm32 pos, Imm32 size);
82 
83     // load
84     void ma_load(Register dest, Address address, LoadStoreSize size = SizeWord,
85                  LoadStoreExtension extension = SignExtend);
86 
87     // store
88     void ma_store(Register data, Address address, LoadStoreSize size = SizeWord,
89                   LoadStoreExtension extension = SignExtend);
90 
91     // arithmetic based ops
92     // add
93     void ma_daddu(Register rd, Register rs, Imm32 imm);
94     void ma_daddu(Register rd, Register rs);
95     void ma_daddu(Register rd, Imm32 imm);
96     void ma_addTestOverflow(Register rd, Register rs, Register rt, Label* overflow);
97     void ma_addTestOverflow(Register rd, Register rs, Imm32 imm, Label* overflow);
98 
99     // subtract
100     void ma_dsubu(Register rd, Register rs, Imm32 imm);
101     void ma_dsubu(Register rd, Imm32 imm);
102     void ma_subTestOverflow(Register rd, Register rs, Register rt, Label* overflow);
103 
104     // multiplies.  For now, there are only few that we care about.
105     void ma_dmult(Register rs, Imm32 imm);
106 
107     // stack
108     void ma_pop(Register r);
109     void ma_push(Register r);
110 
111     void branchWithCode(InstImm code, Label* label, JumpKind jumpKind);
112     // branches when done from within mips-specific code
113     void ma_b(Register lhs, ImmWord imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
114     void ma_b(Register lhs, Address addr, Label* l, Condition c, JumpKind jumpKind = LongJump);
115     void ma_b(Address addr, Imm32 imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
116     void ma_b(Address addr, ImmGCPtr imm, Label* l, Condition c, JumpKind jumpKind = LongJump);
117     void ma_b(Address addr, Register rhs, Label* l, Condition c, JumpKind jumpKind = LongJump) {
118         MOZ_ASSERT(rhs != ScratchRegister);
119         ma_load(ScratchRegister, addr, SizeDouble);
120         ma_b(ScratchRegister, rhs, l, c, jumpKind);
121     }
122 
123     void ma_bal(Label* l, DelaySlotFill delaySlotFill = FillDelaySlot);
124 
125     // fp instructions
126     void ma_lid(FloatRegister dest, double value);
127 
128     void ma_mv(FloatRegister src, ValueOperand dest);
129     void ma_mv(ValueOperand src, FloatRegister dest);
130 
131     void ma_ls(FloatRegister fd, Address address);
132     void ma_ld(FloatRegister fd, Address address);
133     void ma_sd(FloatRegister fd, Address address);
134     void ma_ss(FloatRegister fd, Address address);
135 
136     void ma_pop(FloatRegister fs);
137     void ma_push(FloatRegister fs);
138 
139     void ma_cmp_set(Register dst, Register lhs, ImmWord imm, Condition c);
140     void ma_cmp_set(Register dst, Register lhs, ImmPtr imm, Condition c);
141 
142     // These functions abstract the access to high part of the double precision
143     // float register. They are intended to work on both 32 bit and 64 bit
144     // floating point coprocessor.
moveToDoubleHi(Register src,FloatRegister dest)145     void moveToDoubleHi(Register src, FloatRegister dest) {
146         as_mthc1(src, dest);
147     }
moveFromDoubleHi(FloatRegister src,Register dest)148     void moveFromDoubleHi(FloatRegister src, Register dest) {
149         as_mfhc1(dest, src);
150     }
151 
moveToDouble(Register src,FloatRegister dest)152     void moveToDouble(Register src, FloatRegister dest) {
153         as_dmtc1(src, dest);
154     }
moveFromDouble(FloatRegister src,Register dest)155     void moveFromDouble(FloatRegister src, Register dest) {
156         as_dmfc1(dest, src);
157     }
158 };
159 
160 class MacroAssembler;
161 
162 class MacroAssemblerMIPS64Compat : public MacroAssemblerMIPS64
163 {
164   public:
165     using MacroAssemblerMIPS64::call;
166 
MacroAssemblerMIPS64Compat()167     MacroAssemblerMIPS64Compat()
168     { }
169 
170     void convertBoolToInt32(Register source, Register dest);
171     void convertInt32ToDouble(Register src, FloatRegister dest);
172     void convertInt32ToDouble(const Address& src, FloatRegister dest);
173     void convertInt32ToDouble(const BaseIndex& src, FloatRegister dest);
174     void convertUInt32ToDouble(Register src, FloatRegister dest);
175     void convertUInt32ToFloat32(Register src, FloatRegister dest);
176     void convertDoubleToFloat32(FloatRegister src, FloatRegister dest);
177     void branchTruncateDouble(FloatRegister src, Register dest, Label* fail);
178     void convertDoubleToInt32(FloatRegister src, Register dest, Label* fail,
179                               bool negativeZeroCheck = true);
180     void convertFloat32ToInt32(FloatRegister src, Register dest, Label* fail,
181                                bool negativeZeroCheck = true);
182 
183     void convertFloat32ToDouble(FloatRegister src, FloatRegister dest);
184     void branchTruncateFloat32(FloatRegister src, Register dest, Label* fail);
185     void convertInt32ToFloat32(Register src, FloatRegister dest);
186     void convertInt32ToFloat32(const Address& src, FloatRegister dest);
187 
188     void addDouble(FloatRegister src, FloatRegister dest);
189     void subDouble(FloatRegister src, FloatRegister dest);
190     void mulDouble(FloatRegister src, FloatRegister dest);
191     void divDouble(FloatRegister src, FloatRegister dest);
192 
193     void negateDouble(FloatRegister reg);
194     void inc64(AbsoluteAddress dest);
195 
196     void movq(Register rs, Register rd);
197 
198     void computeScaledAddress(const BaseIndex& address, Register dest);
199 
computeEffectiveAddress(const Address & address,Register dest)200     void computeEffectiveAddress(const Address& address, Register dest) {
201         ma_daddu(dest, address.base, Imm32(address.offset));
202     }
203 
computeEffectiveAddress(const BaseIndex & address,Register dest)204     void computeEffectiveAddress(const BaseIndex& address, Register dest) {
205         computeScaledAddress(address, dest);
206         if (address.offset) {
207             addPtr(Imm32(address.offset), dest);
208         }
209     }
210 
j(Label * dest)211     void j(Label* dest) {
212         ma_b(dest);
213     }
214 
mov(Register src,Register dest)215     void mov(Register src, Register dest) {
216         as_ori(dest, src, 0);
217     }
mov(ImmWord imm,Register dest)218     void mov(ImmWord imm, Register dest) {
219         ma_li(dest, imm);
220     }
mov(ImmPtr imm,Register dest)221     void mov(ImmPtr imm, Register dest) {
222         mov(ImmWord(uintptr_t(imm.value)), dest);
223     }
mov(Register src,Address dest)224     void mov(Register src, Address dest) {
225         MOZ_CRASH("NYI-IC");
226     }
mov(Address src,Register dest)227     void mov(Address src, Register dest) {
228         MOZ_CRASH("NYI-IC");
229     }
230 
writeDataRelocation(const Value & val)231     void writeDataRelocation(const Value& val) {
232         if (val.isMarkable()) {
233             gc::Cell* cell = reinterpret_cast<gc::Cell *>(val.toGCThing());
234             if (cell && gc::IsInsideNursery(cell))
235                 embedsNurseryPointers_ = true;
236             dataRelocations_.writeUnsigned(currentOffset());
237         }
238     }
239 
branch(JitCode * c)240     void branch(JitCode* c) {
241         BufferOffset bo = m_buffer.nextOffset();
242         addPendingJump(bo, ImmPtr(c->raw()), Relocation::JITCODE);
243         ma_liPatchable(ScratchRegister, ImmPtr(c->raw()));
244         as_jr(ScratchRegister);
245         as_nop();
246     }
branch(const Register reg)247     void branch(const Register reg) {
248         as_jr(reg);
249         as_nop();
250     }
nop()251     void nop() {
252         as_nop();
253     }
ret()254     void ret() {
255         ma_pop(ra);
256         as_jr(ra);
257         as_nop();
258     }
retn(Imm32 n)259     void retn(Imm32 n) {
260         // pc <- [sp]; sp += n
261         loadPtr(Address(StackPointer, 0), ra);
262         addPtr(n, StackPointer);
263         as_jr(ra);
264         as_nop();
265     }
push(Imm32 imm)266     void push(Imm32 imm) {
267         ma_li(ScratchRegister, imm);
268         ma_push(ScratchRegister);
269     }
push(ImmWord imm)270     void push(ImmWord imm) {
271         ma_li(ScratchRegister, imm);
272         ma_push(ScratchRegister);
273     }
push(ImmGCPtr imm)274     void push(ImmGCPtr imm) {
275         ma_li(ScratchRegister, imm);
276         ma_push(ScratchRegister);
277     }
push(const Address & address)278     void push(const Address& address) {
279         loadPtr(address, ScratchRegister);
280         ma_push(ScratchRegister);
281     }
push(Register reg)282     void push(Register reg) {
283         ma_push(reg);
284     }
push(FloatRegister reg)285     void push(FloatRegister reg) {
286         ma_push(reg);
287     }
pop(Register reg)288     void pop(Register reg) {
289         ma_pop(reg);
290     }
pop(FloatRegister reg)291     void pop(FloatRegister reg) {
292         ma_pop(reg);
293     }
294 
295     // Emit a branch that can be toggled to a non-operation. On MIPS64 we use
296     // "andi" instruction to toggle the branch.
297     // See ToggleToJmp(), ToggleToCmp().
298     CodeOffset toggledJump(Label* label);
299 
300     // Emit a "jalr" or "nop" instruction. ToggleCall can be used to patch
301     // this instruction.
302     CodeOffset toggledCall(JitCode* target, bool enabled);
303 
ToggledCallSize(uint8_t * code)304     static size_t ToggledCallSize(uint8_t* code) {
305         // Six instructions used in: MacroAssemblerMIPS64Compat::toggledCall
306         return 6 * sizeof(uint32_t);
307     }
308 
pushWithPatch(ImmWord imm)309     CodeOffset pushWithPatch(ImmWord imm) {
310         CodeOffset offset = movWithPatch(imm, ScratchRegister);
311         ma_push(ScratchRegister);
312         return offset;
313     }
314 
movWithPatch(ImmWord imm,Register dest)315     CodeOffset movWithPatch(ImmWord imm, Register dest) {
316         CodeOffset offset = CodeOffset(currentOffset());
317         ma_liPatchable(dest, imm, Li64);
318         return offset;
319     }
movWithPatch(ImmPtr imm,Register dest)320     CodeOffset movWithPatch(ImmPtr imm, Register dest) {
321         CodeOffset offset = CodeOffset(currentOffset());
322         ma_liPatchable(dest, imm);
323         return offset;
324     }
325 
jump(Label * label)326     void jump(Label* label) {
327         ma_b(label);
328     }
jump(Register reg)329     void jump(Register reg) {
330         as_jr(reg);
331         as_nop();
332     }
jump(const Address & address)333     void jump(const Address& address) {
334         loadPtr(address, ScratchRegister);
335         as_jr(ScratchRegister);
336         as_nop();
337     }
338 
jump(JitCode * code)339     void jump(JitCode* code) {
340         branch(code);
341     }
342 
neg32(Register reg)343     void neg32(Register reg) {
344         ma_negu(reg, reg);
345     }
346 
splitTag(Register src,Register dest)347     void splitTag(Register src, Register dest) {
348         ma_dsrl(dest, src, Imm32(JSVAL_TAG_SHIFT));
349     }
350 
splitTag(const ValueOperand & operand,Register dest)351     void splitTag(const ValueOperand& operand, Register dest) {
352         splitTag(operand.valueReg(), dest);
353     }
354 
355     // Returns the register containing the type tag.
splitTagForTest(const ValueOperand & value)356     Register splitTagForTest(const ValueOperand& value) {
357         splitTag(value, SecondScratchReg);
358         return SecondScratchReg;
359     }
360 
361     void branchTestGCThing(Condition cond, const Address& address, Label* label);
362     void branchTestGCThing(Condition cond, const BaseIndex& src, Label* label);
363 
364     void branchTestPrimitive(Condition cond, const ValueOperand& value, Label* label);
365     void branchTestPrimitive(Condition cond, Register tag, Label* label);
366 
367     void branchTestValue(Condition cond, const ValueOperand& value, const Value& v, Label* label);
368     void branchTestValue(Condition cond, const Address& valaddr, const ValueOperand& value,
369                          Label* label);
370 
371     // unboxing code
372     void unboxNonDouble(const ValueOperand& operand, Register dest);
373     void unboxNonDouble(const Address& src, Register dest);
374     void unboxNonDouble(const BaseIndex& src, Register dest);
375     void unboxInt32(const ValueOperand& operand, Register dest);
376     void unboxInt32(const Operand& operand, Register dest);
377     void unboxInt32(const Address& src, Register dest);
378     void unboxInt32(const BaseIndex& src, Register dest);
379     void unboxBoolean(const ValueOperand& operand, Register dest);
380     void unboxBoolean(const Operand& operand, Register dest);
381     void unboxBoolean(const Address& src, Register dest);
382     void unboxBoolean(const BaseIndex& src, Register dest);
383     void unboxDouble(const ValueOperand& operand, FloatRegister dest);
384     void unboxDouble(const Address& src, FloatRegister dest);
385     void unboxString(const ValueOperand& operand, Register dest);
386     void unboxString(const Operand& operand, Register dest);
387     void unboxString(const Address& src, Register dest);
388     void unboxSymbol(const ValueOperand& src, Register dest);
389     void unboxSymbol(const Operand& src, Register dest);
390     void unboxSymbol(const Address& src, Register dest);
391     void unboxObject(const ValueOperand& src, Register dest);
392     void unboxObject(const Operand& src, Register dest);
393     void unboxObject(const Address& src, Register dest);
unboxObject(const BaseIndex & src,Register dest)394     void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(src, dest); }
395     void unboxValue(const ValueOperand& src, AnyRegister dest);
396     void unboxPrivate(const ValueOperand& src, Register dest);
397 
notBoolean(const ValueOperand & val)398     void notBoolean(const ValueOperand& val) {
399         as_xori(val.valueReg(), val.valueReg(), 1);
400     }
401 
402     // boxing code
403     void boxDouble(FloatRegister src, const ValueOperand& dest);
404     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest);
405 
406     // Extended unboxing API. If the payload is already in a register, returns
407     // that register. Otherwise, provides a move to the given scratch register,
408     // and returns that.
409     Register extractObject(const Address& address, Register scratch);
extractObject(const ValueOperand & value,Register scratch)410     Register extractObject(const ValueOperand& value, Register scratch) {
411         unboxObject(value, scratch);
412         return scratch;
413     }
extractInt32(const ValueOperand & value,Register scratch)414     Register extractInt32(const ValueOperand& value, Register scratch) {
415         unboxInt32(value, scratch);
416         return scratch;
417     }
extractBoolean(const ValueOperand & value,Register scratch)418     Register extractBoolean(const ValueOperand& value, Register scratch) {
419         unboxBoolean(value, scratch);
420         return scratch;
421     }
422     Register extractTag(const Address& address, Register scratch);
423     Register extractTag(const BaseIndex& address, Register scratch);
extractTag(const ValueOperand & value,Register scratch)424     Register extractTag(const ValueOperand& value, Register scratch) {
425         MOZ_ASSERT(scratch != ScratchRegister);
426         splitTag(value, scratch);
427         return scratch;
428     }
429 
430     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest);
431     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest);
432     void loadInt32OrDouble(const Address& src, FloatRegister dest);
433     void loadInt32OrDouble(const BaseIndex& addr, FloatRegister dest);
434     void loadConstantDouble(double dp, FloatRegister dest);
435 
436     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest);
437     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest);
438     void loadConstantFloat32(float f, FloatRegister dest);
439 
440     void branchTestInt32(Condition cond, const ValueOperand& value, Label* label);
441     void branchTestInt32(Condition cond, Register tag, Label* label);
442     void branchTestInt32(Condition cond, const Address& address, Label* label);
443     void branchTestInt32(Condition cond, const BaseIndex& src, Label* label);
444 
445     void branchTestBoolean(Condition cond, const ValueOperand& value, Label* label);
446     void branchTestBoolean(Condition cond, Register tag, Label* label);
447     void branchTestBoolean(Condition cond, const Address& address, Label* label);
448     void branchTestBoolean(Condition cond, const BaseIndex& src, Label* label);
449 
branch32(Condition cond,Register lhs,Register rhs,Label * label)450     void branch32(Condition cond, Register lhs, Register rhs, Label* label) {
451         ma_b(lhs, rhs, label, cond);
452     }
branch32(Condition cond,Register lhs,Imm32 imm,Label * label)453     void branch32(Condition cond, Register lhs, Imm32 imm, Label* label) {
454         ma_b(lhs, imm, label, cond);
455     }
branch32(Condition cond,const Operand & lhs,Register rhs,Label * label)456     void branch32(Condition cond, const Operand& lhs, Register rhs, Label* label) {
457         if (lhs.getTag() == Operand::REG) {
458             ma_b(lhs.toReg(), rhs, label, cond);
459         } else {
460             branch32(cond, lhs.toAddress(), rhs, label);
461         }
462     }
branch32(Condition cond,const Operand & lhs,Imm32 rhs,Label * label)463     void branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label) {
464         if (lhs.getTag() == Operand::REG) {
465             ma_b(lhs.toReg(), rhs, label, cond);
466         } else {
467             branch32(cond, lhs.toAddress(), rhs, label);
468         }
469     }
branch32(Condition cond,const Address & lhs,Register rhs,Label * label)470     void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) {
471         load32(lhs, SecondScratchReg);
472         ma_b(SecondScratchReg, rhs, label, cond);
473     }
branch32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)474     void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) {
475         load32(lhs, SecondScratchReg);
476         ma_b(SecondScratchReg, rhs, label, cond);
477     }
branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)478     void branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label) {
479         load32(lhs, SecondScratchReg);
480         ma_b(SecondScratchReg, rhs, label, cond);
481     }
branchPtr(Condition cond,const Address & lhs,Register rhs,Label * label)482     void branchPtr(Condition cond, const Address& lhs, Register rhs, Label* label) {
483         loadPtr(lhs, SecondScratchReg);
484         ma_b(SecondScratchReg, rhs, label, cond);
485     }
486 
branchPrivatePtr(Condition cond,const Address & lhs,ImmPtr ptr,Label * label)487     void branchPrivatePtr(Condition cond, const Address& lhs, ImmPtr ptr, Label* label) {
488         branchPtr(cond, lhs, ptr, label);
489     }
490 
branchPrivatePtr(Condition cond,const Address & lhs,Register ptr,Label * label)491     void branchPrivatePtr(Condition cond, const Address& lhs, Register ptr, Label* label) {
492         branchPtr(cond, lhs, ptr, label);
493     }
494 
branchPrivatePtr(Condition cond,Register lhs,ImmWord ptr,Label * label)495     void branchPrivatePtr(Condition cond, Register lhs, ImmWord ptr, Label* label) {
496         branchPtr(cond, lhs, ptr, label);
497     }
498 
499     void branchTestDouble(Condition cond, const ValueOperand& value, Label* label);
500     void branchTestDouble(Condition cond, Register tag, Label* label);
501     void branchTestDouble(Condition cond, const Address& address, Label* label);
502     void branchTestDouble(Condition cond, const BaseIndex& src, Label* label);
503 
504     void branchTestNull(Condition cond, const ValueOperand& value, Label* label);
505     void branchTestNull(Condition cond, Register tag, Label* label);
506     void branchTestNull(Condition cond, const BaseIndex& src, Label* label);
507     void branchTestNull(Condition cond, const Address& address, Label* label);
508     void testNullSet(Condition cond, const ValueOperand& value, Register dest);
509 
510     void branchTestObject(Condition cond, const ValueOperand& value, Label* label);
511     void branchTestObject(Condition cond, Register tag, Label* label);
512     void branchTestObject(Condition cond, const BaseIndex& src, Label* label);
513     void branchTestObject(Condition cond, const Address& src, Label* label);
514     void testObjectSet(Condition cond, const ValueOperand& value, Register dest);
515 
516     void branchTestString(Condition cond, const ValueOperand& value, Label* label);
517     void branchTestString(Condition cond, Register tag, Label* label);
518     void branchTestString(Condition cond, const BaseIndex& src, Label* label);
519 
520     void branchTestSymbol(Condition cond, const ValueOperand& value, Label* label);
521     void branchTestSymbol(Condition cond, const Register& tag, Label* label);
522     void branchTestSymbol(Condition cond, const BaseIndex& src, Label* label);
523 
524     void branchTestUndefined(Condition cond, const ValueOperand& value, Label* label);
525     void branchTestUndefined(Condition cond, Register tag, Label* label);
526     void branchTestUndefined(Condition cond, const BaseIndex& src, Label* label);
527     void branchTestUndefined(Condition cond, const Address& address, Label* label);
528     void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest);
529 
530     void branchTestNumber(Condition cond, const ValueOperand& value, Label* label);
531     void branchTestNumber(Condition cond, Register tag, Label* label);
532 
533     void branchTestMagic(Condition cond, const ValueOperand& value, Label* label);
534     void branchTestMagic(Condition cond, Register tag, Label* label);
535     void branchTestMagic(Condition cond, const Address& address, Label* label);
536     void branchTestMagic(Condition cond, const BaseIndex& src, Label* label);
537 
branchTestMagicValue(Condition cond,const ValueOperand & val,JSWhyMagic why,Label * label)538     void branchTestMagicValue(Condition cond, const ValueOperand& val, JSWhyMagic why,
539                               Label* label) {
540         MOZ_ASSERT(cond == Equal || cond == NotEqual);
541         branchTestValue(cond, val, MagicValue(why), label);
542     }
543 
544     void branchTestInt32Truthy(bool b, const ValueOperand& value, Label* label);
545 
546     void branchTestStringTruthy(bool b, const ValueOperand& value, Label* label);
547 
548     void branchTestDoubleTruthy(bool b, FloatRegister value, Label* label);
549 
550     void branchTestBooleanTruthy(bool b, const ValueOperand& operand, Label* label);
551 
branchTest32(Condition cond,Register lhs,Register rhs,Label * label)552     void branchTest32(Condition cond, Register lhs, Register rhs, Label* label) {
553         MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
554         if (lhs == rhs) {
555             ma_b(lhs, rhs, label, cond);
556         } else {
557             as_and(ScratchRegister, lhs, rhs);
558             ma_b(ScratchRegister, ScratchRegister, label, cond);
559         }
560     }
branchTest32(Condition cond,Register lhs,Imm32 imm,Label * label)561     void branchTest32(Condition cond, Register lhs, Imm32 imm, Label* label) {
562         ma_li(ScratchRegister, imm);
563         branchTest32(cond, lhs, ScratchRegister, label);
564     }
branchTest32(Condition cond,const Address & address,Imm32 imm,Label * label)565     void branchTest32(Condition cond, const Address& address, Imm32 imm, Label* label) {
566         load32(address, SecondScratchReg);
567         branchTest32(cond, SecondScratchReg, imm, label);
568     }
branchTest32(Condition cond,AbsoluteAddress address,Imm32 imm,Label * label)569     void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label* label) {
570         load32(address, ScratchRegister);
571         branchTest32(cond, ScratchRegister, imm, label);
572     }
branchTestPtr(Condition cond,Register lhs,Register rhs,Label * label)573     void branchTestPtr(Condition cond, Register lhs, Register rhs, Label* label) {
574         MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
575         if (lhs == rhs) {
576             ma_b(lhs, rhs, label, cond);
577         } else {
578             as_and(ScratchRegister, lhs, rhs);
579             ma_b(ScratchRegister, ScratchRegister, label, cond);
580         }
581     }
branchTestPtr(Condition cond,Register lhs,const Imm32 rhs,Label * label)582     void branchTestPtr(Condition cond, Register lhs, const Imm32 rhs, Label* label) {
583         ma_li(ScratchRegister, rhs);
584         branchTestPtr(cond, lhs, ScratchRegister, label);
585     }
branchTestPtr(Condition cond,const Address & lhs,Imm32 imm,Label * label)586     void branchTestPtr(Condition cond, const Address& lhs, Imm32 imm, Label* label) {
587         loadPtr(lhs, SecondScratchReg);
588         branchTestPtr(cond, SecondScratchReg, imm, label);
589     }
branchTest64(Condition cond,Register64 lhs,Register64 rhs,Register temp,Label * label)590     void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp,
591                       Label* label) {
592         branchTestPtr(cond, lhs.reg, rhs.reg, label);
593     }
branchPtr(Condition cond,Register lhs,Register rhs,Label * label)594     void branchPtr(Condition cond, Register lhs, Register rhs, Label* label) {
595         ma_b(lhs, rhs, label, cond);
596     }
branchPtr(Condition cond,Register lhs,ImmGCPtr ptr,Label * label)597     void branchPtr(Condition cond, Register lhs, ImmGCPtr ptr, Label* label) {
598         ma_b(lhs, ptr, label, cond);
599     }
branchPtr(Condition cond,Register lhs,ImmWord imm,Label * label)600     void branchPtr(Condition cond, Register lhs, ImmWord imm, Label* label) {
601         ma_b(lhs, imm, label, cond);
602     }
branchPtr(Condition cond,Register lhs,ImmPtr imm,Label * label)603     void branchPtr(Condition cond, Register lhs, ImmPtr imm, Label* label) {
604         ma_b(lhs, imm, label, cond);
605     }
branchPtr(Condition cond,Register lhs,wasm::SymbolicAddress imm,Label * label)606     void branchPtr(Condition cond, Register lhs, wasm::SymbolicAddress imm, Label* label) {
607         movePtr(imm, SecondScratchReg);
608         ma_b(lhs, SecondScratchReg, label, cond);
609     }
branchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)610     void branchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
611         ma_b(lhs, imm, label, cond);
612     }
decBranchPtr(Condition cond,Register lhs,Imm32 imm,Label * label)613     void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label* label) {
614         subPtr(imm, lhs);
615         branchPtr(cond, lhs, Imm32(0), label);
616     }
617 
618     // higher level tag testing code
ToPayload(Address value)619     Address ToPayload(Address value) {
620         return value;
621     }
622 
623     void moveValue(const Value& val, Register dest);
624 
625     CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr);
626     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr);
627 
628     template <typename T>
branchPtrWithPatch(Condition cond,Register reg,T ptr,RepatchLabel * label)629     CodeOffsetJump branchPtrWithPatch(Condition cond, Register reg, T ptr, RepatchLabel* label) {
630         movePtr(ptr, ScratchRegister);
631         Label skipJump;
632         ma_b(reg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
633         CodeOffsetJump off = jumpWithPatch(label);
634         bind(&skipJump);
635         return off;
636     }
637 
638     template <typename T>
branchPtrWithPatch(Condition cond,Address addr,T ptr,RepatchLabel * label)639     CodeOffsetJump branchPtrWithPatch(Condition cond, Address addr, T ptr, RepatchLabel* label) {
640         loadPtr(addr, SecondScratchReg);
641         movePtr(ptr, ScratchRegister);
642         Label skipJump;
643         ma_b(SecondScratchReg, ScratchRegister, &skipJump, InvertCondition(cond), ShortJump);
644         CodeOffsetJump off = jumpWithPatch(label);
645         bind(&skipJump);
646         return off;
647     }
branchPtr(Condition cond,Address addr,ImmGCPtr ptr,Label * label)648     void branchPtr(Condition cond, Address addr, ImmGCPtr ptr, Label* label) {
649         loadPtr(addr, SecondScratchReg);
650         ma_b(SecondScratchReg, ptr, label, cond);
651     }
652 
branchPtr(Condition cond,Address addr,ImmWord ptr,Label * label)653     void branchPtr(Condition cond, Address addr, ImmWord ptr, Label* label) {
654         loadPtr(addr, SecondScratchReg);
655         ma_b(SecondScratchReg, ptr, label, cond);
656     }
branchPtr(Condition cond,Address addr,ImmPtr ptr,Label * label)657     void branchPtr(Condition cond, Address addr, ImmPtr ptr, Label* label) {
658         loadPtr(addr, SecondScratchReg);
659         ma_b(SecondScratchReg, ptr, label, cond);
660     }
branchPtr(Condition cond,AbsoluteAddress addr,Register ptr,Label * label)661     void branchPtr(Condition cond, AbsoluteAddress addr, Register ptr, Label* label) {
662         loadPtr(addr, SecondScratchReg);
663         ma_b(SecondScratchReg, ptr, label, cond);
664     }
branchPtr(Condition cond,AbsoluteAddress addr,ImmWord ptr,Label * label)665     void branchPtr(Condition cond, AbsoluteAddress addr, ImmWord ptr, Label* label) {
666         loadPtr(addr, SecondScratchReg);
667         ma_b(SecondScratchReg, ptr, label, cond);
668     }
branchPtr(Condition cond,wasm::SymbolicAddress addr,Register ptr,Label * label)669     void branchPtr(Condition cond, wasm::SymbolicAddress addr, Register ptr, Label* label) {
670         loadPtr(addr, SecondScratchReg);
671         ma_b(SecondScratchReg, ptr, label, cond);
672     }
branch32(Condition cond,AbsoluteAddress lhs,Imm32 rhs,Label * label)673     void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label* label) {
674         load32(lhs, SecondScratchReg);
675         ma_b(SecondScratchReg, rhs, label, cond);
676     }
branch32(Condition cond,AbsoluteAddress lhs,Register rhs,Label * label)677     void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label* label) {
678         load32(lhs, SecondScratchReg);
679         ma_b(SecondScratchReg, rhs, label, cond);
680     }
branch32(Condition cond,wasm::SymbolicAddress addr,Imm32 imm,Label * label)681     void branch32(Condition cond, wasm::SymbolicAddress addr, Imm32 imm, Label* label) {
682         load32(addr, SecondScratchReg);
683         ma_b(SecondScratchReg, imm, label, cond);
684     }
685 
686     template <typename T>
loadUnboxedValue(const T & address,MIRType type,AnyRegister dest)687     void loadUnboxedValue(const T& address, MIRType type, AnyRegister dest) {
688         if (dest.isFloat())
689             loadInt32OrDouble(address, dest.fpu());
690         else if (type == MIRType_Int32)
691             unboxInt32(address, dest.gpr());
692         else if (type == MIRType_Boolean)
693             unboxBoolean(address, dest.gpr());
694         else
695             unboxNonDouble(address, dest.gpr());
696     }
697 
698     template <typename T>
699     void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T& dest,
700                            MIRType slotType);
701 
702     template <typename T>
storeUnboxedPayload(ValueOperand value,T address,size_t nbytes)703     void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) {
704         switch (nbytes) {
705           case 8:
706             unboxNonDouble(value, ScratchRegister);
707             storePtr(ScratchRegister, address);
708             return;
709           case 4:
710             store32(value.valueReg(), address);
711             return;
712           case 1:
713             store8(value.valueReg(), address);
714             return;
715           default: MOZ_CRASH("Bad payload width");
716         }
717     }
718 
719     void moveValue(const Value& val, const ValueOperand& dest);
720 
moveValue(const ValueOperand & src,const ValueOperand & dest)721     void moveValue(const ValueOperand& src, const ValueOperand& dest) {
722         if (src.valueReg() != dest.valueReg())
723           ma_move(dest.valueReg(), src.valueReg());
724     }
boxValue(JSValueType type,Register src,Register dest)725     void boxValue(JSValueType type, Register src, Register dest) {
726         MOZ_ASSERT(src != dest);
727 
728         JSValueTag tag = (JSValueTag)JSVAL_TYPE_TO_TAG(type);
729         ma_li(dest, Imm32(tag));
730         ma_dsll(dest, dest, Imm32(JSVAL_TAG_SHIFT));
731         ma_dins(dest, src, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
732     }
733 
734     void storeValue(ValueOperand val, Operand dst);
735     void storeValue(ValueOperand val, const BaseIndex& dest);
736     void storeValue(JSValueType type, Register reg, BaseIndex dest);
737     void storeValue(ValueOperand val, const Address& dest);
738     void storeValue(JSValueType type, Register reg, Address dest);
739     void storeValue(const Value& val, Address dest);
740     void storeValue(const Value& val, BaseIndex dest);
741 
742     void loadValue(Address src, ValueOperand val);
loadValue(Operand dest,ValueOperand val)743     void loadValue(Operand dest, ValueOperand val) {
744         loadValue(dest.toAddress(), val);
745     }
746     void loadValue(const BaseIndex& addr, ValueOperand val);
747     void tagValue(JSValueType type, Register payload, ValueOperand dest);
748 
749     void pushValue(ValueOperand val);
750     void popValue(ValueOperand val);
pushValue(const Value & val)751     void pushValue(const Value& val) {
752         jsval_layout jv = JSVAL_TO_IMPL(val);
753         if (val.isMarkable()) {
754             writeDataRelocation(val);
755             movWithPatch(ImmWord(jv.asBits), ScratchRegister);
756             push(ScratchRegister);
757         } else {
758             push(ImmWord(jv.asBits));
759         }
760     }
pushValue(JSValueType type,Register reg)761     void pushValue(JSValueType type, Register reg) {
762         boxValue(type, reg, ScratchRegister);
763         push(ScratchRegister);
764     }
765     void pushValue(const Address& addr);
766 
767     void handleFailureWithHandlerTail(void* handler);
768 
769     /////////////////////////////////////////////////////////////////
770     // Common interface.
771     /////////////////////////////////////////////////////////////////
772   public:
773     // The following functions are exposed for use in platform-shared code.
774 
775     template<typename T>
compareExchange8SignExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)776     void compareExchange8SignExtend(const T& mem, Register oldval, Register newval, Register valueTemp,
777                                     Register offsetTemp, Register maskTemp, Register output)
778     {
779         compareExchange(1, true, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output);
780     }
781     template<typename T>
compareExchange8ZeroExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)782     void compareExchange8ZeroExtend(const T& mem, Register oldval, Register newval, Register valueTemp,
783                                     Register offsetTemp, Register maskTemp, Register output)
784     {
785         compareExchange(1, false, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output);
786     }
787     template<typename T>
compareExchange16SignExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)788     void compareExchange16SignExtend(const T& mem, Register oldval, Register newval, Register valueTemp,
789                                      Register offsetTemp, Register maskTemp, Register output)
790     {
791         compareExchange(2, true, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output);
792     }
793     template<typename T>
compareExchange16ZeroExtend(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)794     void compareExchange16ZeroExtend(const T& mem, Register oldval, Register newval, Register valueTemp,
795                                      Register offsetTemp, Register maskTemp, Register output)
796     {
797         compareExchange(2, false, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output);
798     }
799     template<typename T>
compareExchange32(const T & mem,Register oldval,Register newval,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)800     void compareExchange32(const T& mem, Register oldval, Register newval, Register valueTemp,
801                            Register offsetTemp, Register maskTemp, Register output)
802     {
803         compareExchange(4, false, mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output);
804     }
805 
806     template<typename T>
atomicExchange8SignExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)807     void atomicExchange8SignExtend(const T& mem, Register value, Register valueTemp,
808                           Register offsetTemp, Register maskTemp, Register output)
809     {
810         atomicExchange(1, true, mem, value, valueTemp, offsetTemp, maskTemp, output);
811     }
812     template<typename T>
atomicExchange8ZeroExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)813     void atomicExchange8ZeroExtend(const T& mem, Register value, Register valueTemp,
814                           Register offsetTemp, Register maskTemp, Register output)
815     {
816         atomicExchange(1, false, mem, value, valueTemp, offsetTemp, maskTemp, output);
817     }
818     template<typename T>
atomicExchange16SignExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)819     void atomicExchange16SignExtend(const T& mem, Register value, Register valueTemp,
820                           Register offsetTemp, Register maskTemp, Register output)
821     {
822         atomicExchange(2, true, mem, value, valueTemp, offsetTemp, maskTemp, output);
823     }
824     template<typename T>
atomicExchange16ZeroExtend(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)825     void atomicExchange16ZeroExtend(const T& mem, Register value, Register valueTemp,
826                           Register offsetTemp, Register maskTemp, Register output)
827     {
828         atomicExchange(2, false, mem, value, valueTemp, offsetTemp, maskTemp, output);
829     }
830     template<typename T>
atomicExchange32(const T & mem,Register value,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)831     void atomicExchange32(const T& mem, Register value, Register valueTemp,
832                           Register offsetTemp, Register maskTemp, Register output)
833     {
834         atomicExchange(4, false, mem, value, valueTemp, offsetTemp, maskTemp, output);
835     }
836 
837     template<typename T, typename S>
atomicFetchAdd8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)838     void atomicFetchAdd8SignExtend(const S& value, const T& mem, Register flagTemp,
839                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
840     {
841         atomicFetchOp(1, true, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
842     }
843     template<typename T, typename S>
atomicFetchAdd8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)844     void atomicFetchAdd8ZeroExtend(const S& value, const T& mem, Register flagTemp,
845                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
846     {
847         atomicFetchOp(1, false, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
848     }
849     template<typename T, typename S>
atomicFetchAdd16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)850     void atomicFetchAdd16SignExtend(const S& value, const T& mem, Register flagTemp,
851                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
852     {
853         atomicFetchOp(2, true, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
854     }
855     template<typename T, typename S>
atomicFetchAdd16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)856     void atomicFetchAdd16ZeroExtend(const S& value, const T& mem, Register flagTemp,
857                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
858     {
859         atomicFetchOp(2, false, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
860     }
861     template<typename T, typename S>
atomicFetchAdd32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)862     void atomicFetchAdd32(const S& value, const T& mem, Register flagTemp,
863                           Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
864     {
865         atomicFetchOp(4, false, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
866     }
867     template <typename T, typename S>
atomicAdd8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)868     void atomicAdd8(const T& value, const S& mem, Register flagTemp,
869                     Register valueTemp, Register offsetTemp, Register maskTemp)
870     {
871         atomicEffectOp(1, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
872     }
873     template <typename T, typename S>
atomicAdd16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)874     void atomicAdd16(const T& value, const S& mem, Register flagTemp,
875                      Register valueTemp, Register offsetTemp, Register maskTemp)
876     {
877         atomicEffectOp(2, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
878     }
879     template <typename T, typename S>
atomicAdd32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)880     void atomicAdd32(const T& value, const S& mem, Register flagTemp,
881                      Register valueTemp, Register offsetTemp, Register maskTemp)
882     {
883         atomicEffectOp(4, AtomicFetchAddOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
884     }
885 
886     template<typename T, typename S>
atomicFetchSub8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)887     void atomicFetchSub8SignExtend(const S& value, const T& mem, Register flagTemp,
888                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
889     {
890         atomicFetchOp(1, true, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
891     }
892     template<typename T, typename S>
atomicFetchSub8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)893     void atomicFetchSub8ZeroExtend(const S& value, const T& mem, Register flagTemp,
894                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
895     {
896         atomicFetchOp(1, false, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
897     }
898     template<typename T, typename S>
atomicFetchSub16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)899     void atomicFetchSub16SignExtend(const S& value, const T& mem, Register flagTemp,
900                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
901     {
902         atomicFetchOp(2, true, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
903     }
904     template<typename T, typename S>
atomicFetchSub16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)905     void atomicFetchSub16ZeroExtend(const S& value, const T& mem, Register flagTemp,
906                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
907     {
908         atomicFetchOp(2, false, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
909     }
910     template<typename T, typename S>
atomicFetchSub32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)911     void atomicFetchSub32(const S& value, const T& mem, Register flagTemp,
912                           Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
913     {
914         atomicFetchOp(4, false, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
915     }
916     template <typename T, typename S>
atomicSub8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)917     void atomicSub8(const T& value, const S& mem, Register flagTemp,
918                     Register valueTemp, Register offsetTemp, Register maskTemp)
919     {
920         atomicEffectOp(1, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
921     }
922     template <typename T, typename S>
atomicSub16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)923     void atomicSub16(const T& value, const S& mem, Register flagTemp,
924                      Register valueTemp, Register offsetTemp, Register maskTemp)
925     {
926         atomicEffectOp(2, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
927     }
928     template <typename T, typename S>
atomicSub32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)929     void atomicSub32(const T& value, const S& mem, Register flagTemp,
930                      Register valueTemp, Register offsetTemp, Register maskTemp)
931     {
932         atomicEffectOp(4, AtomicFetchSubOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
933     }
934 
935     template<typename T, typename S>
atomicFetchAnd8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)936     void atomicFetchAnd8SignExtend(const S& value, const T& mem, Register flagTemp,
937                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
938     {
939         atomicFetchOp(1, true, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
940     }
941     template<typename T, typename S>
atomicFetchAnd8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)942     void atomicFetchAnd8ZeroExtend(const S& value, const T& mem, Register flagTemp,
943                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
944     {
945         atomicFetchOp(1, false, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
946     }
947     template<typename T, typename S>
atomicFetchAnd16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)948     void atomicFetchAnd16SignExtend(const S& value, const T& mem, Register flagTemp,
949                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
950     {
951         atomicFetchOp(2, true, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
952     }
953     template<typename T, typename S>
atomicFetchAnd16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)954     void atomicFetchAnd16ZeroExtend(const S& value, const T& mem, Register flagTemp,
955                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
956     {
957         atomicFetchOp(2, false, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
958     }
959     template<typename T, typename S>
atomicFetchAnd32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)960     void atomicFetchAnd32(const S& value, const T& mem, Register flagTemp,
961                           Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
962     {
963         atomicFetchOp(4, false, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
964     }
965     template <typename T, typename S>
atomicAnd8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)966     void atomicAnd8(const T& value, const S& mem, Register flagTemp,
967                     Register valueTemp, Register offsetTemp, Register maskTemp)
968     {
969         atomicEffectOp(1, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
970     }
971     template <typename T, typename S>
atomicAnd16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)972     void atomicAnd16(const T& value, const S& mem, Register flagTemp,
973                      Register valueTemp, Register offsetTemp, Register maskTemp)
974     {
975         atomicEffectOp(2, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
976     }
977     template <typename T, typename S>
atomicAnd32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)978     void atomicAnd32(const T& value, const S& mem, Register flagTemp,
979                      Register valueTemp, Register offsetTemp, Register maskTemp)
980     {
981         atomicEffectOp(4, AtomicFetchAndOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
982     }
983 
984     template<typename T, typename S>
atomicFetchOr8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)985     void atomicFetchOr8SignExtend(const S& value, const T& mem, Register flagTemp,
986                                   Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
987     {
988         atomicFetchOp(1, true, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
989     }
990     template<typename T, typename S>
atomicFetchOr8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)991     void atomicFetchOr8ZeroExtend(const S& value, const T& mem, Register flagTemp,
992                                   Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
993     {
994         atomicFetchOp(1, false, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
995     }
996     template<typename T, typename S>
atomicFetchOr16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)997     void atomicFetchOr16SignExtend(const S& value, const T& mem, Register flagTemp,
998                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
999     {
1000         atomicFetchOp(2, true, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1001     }
1002     template<typename T, typename S>
atomicFetchOr16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1003     void atomicFetchOr16ZeroExtend(const S& value, const T& mem, Register flagTemp,
1004                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1005     {
1006         atomicFetchOp(2, false, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1007     }
1008     template<typename T, typename S>
atomicFetchOr32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1009     void atomicFetchOr32(const S& value, const T& mem, Register flagTemp,
1010                          Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1011     {
1012         atomicFetchOp(4, false, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1013     }
1014     template <typename T, typename S>
atomicOr8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1015     void atomicOr8(const T& value, const S& mem, Register flagTemp,
1016                    Register valueTemp, Register offsetTemp, Register maskTemp)
1017     {
1018         atomicEffectOp(1, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
1019     }
1020     template <typename T, typename S>
atomicOr16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1021     void atomicOr16(const T& value, const S& mem, Register flagTemp,
1022                     Register valueTemp, Register offsetTemp, Register maskTemp)
1023     {
1024         atomicEffectOp(2, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
1025     }
1026     template <typename T, typename S>
atomicOr32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1027     void atomicOr32(const T& value, const S& mem, Register flagTemp,
1028                     Register valueTemp, Register offsetTemp, Register maskTemp)
1029     {
1030         atomicEffectOp(4, AtomicFetchOrOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
1031     }
1032 
1033     template<typename T, typename S>
atomicFetchXor8SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1034     void atomicFetchXor8SignExtend(const S& value, const T& mem, Register flagTemp,
1035                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1036     {
1037         atomicFetchOp(1, true, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1038     }
1039     template<typename T, typename S>
atomicFetchXor8ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1040     void atomicFetchXor8ZeroExtend(const S& value, const T& mem, Register flagTemp,
1041                                    Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1042     {
1043         atomicFetchOp(1, false, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1044     }
1045     template<typename T, typename S>
atomicFetchXor16SignExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1046     void atomicFetchXor16SignExtend(const S& value, const T& mem, Register flagTemp,
1047                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1048     {
1049         atomicFetchOp(2, true, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1050     }
1051     template<typename T, typename S>
atomicFetchXor16ZeroExtend(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1052     void atomicFetchXor16ZeroExtend(const S& value, const T& mem, Register flagTemp,
1053                                     Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1054     {
1055         atomicFetchOp(2, false, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1056     }
1057     template<typename T, typename S>
atomicFetchXor32(const S & value,const T & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp,Register output)1058     void atomicFetchXor32(const S& value, const T& mem, Register flagTemp,
1059                           Register valueTemp, Register offsetTemp, Register maskTemp, Register output)
1060     {
1061         atomicFetchOp(4, false, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output);
1062     }
1063     template <typename T, typename S>
atomicXor8(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1064     void atomicXor8(const T& value, const S& mem, Register flagTemp,
1065                      Register valueTemp, Register offsetTemp, Register maskTemp)
1066     {
1067         atomicEffectOp(1, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
1068     }
1069     template <typename T, typename S>
atomicXor16(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1070     void atomicXor16(const T& value, const S& mem, Register flagTemp,
1071                      Register valueTemp, Register offsetTemp, Register maskTemp)
1072     {
1073         atomicEffectOp(2, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
1074     }
1075     template <typename T, typename S>
atomicXor32(const T & value,const S & mem,Register flagTemp,Register valueTemp,Register offsetTemp,Register maskTemp)1076     void atomicXor32(const T& value, const S& mem, Register flagTemp,
1077                      Register valueTemp, Register offsetTemp, Register maskTemp)
1078     {
1079         atomicEffectOp(4, AtomicFetchXorOp, value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
1080     }
1081 
1082     template<typename T>
1083     void compareExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register oldval, Register newval,
1084                                         Register temp, Register valueTemp, Register offsetTemp, Register maskTemp,
1085                                         AnyRegister output);
1086 
1087     template<typename T>
1088     void atomicExchangeToTypedIntArray(Scalar::Type arrayType, const T& mem, Register value,
1089                                        Register temp, Register valueTemp, Register offsetTemp, Register maskTemp,
1090                                        AnyRegister output);
1091 
1092     void add32(Register src, Register dest);
1093     void add32(Imm32 imm, Register dest);
1094     void add32(Imm32 imm, const Address& dest);
add64(Imm32 imm,Register64 dest)1095     void add64(Imm32 imm, Register64 dest) {
1096         ma_daddu(dest.reg, imm);
1097     }
1098 
incrementInt32Value(const Address & addr)1099     void incrementInt32Value(const Address& addr) {
1100         add32(Imm32(1), addr);
1101     }
1102 
1103     template <typename T>
branchAdd32(Condition cond,T src,Register dest,Label * overflow)1104     void branchAdd32(Condition cond, T src, Register dest, Label* overflow) {
1105         switch (cond) {
1106           case Overflow:
1107             ma_addTestOverflow(dest, dest, src, overflow);
1108             break;
1109           default:
1110             MOZ_CRASH("NYI");
1111         }
1112     }
1113     template <typename T>
branchSub32(Condition cond,T src,Register dest,Label * overflow)1114     void branchSub32(Condition cond, T src, Register dest, Label* overflow) {
1115         switch (cond) {
1116           case Overflow:
1117             ma_subTestOverflow(dest, dest, src, overflow);
1118             break;
1119           case NonZero:
1120           case Zero:
1121             ma_subu(dest, src);
1122             ma_b(dest, dest, overflow, cond);
1123             break;
1124           default:
1125             MOZ_CRASH("NYI");
1126         }
1127     }
1128 
1129     void addPtr(Register src, Register dest);
1130     void subPtr(Register src, Register dest);
1131     void addPtr(const Address& src, Register dest);
1132 
1133     void move32(Imm32 imm, Register dest);
1134     void move32(Register src, Register dest);
move64(Register64 src,Register64 dest)1135     void move64(Register64 src, Register64 dest) {
1136         movePtr(src.reg, dest.reg);
1137     }
1138 
1139     void movePtr(Register src, Register dest);
1140     void movePtr(ImmWord imm, Register dest);
1141     void movePtr(ImmPtr imm, Register dest);
1142     void movePtr(wasm::SymbolicAddress imm, Register dest);
1143     void movePtr(ImmGCPtr imm, Register dest);
1144 
1145     void load8SignExtend(const Address& address, Register dest);
1146     void load8SignExtend(const BaseIndex& src, Register dest);
1147 
1148     void load8ZeroExtend(const Address& address, Register dest);
1149     void load8ZeroExtend(const BaseIndex& src, Register dest);
1150 
1151     void load16SignExtend(const Address& address, Register dest);
1152     void load16SignExtend(const BaseIndex& src, Register dest);
1153 
1154     void load16ZeroExtend(const Address& address, Register dest);
1155     void load16ZeroExtend(const BaseIndex& src, Register dest);
1156 
1157     void load32(const Address& address, Register dest);
1158     void load32(const BaseIndex& address, Register dest);
1159     void load32(AbsoluteAddress address, Register dest);
1160     void load32(wasm::SymbolicAddress address, Register dest);
load64(const Address & address,Register64 dest)1161     void load64(const Address& address, Register64 dest) {
1162         loadPtr(address, dest.reg);
1163     }
1164 
1165     void loadPtr(const Address& address, Register dest);
1166     void loadPtr(const BaseIndex& src, Register dest);
1167     void loadPtr(AbsoluteAddress address, Register dest);
1168     void loadPtr(wasm::SymbolicAddress address, Register dest);
1169 
branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)1170     void branch64(Condition cond, const Address& lhs, Imm64 val, Label* label) {
1171         MOZ_ASSERT(cond == Assembler::NotEqual,
1172                    "other condition codes not supported");
1173 
1174         branchPtr(cond, lhs, ImmWord(val.value), label);
1175     }
1176 
branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)1177     void branch64(Condition cond, const Address& lhs, const Address& rhs, Register scratch,
1178                   Label* label)
1179     {
1180         MOZ_ASSERT(cond == Assembler::NotEqual,
1181                    "other condition codes not supported");
1182         MOZ_ASSERT(lhs.base != scratch);
1183         MOZ_ASSERT(rhs.base != scratch);
1184 
1185         loadPtr(rhs, scratch);
1186         branchPtr(cond, lhs, scratch, label);
1187     }
1188 
1189     void loadPrivate(const Address& address, Register dest);
1190 
loadInt32x1(const Address & addr,FloatRegister dest)1191     void loadInt32x1(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x1(const BaseIndex & addr,FloatRegister dest)1192     void loadInt32x1(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x2(const Address & addr,FloatRegister dest)1193     void loadInt32x2(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x2(const BaseIndex & addr,FloatRegister dest)1194     void loadInt32x2(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x3(const Address & src,FloatRegister dest)1195     void loadInt32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadInt32x3(const BaseIndex & src,FloatRegister dest)1196     void loadInt32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeInt32x1(FloatRegister src,const Address & dest)1197     void storeInt32x1(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeInt32x1(FloatRegister src,const BaseIndex & dest)1198     void storeInt32x1(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
storeInt32x2(FloatRegister src,const Address & dest)1199     void storeInt32x2(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeInt32x2(FloatRegister src,const BaseIndex & dest)1200     void storeInt32x2(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
storeInt32x3(FloatRegister src,const Address & dest)1201     void storeInt32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeInt32x3(FloatRegister src,const BaseIndex & dest)1202     void storeInt32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
loadAlignedInt32x4(const Address & addr,FloatRegister dest)1203     void loadAlignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeAlignedInt32x4(FloatRegister src,Address addr)1204     void storeAlignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
loadUnalignedInt32x4(const Address & addr,FloatRegister dest)1205     void loadUnalignedInt32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadUnalignedInt32x4(const BaseIndex & addr,FloatRegister dest)1206     void loadUnalignedInt32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeUnalignedInt32x4(FloatRegister src,Address addr)1207     void storeUnalignedInt32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
storeUnalignedInt32x4(FloatRegister src,BaseIndex addr)1208     void storeUnalignedInt32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); }
1209 
loadFloat32x3(const Address & src,FloatRegister dest)1210     void loadFloat32x3(const Address& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadFloat32x3(const BaseIndex & src,FloatRegister dest)1211     void loadFloat32x3(const BaseIndex& src, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeFloat32x3(FloatRegister src,const Address & dest)1212     void storeFloat32x3(FloatRegister src, const Address& dest) { MOZ_CRASH("NYI"); }
storeFloat32x3(FloatRegister src,const BaseIndex & dest)1213     void storeFloat32x3(FloatRegister src, const BaseIndex& dest) { MOZ_CRASH("NYI"); }
loadAlignedFloat32x4(const Address & addr,FloatRegister dest)1214     void loadAlignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeAlignedFloat32x4(FloatRegister src,Address addr)1215     void storeAlignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
loadUnalignedFloat32x4(const Address & addr,FloatRegister dest)1216     void loadUnalignedFloat32x4(const Address& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
loadUnalignedFloat32x4(const BaseIndex & addr,FloatRegister dest)1217     void loadUnalignedFloat32x4(const BaseIndex& addr, FloatRegister dest) { MOZ_CRASH("NYI"); }
storeUnalignedFloat32x4(FloatRegister src,Address addr)1218     void storeUnalignedFloat32x4(FloatRegister src, Address addr) { MOZ_CRASH("NYI"); }
storeUnalignedFloat32x4(FloatRegister src,BaseIndex addr)1219     void storeUnalignedFloat32x4(FloatRegister src, BaseIndex addr) { MOZ_CRASH("NYI"); }
1220 
1221     void loadDouble(const Address& addr, FloatRegister dest);
1222     void loadDouble(const BaseIndex& src, FloatRegister dest);
1223 
1224     // Load a float value into a register, then expand it to a double.
1225     void loadFloatAsDouble(const Address& addr, FloatRegister dest);
1226     void loadFloatAsDouble(const BaseIndex& src, FloatRegister dest);
1227 
1228     void loadFloat32(const Address& addr, FloatRegister dest);
1229     void loadFloat32(const BaseIndex& src, FloatRegister dest);
1230 
1231     void store8(Register src, const Address& address);
1232     void store8(Imm32 imm, const Address& address);
1233     void store8(Register src, const BaseIndex& address);
1234     void store8(Imm32 imm, const BaseIndex& address);
1235 
1236     void store16(Register src, const Address& address);
1237     void store16(Imm32 imm, const Address& address);
1238     void store16(Register src, const BaseIndex& address);
1239     void store16(Imm32 imm, const BaseIndex& address);
1240 
1241     void store32(Register src, AbsoluteAddress address);
1242     void store32(Register src, const Address& address);
1243     void store32(Register src, const BaseIndex& address);
1244     void store32(Imm32 src, const Address& address);
1245     void store32(Imm32 src, const BaseIndex& address);
1246 
1247     // NOTE: This will use second scratch on MIPS64. Only ARM needs the
1248     // implementation without second scratch.
store32_NoSecondScratch(Imm32 src,const Address & address)1249     void store32_NoSecondScratch(Imm32 src, const Address& address) {
1250         store32(src, address);
1251     }
1252 
store64(Register64 src,Address address)1253     void store64(Register64 src, Address address) {
1254         storePtr(src.reg, address);
1255     }
1256 
1257     template <typename T> void storePtr(ImmWord imm, T address);
1258     template <typename T> void storePtr(ImmPtr imm, T address);
1259     template <typename T> void storePtr(ImmGCPtr imm, T address);
1260     void storePtr(Register src, const Address& address);
1261     void storePtr(Register src, const BaseIndex& address);
1262     void storePtr(Register src, AbsoluteAddress dest);
storeDouble(FloatRegister src,Address addr)1263     void storeDouble(FloatRegister src, Address addr) {
1264         ma_sd(src, addr);
1265     }
storeDouble(FloatRegister src,BaseIndex addr)1266     void storeDouble(FloatRegister src, BaseIndex addr) {
1267         MOZ_ASSERT(addr.offset == 0);
1268         ma_sd(src, addr);
1269     }
moveDouble(FloatRegister src,FloatRegister dest)1270     void moveDouble(FloatRegister src, FloatRegister dest) {
1271         as_movd(dest, src);
1272     }
1273 
storeFloat32(FloatRegister src,Address addr)1274     void storeFloat32(FloatRegister src, Address addr) {
1275         ma_ss(src, addr);
1276     }
storeFloat32(FloatRegister src,BaseIndex addr)1277     void storeFloat32(FloatRegister src, BaseIndex addr) {
1278         MOZ_ASSERT(addr.offset == 0);
1279         ma_ss(src, addr);
1280     }
1281 
zeroDouble(FloatRegister reg)1282     void zeroDouble(FloatRegister reg) {
1283         moveToDouble(zero, reg);
1284     }
1285 
1286     void clampIntToUint8(Register reg);
1287 
1288     void subPtr(Imm32 imm, const Register dest);
1289     void subPtr(const Address& addr, const Register dest);
1290     void subPtr(Register src, const Address& dest);
1291     void addPtr(Imm32 imm, const Register dest);
1292     void addPtr(Imm32 imm, const Address& dest);
addPtr(ImmWord imm,const Register dest)1293     void addPtr(ImmWord imm, const Register dest) {
1294         movePtr(imm, ScratchRegister);
1295         addPtr(ScratchRegister, dest);
1296     }
addPtr(ImmPtr imm,const Register dest)1297     void addPtr(ImmPtr imm, const Register dest) {
1298         addPtr(ImmWord(uintptr_t(imm.value)), dest);
1299     }
mulBy3(const Register & src,const Register & dest)1300     void mulBy3(const Register& src, const Register& dest) {
1301         as_daddu(dest, src, src);
1302         as_daddu(dest, dest, src);
1303     }
1304 
mul64(Imm64 imm,const Register64 & dest)1305     void mul64(Imm64 imm, const Register64& dest) {
1306         MOZ_ASSERT(dest.reg != ScratchRegister);
1307         mov(ImmWord(imm.value), ScratchRegister);
1308         as_dmultu(dest.reg, ScratchRegister);
1309         as_mflo(dest.reg);
1310     }
1311 
1312     void convertUInt64ToDouble(Register64 src, Register temp, FloatRegister dest);
mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)1313     void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest) {
1314         movePtr(imm, ScratchRegister);
1315         loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
1316         mulDouble(ScratchDoubleReg, dest);
1317     }
1318 
1319     void breakpoint();
1320 
1321     void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
1322                       Label* label);
1323 
1324     void branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
1325                      Label* label);
1326 
1327     void checkStackAlignment();
1328 
1329     static void calculateAlignedStackPointer(void** stackPointer);
1330 
1331     // If source is a double, load it into dest. If source is int32,
1332     // convert it to double. Else, branch to failure.
1333     void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
1334 
1335     template <typename T1, typename T2>
cmpPtrSet(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1336     void cmpPtrSet(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest)
1337     {
1338         ma_cmp_set(dest, lhs, rhs, cond);
1339     }
1340     void cmpPtrSet(Assembler::Condition cond, Address lhs, ImmPtr rhs, Register dest);
1341     void cmpPtrSet(Assembler::Condition cond, Register lhs, Address rhs, Register dest);
1342 
1343     template <typename T1, typename T2>
cmp32Set(Assembler::Condition cond,T1 lhs,T2 rhs,Register dest)1344     void cmp32Set(Assembler::Condition cond, T1 lhs, T2 rhs, Register dest)
1345     {
1346         ma_cmp_set(dest, lhs, rhs, cond);
1347     }
1348     void cmp32Set(Assembler::Condition cond, Register lhs, Address rhs, Register dest);
1349 
1350   protected:
1351     bool buildOOLFakeExitFrame(void* fakeReturnAddr);
1352 
1353   public:
labelForPatch()1354     CodeOffset labelForPatch() {
1355         return CodeOffset(nextOffset().getOffset());
1356     }
1357 
memIntToValue(Address Source,Address Dest)1358     void memIntToValue(Address Source, Address Dest) {
1359         load32(Source, ScratchRegister);
1360         storeValue(JSVAL_TYPE_INT32, ScratchRegister, Dest);
1361     }
1362 
lea(Operand addr,Register dest)1363     void lea(Operand addr, Register dest) {
1364         ma_daddu(dest, addr.baseReg(), Imm32(addr.disp()));
1365     }
1366 
abiret()1367     void abiret() {
1368         as_jr(ra);
1369         as_nop();
1370     }
1371 
ma_BoundsCheck(Register bounded)1372     BufferOffset ma_BoundsCheck(Register bounded) {
1373         BufferOffset bo = m_buffer.nextOffset();
1374         ma_liPatchable(bounded, ImmWord(0));
1375         return bo;
1376     }
1377 
moveFloat32(FloatRegister src,FloatRegister dest)1378     void moveFloat32(FloatRegister src, FloatRegister dest) {
1379         as_movs(dest, src);
1380     }
1381 
1382     void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label* label);
1383     void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
1384                                     Label* label);
1385 
loadAsmJSActivation(Register dest)1386     void loadAsmJSActivation(Register dest) {
1387         loadPtr(Address(GlobalReg, wasm::ActivationGlobalDataOffset - AsmJSGlobalRegBias), dest);
1388     }
loadAsmJSHeapRegisterFromGlobalData()1389     void loadAsmJSHeapRegisterFromGlobalData() {
1390         MOZ_ASSERT(Imm16::IsInSignedRange(wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias));
1391         loadPtr(Address(GlobalReg, wasm::HeapGlobalDataOffset - AsmJSGlobalRegBias), HeapReg);
1392     }
1393 
1394     // Instrumentation for entering and leaving the profiler.
1395     void profilerEnterFrame(Register framePtr, Register scratch);
1396     void profilerExitFrame();
1397 };
1398 
1399 typedef MacroAssemblerMIPS64Compat MacroAssemblerSpecific;
1400 
1401 } // namespace jit
1402 } // namespace js
1403 
1404 #endif /* jit_mips64_MacroAssembler_mips64_h */
1405