1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
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_inl_h
8 #define jit_mips64_MacroAssembler_mips64_inl_h
9 
10 #include "jit/mips64/MacroAssembler-mips64.h"
11 
12 #include "vm/BigIntType.h"  // JS::BigInt
13 
14 #include "jit/mips-shared/MacroAssembler-mips-shared-inl.h"
15 
16 namespace js {
17 namespace jit {
18 
19 //{{{ check_macroassembler_style
20 
move64(Register64 src,Register64 dest)21 void MacroAssembler::move64(Register64 src, Register64 dest) {
22   movePtr(src.reg, dest.reg);
23 }
24 
move64(Imm64 imm,Register64 dest)25 void MacroAssembler::move64(Imm64 imm, Register64 dest) {
26   movePtr(ImmWord(imm.value), dest.reg);
27 }
28 
moveDoubleToGPR64(FloatRegister src,Register64 dest)29 void MacroAssembler::moveDoubleToGPR64(FloatRegister src, Register64 dest) {
30   moveFromDouble(src, dest.reg);
31 }
32 
moveGPR64ToDouble(Register64 src,FloatRegister dest)33 void MacroAssembler::moveGPR64ToDouble(Register64 src, FloatRegister dest) {
34   moveToDouble(src.reg, dest);
35 }
36 
move64To32(Register64 src,Register dest)37 void MacroAssembler::move64To32(Register64 src, Register dest) {
38   ma_sll(dest, src.reg, Imm32(0));
39 }
40 
move32To64ZeroExtend(Register src,Register64 dest)41 void MacroAssembler::move32To64ZeroExtend(Register src, Register64 dest) {
42   ma_dext(dest.reg, src, Imm32(0), Imm32(32));
43 }
44 
move8To64SignExtend(Register src,Register64 dest)45 void MacroAssembler::move8To64SignExtend(Register src, Register64 dest) {
46   move32To64SignExtend(src, dest);
47   move8SignExtend(dest.reg, dest.reg);
48 }
49 
move16To64SignExtend(Register src,Register64 dest)50 void MacroAssembler::move16To64SignExtend(Register src, Register64 dest) {
51   move32To64SignExtend(src, dest);
52   move16SignExtend(dest.reg, dest.reg);
53 }
54 
move32To64SignExtend(Register src,Register64 dest)55 void MacroAssembler::move32To64SignExtend(Register src, Register64 dest) {
56   ma_sll(dest.reg, src, Imm32(0));
57 }
58 
move32SignExtendToPtr(Register src,Register dest)59 void MacroAssembler::move32SignExtendToPtr(Register src, Register dest) {
60   ma_sll(dest, src, Imm32(0));
61 }
62 
move32ZeroExtendToPtr(Register src,Register dest)63 void MacroAssembler::move32ZeroExtendToPtr(Register src, Register dest) {
64   ma_dext(dest, src, Imm32(0), Imm32(32));
65 }
66 
67 // ===============================================================
68 // Load instructions
69 
load32SignExtendToPtr(const Address & src,Register dest)70 void MacroAssembler::load32SignExtendToPtr(const Address& src, Register dest) {
71   load32(src, dest);
72 }
73 
74 // ===============================================================
75 // Logical instructions
76 
notPtr(Register reg)77 void MacroAssembler::notPtr(Register reg) { ma_not(reg, reg); }
78 
andPtr(Register src,Register dest)79 void MacroAssembler::andPtr(Register src, Register dest) { ma_and(dest, src); }
80 
andPtr(Imm32 imm,Register dest)81 void MacroAssembler::andPtr(Imm32 imm, Register dest) { ma_and(dest, imm); }
82 
and64(Imm64 imm,Register64 dest)83 void MacroAssembler::and64(Imm64 imm, Register64 dest) {
84   ma_li(ScratchRegister, ImmWord(imm.value));
85   ma_and(dest.reg, ScratchRegister);
86 }
87 
and64(Register64 src,Register64 dest)88 void MacroAssembler::and64(Register64 src, Register64 dest) {
89   ma_and(dest.reg, src.reg);
90 }
91 
and64(const Operand & src,Register64 dest)92 void MacroAssembler::and64(const Operand& src, Register64 dest) {
93   if (src.getTag() == Operand::MEM) {
94     Register64 scratch(ScratchRegister);
95 
96     load64(src.toAddress(), scratch);
97     and64(scratch, dest);
98   } else {
99     and64(Register64(src.toReg()), dest);
100   }
101 }
102 
or64(Imm64 imm,Register64 dest)103 void MacroAssembler::or64(Imm64 imm, Register64 dest) {
104   ma_li(ScratchRegister, ImmWord(imm.value));
105   ma_or(dest.reg, ScratchRegister);
106 }
107 
xor64(Imm64 imm,Register64 dest)108 void MacroAssembler::xor64(Imm64 imm, Register64 dest) {
109   ma_li(ScratchRegister, ImmWord(imm.value));
110   ma_xor(dest.reg, ScratchRegister);
111 }
112 
orPtr(Register src,Register dest)113 void MacroAssembler::orPtr(Register src, Register dest) { ma_or(dest, src); }
114 
orPtr(Imm32 imm,Register dest)115 void MacroAssembler::orPtr(Imm32 imm, Register dest) { ma_or(dest, imm); }
116 
or64(Register64 src,Register64 dest)117 void MacroAssembler::or64(Register64 src, Register64 dest) {
118   ma_or(dest.reg, src.reg);
119 }
120 
or64(const Operand & src,Register64 dest)121 void MacroAssembler::or64(const Operand& src, Register64 dest) {
122   if (src.getTag() == Operand::MEM) {
123     Register64 scratch(ScratchRegister);
124 
125     load64(src.toAddress(), scratch);
126     or64(scratch, dest);
127   } else {
128     or64(Register64(src.toReg()), dest);
129   }
130 }
131 
xor64(Register64 src,Register64 dest)132 void MacroAssembler::xor64(Register64 src, Register64 dest) {
133   ma_xor(dest.reg, src.reg);
134 }
135 
xor64(const Operand & src,Register64 dest)136 void MacroAssembler::xor64(const Operand& src, Register64 dest) {
137   if (src.getTag() == Operand::MEM) {
138     Register64 scratch(ScratchRegister);
139 
140     load64(src.toAddress(), scratch);
141     xor64(scratch, dest);
142   } else {
143     xor64(Register64(src.toReg()), dest);
144   }
145 }
146 
xorPtr(Register src,Register dest)147 void MacroAssembler::xorPtr(Register src, Register dest) { ma_xor(dest, src); }
148 
xorPtr(Imm32 imm,Register dest)149 void MacroAssembler::xorPtr(Imm32 imm, Register dest) { ma_xor(dest, imm); }
150 
151 // ===============================================================
152 // Swap instructions
153 
byteSwap64(Register64 reg64)154 void MacroAssembler::byteSwap64(Register64 reg64) {
155   Register reg = reg64.reg;
156   ma_dsbh(reg, reg);
157   ma_dshd(reg, reg);
158 }
159 
160 // ===============================================================
161 // Arithmetic functions
162 
addPtr(Register src,Register dest)163 void MacroAssembler::addPtr(Register src, Register dest) {
164   ma_daddu(dest, src);
165 }
166 
addPtr(Imm32 imm,Register dest)167 void MacroAssembler::addPtr(Imm32 imm, Register dest) { ma_daddu(dest, imm); }
168 
addPtr(ImmWord imm,Register dest)169 void MacroAssembler::addPtr(ImmWord imm, Register dest) {
170   movePtr(imm, ScratchRegister);
171   addPtr(ScratchRegister, dest);
172 }
173 
add64(Register64 src,Register64 dest)174 void MacroAssembler::add64(Register64 src, Register64 dest) {
175   addPtr(src.reg, dest.reg);
176 }
177 
add64(const Operand & src,Register64 dest)178 void MacroAssembler::add64(const Operand& src, Register64 dest) {
179   if (src.getTag() == Operand::MEM) {
180     Register64 scratch(ScratchRegister);
181 
182     load64(src.toAddress(), scratch);
183     add64(scratch, dest);
184   } else {
185     add64(Register64(src.toReg()), dest);
186   }
187 }
188 
add64(Imm32 imm,Register64 dest)189 void MacroAssembler::add64(Imm32 imm, Register64 dest) {
190   ma_daddu(dest.reg, imm);
191 }
192 
add64(Imm64 imm,Register64 dest)193 void MacroAssembler::add64(Imm64 imm, Register64 dest) {
194   MOZ_ASSERT(dest.reg != ScratchRegister);
195   mov(ImmWord(imm.value), ScratchRegister);
196   ma_daddu(dest.reg, ScratchRegister);
197 }
198 
sub32FromStackPtrWithPatch(Register dest)199 CodeOffset MacroAssembler::sub32FromStackPtrWithPatch(Register dest) {
200   CodeOffset offset = CodeOffset(currentOffset());
201   MacroAssemblerMIPSShared::ma_liPatchable(dest, Imm32(0));
202   as_dsubu(dest, StackPointer, dest);
203   return offset;
204 }
205 
patchSub32FromStackPtr(CodeOffset offset,Imm32 imm)206 void MacroAssembler::patchSub32FromStackPtr(CodeOffset offset, Imm32 imm) {
207   Instruction* lui =
208       (Instruction*)m_buffer.getInst(BufferOffset(offset.offset()));
209   MOZ_ASSERT(lui->extractOpcode() == ((uint32_t)op_lui >> OpcodeShift));
210   MOZ_ASSERT(lui->next()->extractOpcode() == ((uint32_t)op_ori >> OpcodeShift));
211 
212   MacroAssemblerMIPSShared::UpdateLuiOriValue(lui, lui->next(), imm.value);
213 }
214 
subPtr(Register src,Register dest)215 void MacroAssembler::subPtr(Register src, Register dest) {
216   as_dsubu(dest, dest, src);
217 }
218 
subPtr(Imm32 imm,Register dest)219 void MacroAssembler::subPtr(Imm32 imm, Register dest) {
220   ma_dsubu(dest, dest, imm);
221 }
222 
sub64(Register64 src,Register64 dest)223 void MacroAssembler::sub64(Register64 src, Register64 dest) {
224   as_dsubu(dest.reg, dest.reg, src.reg);
225 }
226 
sub64(const Operand & src,Register64 dest)227 void MacroAssembler::sub64(const Operand& src, Register64 dest) {
228   if (src.getTag() == Operand::MEM) {
229     Register64 scratch(ScratchRegister);
230 
231     load64(src.toAddress(), scratch);
232     sub64(scratch, dest);
233   } else {
234     sub64(Register64(src.toReg()), dest);
235   }
236 }
237 
sub64(Imm64 imm,Register64 dest)238 void MacroAssembler::sub64(Imm64 imm, Register64 dest) {
239   MOZ_ASSERT(dest.reg != ScratchRegister);
240   mov(ImmWord(imm.value), ScratchRegister);
241   as_dsubu(dest.reg, dest.reg, ScratchRegister);
242 }
243 
mulPtr(Register rhs,Register srcDest)244 void MacroAssembler::mulPtr(Register rhs, Register srcDest) {
245 #ifdef MIPSR6
246   as_dmulu(srcDest, srcDest, rhs);
247 #else
248   as_dmultu(srcDest, rhs);
249   as_mflo(srcDest);
250 #endif
251 }
252 
mul64(Imm64 imm,const Register64 & dest)253 void MacroAssembler::mul64(Imm64 imm, const Register64& dest) {
254   MOZ_ASSERT(dest.reg != ScratchRegister);
255   mov(ImmWord(imm.value), ScratchRegister);
256 #ifdef MIPSR6
257   as_dmulu(dest.reg, ScratchRegister, dest.reg);
258 #else
259   as_dmultu(dest.reg, ScratchRegister);
260   as_mflo(dest.reg);
261 #endif
262 }
263 
mul64(Imm64 imm,const Register64 & dest,const Register temp)264 void MacroAssembler::mul64(Imm64 imm, const Register64& dest,
265                            const Register temp) {
266   MOZ_ASSERT(temp == InvalidReg);
267   mul64(imm, dest);
268 }
269 
mul64(const Register64 & src,const Register64 & dest,const Register temp)270 void MacroAssembler::mul64(const Register64& src, const Register64& dest,
271                            const Register temp) {
272   MOZ_ASSERT(temp == InvalidReg);
273 #ifdef MIPSR6
274   as_dmulu(dest.reg, src.reg, dest.reg);
275 #else
276   as_dmultu(dest.reg, src.reg);
277   as_mflo(dest.reg);
278 #endif
279 }
280 
mul64(const Operand & src,const Register64 & dest,const Register temp)281 void MacroAssembler::mul64(const Operand& src, const Register64& dest,
282                            const Register temp) {
283   if (src.getTag() == Operand::MEM) {
284     Register64 scratch(ScratchRegister);
285 
286     load64(src.toAddress(), scratch);
287     mul64(scratch, dest, temp);
288   } else {
289     mul64(Register64(src.toReg()), dest, temp);
290   }
291 }
292 
mulBy3(Register src,Register dest)293 void MacroAssembler::mulBy3(Register src, Register dest) {
294   MOZ_ASSERT(src != ScratchRegister);
295   as_daddu(ScratchRegister, src, src);
296   as_daddu(dest, ScratchRegister, src);
297 }
298 
inc64(AbsoluteAddress dest)299 void MacroAssembler::inc64(AbsoluteAddress dest) {
300   ma_li(ScratchRegister, ImmWord(uintptr_t(dest.addr)));
301   as_ld(SecondScratchReg, ScratchRegister, 0);
302   as_daddiu(SecondScratchReg, SecondScratchReg, 1);
303   as_sd(SecondScratchReg, ScratchRegister, 0);
304 }
305 
neg64(Register64 reg)306 void MacroAssembler::neg64(Register64 reg) { as_dsubu(reg.reg, zero, reg.reg); }
307 
negPtr(Register reg)308 void MacroAssembler::negPtr(Register reg) { as_dsubu(reg, zero, reg); }
309 
310 // ===============================================================
311 // Shift functions
312 
lshiftPtr(Imm32 imm,Register dest)313 void MacroAssembler::lshiftPtr(Imm32 imm, Register dest) {
314   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
315   ma_dsll(dest, dest, imm);
316 }
317 
lshiftPtr(Register shift,Register dest)318 void MacroAssembler::lshiftPtr(Register shift, Register dest) {
319   ma_dsll(dest, dest, shift);
320 }
321 
lshift64(Imm32 imm,Register64 dest)322 void MacroAssembler::lshift64(Imm32 imm, Register64 dest) {
323   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
324   ma_dsll(dest.reg, dest.reg, imm);
325 }
326 
lshift64(Register shift,Register64 dest)327 void MacroAssembler::lshift64(Register shift, Register64 dest) {
328   ma_dsll(dest.reg, dest.reg, shift);
329 }
330 
rshiftPtr(Imm32 imm,Register dest)331 void MacroAssembler::rshiftPtr(Imm32 imm, Register dest) {
332   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
333   ma_dsrl(dest, dest, imm);
334 }
335 
rshiftPtr(Register shift,Register dest)336 void MacroAssembler::rshiftPtr(Register shift, Register dest) {
337   ma_dsrl(dest, dest, shift);
338 }
339 
rshift64(Imm32 imm,Register64 dest)340 void MacroAssembler::rshift64(Imm32 imm, Register64 dest) {
341   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
342   ma_dsrl(dest.reg, dest.reg, imm);
343 }
344 
rshift64(Register shift,Register64 dest)345 void MacroAssembler::rshift64(Register shift, Register64 dest) {
346   ma_dsrl(dest.reg, dest.reg, shift);
347 }
348 
rshiftPtrArithmetic(Imm32 imm,Register dest)349 void MacroAssembler::rshiftPtrArithmetic(Imm32 imm, Register dest) {
350   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
351   ma_dsra(dest, dest, imm);
352 }
353 
rshift64Arithmetic(Imm32 imm,Register64 dest)354 void MacroAssembler::rshift64Arithmetic(Imm32 imm, Register64 dest) {
355   MOZ_ASSERT(0 <= imm.value && imm.value < 64);
356   ma_dsra(dest.reg, dest.reg, imm);
357 }
358 
rshift64Arithmetic(Register shift,Register64 dest)359 void MacroAssembler::rshift64Arithmetic(Register shift, Register64 dest) {
360   ma_dsra(dest.reg, dest.reg, shift);
361 }
362 
363 // ===============================================================
364 // Rotation functions
365 
rotateLeft64(Imm32 count,Register64 src,Register64 dest,Register temp)366 void MacroAssembler::rotateLeft64(Imm32 count, Register64 src, Register64 dest,
367                                   Register temp) {
368   MOZ_ASSERT(temp == InvalidReg);
369 
370   if (count.value) {
371     ma_drol(dest.reg, src.reg, count);
372   } else {
373     ma_move(dest.reg, src.reg);
374   }
375 }
376 
rotateLeft64(Register count,Register64 src,Register64 dest,Register temp)377 void MacroAssembler::rotateLeft64(Register count, Register64 src,
378                                   Register64 dest, Register temp) {
379   MOZ_ASSERT(temp == InvalidReg);
380   ma_drol(dest.reg, src.reg, count);
381 }
382 
rotateRight64(Imm32 count,Register64 src,Register64 dest,Register temp)383 void MacroAssembler::rotateRight64(Imm32 count, Register64 src, Register64 dest,
384                                    Register temp) {
385   MOZ_ASSERT(temp == InvalidReg);
386 
387   if (count.value) {
388     ma_dror(dest.reg, src.reg, count);
389   } else {
390     ma_move(dest.reg, src.reg);
391   }
392 }
393 
rotateRight64(Register count,Register64 src,Register64 dest,Register temp)394 void MacroAssembler::rotateRight64(Register count, Register64 src,
395                                    Register64 dest, Register temp) {
396   MOZ_ASSERT(temp == InvalidReg);
397   ma_dror(dest.reg, src.reg, count);
398 }
399 
400 // ===============================================================
401 // Condition functions
402 
403 template <typename T1, typename T2>
cmpPtrSet(Condition cond,T1 lhs,T2 rhs,Register dest)404 void MacroAssembler::cmpPtrSet(Condition cond, T1 lhs, T2 rhs, Register dest) {
405   ma_cmp_set(dest, lhs, rhs, cond);
406 }
407 
408 // Also see below for specializations of cmpPtrSet.
409 
410 template <typename T1, typename T2>
cmp32Set(Condition cond,T1 lhs,T2 rhs,Register dest)411 void MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest) {
412   ma_cmp_set(dest, lhs, rhs, cond);
413 }
414 
415 // ===============================================================
416 // Bit counting functions
417 
clz64(Register64 src,Register dest)418 void MacroAssembler::clz64(Register64 src, Register dest) {
419   as_dclz(dest, src.reg);
420 }
421 
ctz64(Register64 src,Register dest)422 void MacroAssembler::ctz64(Register64 src, Register dest) {
423   ma_dctz(dest, src.reg);
424 }
425 
popcnt64(Register64 input,Register64 output,Register tmp)426 void MacroAssembler::popcnt64(Register64 input, Register64 output,
427                               Register tmp) {
428   ma_move(output.reg, input.reg);
429   ma_dsra(tmp, input.reg, Imm32(1));
430   ma_li(ScratchRegister, ImmWord(0x5555555555555555UL));
431   ma_and(tmp, ScratchRegister);
432   ma_dsubu(output.reg, tmp);
433   ma_dsra(tmp, output.reg, Imm32(2));
434   ma_li(ScratchRegister, ImmWord(0x3333333333333333UL));
435   ma_and(output.reg, ScratchRegister);
436   ma_and(tmp, ScratchRegister);
437   ma_daddu(output.reg, tmp);
438   ma_dsrl(tmp, output.reg, Imm32(4));
439   ma_daddu(output.reg, tmp);
440   ma_li(ScratchRegister, ImmWord(0xF0F0F0F0F0F0F0FUL));
441   ma_and(output.reg, ScratchRegister);
442   ma_dsll(tmp, output.reg, Imm32(8));
443   ma_daddu(output.reg, tmp);
444   ma_dsll(tmp, output.reg, Imm32(16));
445   ma_daddu(output.reg, tmp);
446   ma_dsll(tmp, output.reg, Imm32(32));
447   ma_daddu(output.reg, tmp);
448   ma_dsra(output.reg, output.reg, Imm32(56));
449 }
450 
451 // ===============================================================
452 // Branch functions
453 
branch64(Condition cond,Register64 lhs,Imm64 val,Label * success,Label * fail)454 void MacroAssembler::branch64(Condition cond, Register64 lhs, Imm64 val,
455                               Label* success, Label* fail) {
456   MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
457                  cond == Assembler::LessThan ||
458                  cond == Assembler::LessThanOrEqual ||
459                  cond == Assembler::GreaterThan ||
460                  cond == Assembler::GreaterThanOrEqual ||
461                  cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
462                  cond == Assembler::Above || cond == Assembler::AboveOrEqual,
463              "other condition codes not supported");
464 
465   branchPtr(cond, lhs.reg, ImmWord(val.value), success);
466   if (fail) {
467     jump(fail);
468   }
469 }
470 
branch64(Condition cond,Register64 lhs,Register64 rhs,Label * success,Label * fail)471 void MacroAssembler::branch64(Condition cond, Register64 lhs, Register64 rhs,
472                               Label* success, Label* fail) {
473   MOZ_ASSERT(cond == Assembler::NotEqual || cond == Assembler::Equal ||
474                  cond == Assembler::LessThan ||
475                  cond == Assembler::LessThanOrEqual ||
476                  cond == Assembler::GreaterThan ||
477                  cond == Assembler::GreaterThanOrEqual ||
478                  cond == Assembler::Below || cond == Assembler::BelowOrEqual ||
479                  cond == Assembler::Above || cond == Assembler::AboveOrEqual,
480              "other condition codes not supported");
481 
482   branchPtr(cond, lhs.reg, rhs.reg, success);
483   if (fail) {
484     jump(fail);
485   }
486 }
487 
branch64(Condition cond,const Address & lhs,Imm64 val,Label * label)488 void MacroAssembler::branch64(Condition cond, const Address& lhs, Imm64 val,
489                               Label* label) {
490   MOZ_ASSERT(cond == Assembler::NotEqual,
491              "other condition codes not supported");
492 
493   branchPtr(cond, lhs, ImmWord(val.value), label);
494 }
495 
branch64(Condition cond,const Address & lhs,const Address & rhs,Register scratch,Label * label)496 void MacroAssembler::branch64(Condition cond, const Address& lhs,
497                               const Address& rhs, Register scratch,
498                               Label* label) {
499   MOZ_ASSERT(cond == Assembler::NotEqual,
500              "other condition codes not supported");
501   MOZ_ASSERT(lhs.base != scratch);
502   MOZ_ASSERT(rhs.base != scratch);
503 
504   loadPtr(rhs, scratch);
505   branchPtr(cond, lhs, scratch, label);
506 }
507 
branchPrivatePtr(Condition cond,const Address & lhs,Register rhs,Label * label)508 void MacroAssembler::branchPrivatePtr(Condition cond, const Address& lhs,
509                                       Register rhs, Label* label) {
510   branchPtr(cond, lhs, rhs, label);
511 }
512 
513 template <class L>
branchTest64(Condition cond,Register64 lhs,Register64 rhs,Register temp,L label)514 void MacroAssembler::branchTest64(Condition cond, Register64 lhs,
515                                   Register64 rhs, Register temp, L label) {
516   branchTestPtr(cond, lhs.reg, rhs.reg, label);
517 }
518 
branchTestUndefined(Condition cond,const ValueOperand & value,Label * label)519 void MacroAssembler::branchTestUndefined(Condition cond,
520                                          const ValueOperand& value,
521                                          Label* label) {
522   SecondScratchRegisterScope scratch2(*this);
523   splitTag(value, scratch2);
524   branchTestUndefined(cond, scratch2, label);
525 }
526 
branchTestInt32(Condition cond,const ValueOperand & value,Label * label)527 void MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value,
528                                      Label* label) {
529   SecondScratchRegisterScope scratch2(*this);
530   splitTag(value, scratch2);
531   branchTestInt32(cond, scratch2, label);
532 }
533 
branchTestInt32Truthy(bool b,const ValueOperand & value,Label * label)534 void MacroAssembler::branchTestInt32Truthy(bool b, const ValueOperand& value,
535                                            Label* label) {
536   ScratchRegisterScope scratch(*this);
537   ma_dext(scratch, value.valueReg(), Imm32(0), Imm32(32));
538   ma_b(scratch, scratch, label, b ? NonZero : Zero);
539 }
540 
branchTestDouble(Condition cond,Register tag,Label * label)541 void MacroAssembler::branchTestDouble(Condition cond, Register tag,
542                                       Label* label) {
543   MOZ_ASSERT(cond == Equal || cond == NotEqual);
544   Condition actual = (cond == Equal) ? BelowOrEqual : Above;
545   ma_b(tag, ImmTag(JSVAL_TAG_MAX_DOUBLE), label, actual);
546 }
547 
branchTestDouble(Condition cond,const ValueOperand & value,Label * label)548 void MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value,
549                                       Label* label) {
550   SecondScratchRegisterScope scratch2(*this);
551   splitTag(value, scratch2);
552   branchTestDouble(cond, scratch2, label);
553 }
554 
branchTestNumber(Condition cond,const ValueOperand & value,Label * label)555 void MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value,
556                                       Label* label) {
557   SecondScratchRegisterScope scratch2(*this);
558   splitTag(value, scratch2);
559   branchTestNumber(cond, scratch2, label);
560 }
561 
branchTestBoolean(Condition cond,const ValueOperand & value,Label * label)562 void MacroAssembler::branchTestBoolean(Condition cond,
563                                        const ValueOperand& value,
564                                        Label* label) {
565   SecondScratchRegisterScope scratch2(*this);
566   splitTag(value, scratch2);
567   branchTestBoolean(cond, scratch2, label);
568 }
569 
branchTestBooleanTruthy(bool b,const ValueOperand & value,Label * label)570 void MacroAssembler::branchTestBooleanTruthy(bool b, const ValueOperand& value,
571                                              Label* label) {
572   SecondScratchRegisterScope scratch2(*this);
573   unboxBoolean(value, scratch2);
574   ma_b(scratch2, scratch2, label, b ? NonZero : Zero);
575 }
576 
branchTestString(Condition cond,const ValueOperand & value,Label * label)577 void MacroAssembler::branchTestString(Condition cond, const ValueOperand& value,
578                                       Label* label) {
579   SecondScratchRegisterScope scratch2(*this);
580   splitTag(value, scratch2);
581   branchTestString(cond, scratch2, label);
582 }
583 
branchTestStringTruthy(bool b,const ValueOperand & value,Label * label)584 void MacroAssembler::branchTestStringTruthy(bool b, const ValueOperand& value,
585                                             Label* label) {
586   SecondScratchRegisterScope scratch2(*this);
587   unboxString(value, scratch2);
588   load32(Address(scratch2, JSString::offsetOfLength()), scratch2);
589   ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
590 }
591 
branchTestSymbol(Condition cond,const ValueOperand & value,Label * label)592 void MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value,
593                                       Label* label) {
594   SecondScratchRegisterScope scratch2(*this);
595   splitTag(value, scratch2);
596   branchTestSymbol(cond, scratch2, label);
597 }
598 
branchTestBigInt(Condition cond,const BaseIndex & address,Label * label)599 void MacroAssembler::branchTestBigInt(Condition cond, const BaseIndex& address,
600                                       Label* label) {
601   SecondScratchRegisterScope scratch2(*this);
602   computeEffectiveAddress(address, scratch2);
603   splitTag(scratch2, scratch2);
604   branchTestBigInt(cond, scratch2, label);
605 }
606 
branchTestBigInt(Condition cond,const ValueOperand & value,Label * label)607 void MacroAssembler::branchTestBigInt(Condition cond, const ValueOperand& value,
608                                       Label* label) {
609   SecondScratchRegisterScope scratch2(*this);
610   splitTag(value, scratch2);
611   branchTestBigInt(cond, scratch2, label);
612 }
613 
branchTestBigIntTruthy(bool b,const ValueOperand & value,Label * label)614 void MacroAssembler::branchTestBigIntTruthy(bool b, const ValueOperand& value,
615                                             Label* label) {
616   SecondScratchRegisterScope scratch2(*this);
617   unboxBigInt(value, scratch2);
618   load32(Address(scratch2, BigInt::offsetOfDigitLength()), scratch2);
619   ma_b(scratch2, Imm32(0), label, b ? NotEqual : Equal);
620 }
621 
branchTestNull(Condition cond,const ValueOperand & value,Label * label)622 void MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value,
623                                     Label* label) {
624   SecondScratchRegisterScope scratch2(*this);
625   splitTag(value, scratch2);
626   branchTestNull(cond, scratch2, label);
627 }
628 
branchTestObject(Condition cond,const ValueOperand & value,Label * label)629 void MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value,
630                                       Label* label) {
631   SecondScratchRegisterScope scratch2(*this);
632   splitTag(value, scratch2);
633   branchTestObject(cond, scratch2, label);
634 }
635 
branchTestPrimitive(Condition cond,const ValueOperand & value,Label * label)636 void MacroAssembler::branchTestPrimitive(Condition cond,
637                                          const ValueOperand& value,
638                                          Label* label) {
639   SecondScratchRegisterScope scratch2(*this);
640   splitTag(value, scratch2);
641   branchTestPrimitive(cond, scratch2, label);
642 }
643 
644 template <class L>
branchTestMagic(Condition cond,const ValueOperand & value,L label)645 void MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value,
646                                      L label) {
647   SecondScratchRegisterScope scratch2(*this);
648   splitTag(value, scratch2);
649   ma_b(scratch2, ImmTag(JSVAL_TAG_MAGIC), label, cond);
650 }
651 
branchTestMagic(Condition cond,const Address & valaddr,JSWhyMagic why,Label * label)652 void MacroAssembler::branchTestMagic(Condition cond, const Address& valaddr,
653                                      JSWhyMagic why, Label* label) {
654   uint64_t magic = MagicValue(why).asRawBits();
655   SecondScratchRegisterScope scratch(*this);
656   loadPtr(valaddr, scratch);
657   ma_b(scratch, ImmWord(magic), label, cond);
658 }
659 
branchTestValue(Condition cond,const BaseIndex & lhs,const ValueOperand & rhs,Label * label)660 void MacroAssembler::branchTestValue(Condition cond, const BaseIndex& lhs,
661                                      const ValueOperand& rhs, Label* label) {
662   MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
663   branchPtr(cond, lhs, rhs.valueReg(), label);
664 }
665 
branchTruncateDoubleMaybeModUint32(FloatRegister src,Register dest,Label * fail)666 void MacroAssembler::branchTruncateDoubleMaybeModUint32(FloatRegister src,
667                                                         Register dest,
668                                                         Label* fail) {
669   as_truncld(ScratchDoubleReg, src);
670   as_cfc1(ScratchRegister, Assembler::FCSR);
671   moveFromDouble(ScratchDoubleReg, dest);
672   ma_ext(ScratchRegister, ScratchRegister, Assembler::CauseV, 1);
673   ma_b(ScratchRegister, Imm32(0), fail, Assembler::NotEqual);
674 
675   as_sll(dest, dest, 0);
676 }
677 
branchTruncateFloat32MaybeModUint32(FloatRegister src,Register dest,Label * fail)678 void MacroAssembler::branchTruncateFloat32MaybeModUint32(FloatRegister src,
679                                                          Register dest,
680                                                          Label* fail) {
681   as_truncls(ScratchDoubleReg, src);
682   as_cfc1(ScratchRegister, Assembler::FCSR);
683   moveFromDouble(ScratchDoubleReg, dest);
684   ma_ext(ScratchRegister, ScratchRegister, Assembler::CauseV, 1);
685   ma_b(ScratchRegister, Imm32(0), fail, Assembler::NotEqual);
686 
687   as_sll(dest, dest, 0);
688 }
689 
fallibleUnboxPtr(const ValueOperand & src,Register dest,JSValueType type,Label * fail)690 void MacroAssembler::fallibleUnboxPtr(const ValueOperand& src, Register dest,
691                                       JSValueType type, Label* fail) {
692   MOZ_ASSERT(type == JSVAL_TYPE_OBJECT || type == JSVAL_TYPE_STRING ||
693              type == JSVAL_TYPE_SYMBOL || type == JSVAL_TYPE_BIGINT);
694   // dest := src XOR mask
695   // scratch := dest >> JSVAL_TAG_SHIFT
696   // fail if scratch != 0
697   //
698   // Note: src and dest can be the same register
699   ScratchRegisterScope scratch(asMasm());
700   mov(ImmWord(JSVAL_TYPE_TO_SHIFTED_TAG(type)), scratch);
701   ma_xor(scratch, src.valueReg());
702   ma_move(dest, scratch);
703   ma_dsrl(scratch, scratch, Imm32(JSVAL_TAG_SHIFT));
704   ma_b(scratch, Imm32(0), fail, Assembler::NotEqual);
705 }
706 
fallibleUnboxPtr(const Address & src,Register dest,JSValueType type,Label * fail)707 void MacroAssembler::fallibleUnboxPtr(const Address& src, Register dest,
708                                       JSValueType type, Label* fail) {
709   loadValue(src, ValueOperand(dest));
710   fallibleUnboxPtr(ValueOperand(dest), dest, type, fail);
711 }
712 
fallibleUnboxPtr(const BaseIndex & src,Register dest,JSValueType type,Label * fail)713 void MacroAssembler::fallibleUnboxPtr(const BaseIndex& src, Register dest,
714                                       JSValueType type, Label* fail) {
715   loadValue(src, ValueOperand(dest));
716   fallibleUnboxPtr(ValueOperand(dest), dest, type, fail);
717 }
718 
719 //}}} check_macroassembler_style
720 // ===============================================================
721 
722 // The specializations for cmpPtrSet are outside the braces because
723 // check_macroassembler_style can't yet deal with specializations.
724 
725 template <>
cmpPtrSet(Assembler::Condition cond,Address lhs,ImmPtr rhs,Register dest)726 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs,
727                                       ImmPtr rhs, Register dest) {
728   loadPtr(lhs, SecondScratchReg);
729   cmpPtrSet(cond, SecondScratchReg, rhs, dest);
730 }
731 
732 template <>
cmpPtrSet(Assembler::Condition cond,Register lhs,Address rhs,Register dest)733 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Register lhs,
734                                       Address rhs, Register dest) {
735   MOZ_ASSERT(lhs != ScratchRegister);
736   loadPtr(rhs, ScratchRegister);
737   cmpPtrSet(cond, lhs, ScratchRegister, dest);
738 }
739 
740 template <>
cmpPtrSet(Assembler::Condition cond,Address lhs,Register rhs,Register dest)741 inline void MacroAssembler::cmpPtrSet(Assembler::Condition cond, Address lhs,
742                                       Register rhs, Register dest) {
743   MOZ_ASSERT(rhs != ScratchRegister);
744   loadPtr(lhs, ScratchRegister);
745   cmpPtrSet(cond, ScratchRegister, rhs, dest);
746 }
747 
748 template <>
cmp32Set(Assembler::Condition cond,Register lhs,Address rhs,Register dest)749 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Register lhs,
750                                      Address rhs, Register dest) {
751   MOZ_ASSERT(lhs != ScratchRegister);
752   load32(rhs, ScratchRegister);
753   cmp32Set(cond, lhs, ScratchRegister, dest);
754 }
755 
756 template <>
cmp32Set(Assembler::Condition cond,Address lhs,Register rhs,Register dest)757 inline void MacroAssembler::cmp32Set(Assembler::Condition cond, Address lhs,
758                                      Register rhs, Register dest) {
759   MOZ_ASSERT(rhs != ScratchRegister);
760   load32(lhs, ScratchRegister);
761   cmp32Set(cond, ScratchRegister, rhs, dest);
762 }
763 
cmpPtrMovePtr(Condition cond,Register lhs,Register rhs,Register src,Register dest)764 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs, Register rhs,
765                                    Register src, Register dest) {
766   Register scratch = ScratchRegister;
767   MOZ_ASSERT(src != scratch && dest != scratch);
768   cmpPtrSet(cond, lhs, rhs, scratch);
769 #ifdef MIPSR6
770   as_selnez(src, src, scratch);
771   as_seleqz(dest, dest, scratch);
772   as_or(dest, dest, src);
773 #else
774   as_movn(dest, src, scratch);
775 #endif
776 }
777 
cmpPtrMovePtr(Condition cond,Register lhs,const Address & rhs,Register src,Register dest)778 void MacroAssembler::cmpPtrMovePtr(Condition cond, Register lhs,
779                                    const Address& rhs, Register src,
780                                    Register dest) {
781   MOZ_CRASH("NYI");
782 }
783 
incrementInt32Value(const Address & addr)784 void MacroAssemblerMIPS64Compat::incrementInt32Value(const Address& addr) {
785   asMasm().add32(Imm32(1), addr);
786 }
787 
retn(Imm32 n)788 void MacroAssemblerMIPS64Compat::retn(Imm32 n) {
789   // pc <- [sp]; sp += n
790   loadPtr(Address(StackPointer, 0), ra);
791   asMasm().addPtr(n, StackPointer);
792   as_jr(ra);
793   as_nop();
794 }
795 
796 }  // namespace jit
797 }  // namespace js
798 
799 #endif /* jit_mips64_MacroAssembler_mips64_inl_h */
800