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_mips_shared_MacroAssembler_mips_shared_inl_h
8 #define jit_mips_shared_MacroAssembler_mips_shared_inl_h
9 
10 #include "jit/mips-shared/MacroAssembler-mips-shared.h"
11 
12 namespace js {
13 namespace jit {
14 
15 //{{{ check_macroassembler_style
16 
moveFloat32ToGPR(FloatRegister src,Register dest)17 void MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest) {
18   moveFromFloat32(src, dest);
19 }
20 
moveGPRToFloat32(Register src,FloatRegister dest)21 void MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest) {
22   moveToFloat32(src, dest);
23 }
24 
move8SignExtend(Register src,Register dest)25 void MacroAssembler::move8SignExtend(Register src, Register dest) {
26   ma_seb(dest, src);
27 }
28 
move16SignExtend(Register src,Register dest)29 void MacroAssembler::move16SignExtend(Register src, Register dest) {
30   ma_seh(dest, src);
31 }
32 
loadAbiReturnAddress(Register dest)33 void MacroAssembler::loadAbiReturnAddress(Register dest) { movePtr(ra, dest); }
34 
35 // ===============================================================
36 // Logical instructions
37 
not32(Register reg)38 void MacroAssembler::not32(Register reg) { ma_not(reg, reg); }
39 
and32(Register src,Register dest)40 void MacroAssembler::and32(Register src, Register dest) {
41   as_and(dest, dest, src);
42 }
43 
and32(Imm32 imm,Register dest)44 void MacroAssembler::and32(Imm32 imm, Register dest) { ma_and(dest, imm); }
45 
and32(Imm32 imm,const Address & dest)46 void MacroAssembler::and32(Imm32 imm, const Address& dest) {
47   load32(dest, SecondScratchReg);
48   ma_and(SecondScratchReg, imm);
49   store32(SecondScratchReg, dest);
50 }
51 
and32(const Address & src,Register dest)52 void MacroAssembler::and32(const Address& src, Register dest) {
53   load32(src, SecondScratchReg);
54   ma_and(dest, SecondScratchReg);
55 }
56 
or32(Register src,Register dest)57 void MacroAssembler::or32(Register src, Register dest) { ma_or(dest, src); }
58 
or32(Imm32 imm,Register dest)59 void MacroAssembler::or32(Imm32 imm, Register dest) { ma_or(dest, imm); }
60 
or32(Imm32 imm,const Address & dest)61 void MacroAssembler::or32(Imm32 imm, const Address& dest) {
62   load32(dest, SecondScratchReg);
63   ma_or(SecondScratchReg, imm);
64   store32(SecondScratchReg, dest);
65 }
66 
xor32(Register src,Register dest)67 void MacroAssembler::xor32(Register src, Register dest) { ma_xor(dest, src); }
68 
xor32(Imm32 imm,Register dest)69 void MacroAssembler::xor32(Imm32 imm, Register dest) { ma_xor(dest, imm); }
70 
71 // ===============================================================
72 // Swap instructions
73 
byteSwap16SignExtend(Register reg)74 void MacroAssembler::byteSwap16SignExtend(Register reg) {
75   ma_wsbh(reg, reg);
76   ma_seh(reg, reg);
77 }
78 
byteSwap16ZeroExtend(Register reg)79 void MacroAssembler::byteSwap16ZeroExtend(Register reg) {
80   ma_wsbh(reg, reg);
81   ma_and(reg, Imm32(0xFFFF));
82 }
83 
byteSwap32(Register reg)84 void MacroAssembler::byteSwap32(Register reg) {
85   ma_wsbh(reg, reg);
86   as_rotr(reg, reg, 16);
87 }
88 
89 // ===============================================================
90 // Arithmetic instructions
91 
add32(Register src,Register dest)92 void MacroAssembler::add32(Register src, Register dest) {
93   as_addu(dest, dest, src);
94 }
95 
add32(Imm32 imm,Register dest)96 void MacroAssembler::add32(Imm32 imm, Register dest) {
97   ma_addu(dest, dest, imm);
98 }
99 
add32(Imm32 imm,const Address & dest)100 void MacroAssembler::add32(Imm32 imm, const Address& dest) {
101   load32(dest, SecondScratchReg);
102   ma_addu(SecondScratchReg, imm);
103   store32(SecondScratchReg, dest);
104 }
105 
addPtr(Imm32 imm,const Address & dest)106 void MacroAssembler::addPtr(Imm32 imm, const Address& dest) {
107   loadPtr(dest, ScratchRegister);
108   addPtr(imm, ScratchRegister);
109   storePtr(ScratchRegister, dest);
110 }
111 
addPtr(const Address & src,Register dest)112 void MacroAssembler::addPtr(const Address& src, Register dest) {
113   loadPtr(src, ScratchRegister);
114   addPtr(ScratchRegister, dest);
115 }
116 
addDouble(FloatRegister src,FloatRegister dest)117 void MacroAssembler::addDouble(FloatRegister src, FloatRegister dest) {
118   as_addd(dest, dest, src);
119 }
120 
addFloat32(FloatRegister src,FloatRegister dest)121 void MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest) {
122   as_adds(dest, dest, src);
123 }
124 
sub32(Register src,Register dest)125 void MacroAssembler::sub32(Register src, Register dest) {
126   as_subu(dest, dest, src);
127 }
128 
sub32(Imm32 imm,Register dest)129 void MacroAssembler::sub32(Imm32 imm, Register dest) {
130   ma_subu(dest, dest, imm);
131 }
132 
sub32(const Address & src,Register dest)133 void MacroAssembler::sub32(const Address& src, Register dest) {
134   load32(src, SecondScratchReg);
135   as_subu(dest, dest, SecondScratchReg);
136 }
137 
subPtr(Register src,const Address & dest)138 void MacroAssembler::subPtr(Register src, const Address& dest) {
139   loadPtr(dest, SecondScratchReg);
140   subPtr(src, SecondScratchReg);
141   storePtr(SecondScratchReg, dest);
142 }
143 
subPtr(const Address & addr,Register dest)144 void MacroAssembler::subPtr(const Address& addr, Register dest) {
145   loadPtr(addr, SecondScratchReg);
146   subPtr(SecondScratchReg, dest);
147 }
148 
subDouble(FloatRegister src,FloatRegister dest)149 void MacroAssembler::subDouble(FloatRegister src, FloatRegister dest) {
150   as_subd(dest, dest, src);
151 }
152 
subFloat32(FloatRegister src,FloatRegister dest)153 void MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest) {
154   as_subs(dest, dest, src);
155 }
156 
mul32(Register rhs,Register srcDest)157 void MacroAssembler::mul32(Register rhs, Register srcDest) {
158   as_mul(srcDest, srcDest, rhs);
159 }
160 
mulFloat32(FloatRegister src,FloatRegister dest)161 void MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest) {
162   as_muls(dest, dest, src);
163 }
164 
mulDouble(FloatRegister src,FloatRegister dest)165 void MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest) {
166   as_muld(dest, dest, src);
167 }
168 
mulDoublePtr(ImmPtr imm,Register temp,FloatRegister dest)169 void MacroAssembler::mulDoublePtr(ImmPtr imm, Register temp,
170                                   FloatRegister dest) {
171   movePtr(imm, ScratchRegister);
172   loadDouble(Address(ScratchRegister, 0), ScratchDoubleReg);
173   mulDouble(ScratchDoubleReg, dest);
174 }
175 
quotient32(Register rhs,Register srcDest,bool isUnsigned)176 void MacroAssembler::quotient32(Register rhs, Register srcDest,
177                                 bool isUnsigned) {
178   if (isUnsigned) {
179 #ifdef MIPSR6
180     as_divu(srcDest, srcDest, rhs);
181 #else
182     as_divu(srcDest, rhs);
183 #endif
184   } else {
185 #ifdef MIPSR6
186     as_div(srcDest, srcDest, rhs);
187 #else
188     as_div(srcDest, rhs);
189 #endif
190   }
191 #ifndef MIPSR6
192   as_mflo(srcDest);
193 #endif
194 }
195 
remainder32(Register rhs,Register srcDest,bool isUnsigned)196 void MacroAssembler::remainder32(Register rhs, Register srcDest,
197                                  bool isUnsigned) {
198   if (isUnsigned) {
199 #ifdef MIPSR6
200     as_modu(srcDest, srcDest, rhs);
201 #else
202     as_divu(srcDest, rhs);
203 #endif
204   } else {
205 #ifdef MIPSR6
206     as_mod(srcDest, srcDest, rhs);
207 #else
208     as_div(srcDest, rhs);
209 #endif
210   }
211 #ifndef MIPSR6
212   as_mfhi(srcDest);
213 #endif
214 }
215 
divFloat32(FloatRegister src,FloatRegister dest)216 void MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest) {
217   as_divs(dest, dest, src);
218 }
219 
divDouble(FloatRegister src,FloatRegister dest)220 void MacroAssembler::divDouble(FloatRegister src, FloatRegister dest) {
221   as_divd(dest, dest, src);
222 }
223 
neg32(Register reg)224 void MacroAssembler::neg32(Register reg) { ma_negu(reg, reg); }
225 
negateDouble(FloatRegister reg)226 void MacroAssembler::negateDouble(FloatRegister reg) { as_negd(reg, reg); }
227 
negateFloat(FloatRegister reg)228 void MacroAssembler::negateFloat(FloatRegister reg) { as_negs(reg, reg); }
229 
absFloat32(FloatRegister src,FloatRegister dest)230 void MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest) {
231   as_abss(dest, src);
232 }
233 
absDouble(FloatRegister src,FloatRegister dest)234 void MacroAssembler::absDouble(FloatRegister src, FloatRegister dest) {
235   as_absd(dest, src);
236 }
237 
sqrtFloat32(FloatRegister src,FloatRegister dest)238 void MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest) {
239   as_sqrts(dest, src);
240 }
241 
sqrtDouble(FloatRegister src,FloatRegister dest)242 void MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest) {
243   as_sqrtd(dest, src);
244 }
245 
minFloat32(FloatRegister other,FloatRegister srcDest,bool handleNaN)246 void MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest,
247                                 bool handleNaN) {
248   minMaxFloat32(srcDest, other, handleNaN, false);
249 }
250 
minDouble(FloatRegister other,FloatRegister srcDest,bool handleNaN)251 void MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest,
252                                bool handleNaN) {
253   minMaxDouble(srcDest, other, handleNaN, false);
254 }
255 
maxFloat32(FloatRegister other,FloatRegister srcDest,bool handleNaN)256 void MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest,
257                                 bool handleNaN) {
258   minMaxFloat32(srcDest, other, handleNaN, true);
259 }
260 
maxDouble(FloatRegister other,FloatRegister srcDest,bool handleNaN)261 void MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest,
262                                bool handleNaN) {
263   minMaxDouble(srcDest, other, handleNaN, true);
264 }
265 
266 // ===============================================================
267 // Shift functions
268 
lshift32(Register src,Register dest)269 void MacroAssembler::lshift32(Register src, Register dest) {
270   ma_sll(dest, dest, src);
271 }
272 
flexibleLshift32(Register src,Register dest)273 void MacroAssembler::flexibleLshift32(Register src, Register dest) {
274   lshift32(src, dest);
275 }
276 
lshift32(Imm32 imm,Register dest)277 void MacroAssembler::lshift32(Imm32 imm, Register dest) {
278   ma_sll(dest, dest, imm);
279 }
280 
rshift32(Register src,Register dest)281 void MacroAssembler::rshift32(Register src, Register dest) {
282   ma_srl(dest, dest, src);
283 }
284 
flexibleRshift32(Register src,Register dest)285 void MacroAssembler::flexibleRshift32(Register src, Register dest) {
286   rshift32(src, dest);
287 }
288 
rshift32(Imm32 imm,Register dest)289 void MacroAssembler::rshift32(Imm32 imm, Register dest) {
290   ma_srl(dest, dest, imm);
291 }
292 
rshift32Arithmetic(Register src,Register dest)293 void MacroAssembler::rshift32Arithmetic(Register src, Register dest) {
294   ma_sra(dest, dest, src);
295 }
296 
flexibleRshift32Arithmetic(Register src,Register dest)297 void MacroAssembler::flexibleRshift32Arithmetic(Register src, Register dest) {
298   rshift32Arithmetic(src, dest);
299 }
300 
rshift32Arithmetic(Imm32 imm,Register dest)301 void MacroAssembler::rshift32Arithmetic(Imm32 imm, Register dest) {
302   ma_sra(dest, dest, imm);
303 }
304 
305 // ===============================================================
306 // Rotation functions
rotateLeft(Imm32 count,Register input,Register dest)307 void MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest) {
308   if (count.value) {
309     ma_rol(dest, input, count);
310   } else {
311     ma_move(dest, input);
312   }
313 }
rotateLeft(Register count,Register input,Register dest)314 void MacroAssembler::rotateLeft(Register count, Register input, Register dest) {
315   ma_rol(dest, input, count);
316 }
rotateRight(Imm32 count,Register input,Register dest)317 void MacroAssembler::rotateRight(Imm32 count, Register input, Register dest) {
318   if (count.value) {
319     ma_ror(dest, input, count);
320   } else {
321     ma_move(dest, input);
322   }
323 }
rotateRight(Register count,Register input,Register dest)324 void MacroAssembler::rotateRight(Register count, Register input,
325                                  Register dest) {
326   ma_ror(dest, input, count);
327 }
328 
329 // ===============================================================
330 // Bit counting functions
331 
clz32(Register src,Register dest,bool knownNotZero)332 void MacroAssembler::clz32(Register src, Register dest, bool knownNotZero) {
333   as_clz(dest, src);
334 }
335 
ctz32(Register src,Register dest,bool knownNotZero)336 void MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero) {
337   ma_ctz(dest, src);
338 }
339 
popcnt32(Register input,Register output,Register tmp)340 void MacroAssembler::popcnt32(Register input, Register output, Register tmp) {
341   // Equivalent to GCC output of mozilla::CountPopulation32()
342   ma_move(output, input);
343   ma_sra(tmp, input, Imm32(1));
344   ma_and(tmp, Imm32(0x55555555));
345   ma_subu(output, tmp);
346   ma_sra(tmp, output, Imm32(2));
347   ma_and(output, Imm32(0x33333333));
348   ma_and(tmp, Imm32(0x33333333));
349   ma_addu(output, tmp);
350   ma_srl(tmp, output, Imm32(4));
351   ma_addu(output, tmp);
352   ma_and(output, Imm32(0xF0F0F0F));
353   ma_sll(tmp, output, Imm32(8));
354   ma_addu(output, tmp);
355   ma_sll(tmp, output, Imm32(16));
356   ma_addu(output, tmp);
357   ma_sra(output, output, Imm32(24));
358 }
359 
360 // ===============================================================
361 // Branch functions
362 
363 template <class L>
branch32(Condition cond,Register lhs,Register rhs,L label)364 void MacroAssembler::branch32(Condition cond, Register lhs, Register rhs,
365                               L label) {
366   ma_b(lhs, rhs, label, cond);
367 }
368 
369 template <class L>
branch32(Condition cond,Register lhs,Imm32 imm,L label)370 void MacroAssembler::branch32(Condition cond, Register lhs, Imm32 imm,
371                               L label) {
372   ma_b(lhs, imm, label, cond);
373 }
374 
branch32(Condition cond,const Address & lhs,Register rhs,Label * label)375 void MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs,
376                               Label* label) {
377   load32(lhs, SecondScratchReg);
378   ma_b(SecondScratchReg, rhs, label, cond);
379 }
380 
branch32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)381 void MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 rhs,
382                               Label* label) {
383   load32(lhs, SecondScratchReg);
384   ma_b(SecondScratchReg, rhs, label, cond);
385 }
386 
branch32(Condition cond,const AbsoluteAddress & lhs,Register rhs,Label * label)387 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs,
388                               Register rhs, Label* label) {
389   load32(lhs, SecondScratchReg);
390   ma_b(SecondScratchReg, rhs, label, cond);
391 }
392 
branch32(Condition cond,const AbsoluteAddress & lhs,Imm32 rhs,Label * label)393 void MacroAssembler::branch32(Condition cond, const AbsoluteAddress& lhs,
394                               Imm32 rhs, Label* label) {
395   load32(lhs, SecondScratchReg);
396   ma_b(SecondScratchReg, rhs, label, cond);
397 }
398 
branch32(Condition cond,const BaseIndex & lhs,Imm32 rhs,Label * label)399 void MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs,
400                               Label* label) {
401   load32(lhs, SecondScratchReg);
402   ma_b(SecondScratchReg, rhs, label, cond);
403 }
404 
branch32(Condition cond,wasm::SymbolicAddress addr,Imm32 imm,Label * label)405 void MacroAssembler::branch32(Condition cond, wasm::SymbolicAddress addr,
406                               Imm32 imm, Label* label) {
407   load32(addr, SecondScratchReg);
408   ma_b(SecondScratchReg, imm, label, cond);
409 }
410 
411 template <class L>
branchPtr(Condition cond,Register lhs,Register rhs,L label)412 void MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs,
413                                L label) {
414   ma_b(lhs, rhs, label, cond);
415 }
416 
branchPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)417 void MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs,
418                                Label* label) {
419   ma_b(lhs, rhs, label, cond);
420 }
421 
branchPtr(Condition cond,Register lhs,ImmPtr rhs,Label * label)422 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs,
423                                Label* label) {
424   ma_b(lhs, rhs, label, cond);
425 }
426 
branchPtr(Condition cond,Register lhs,ImmGCPtr rhs,Label * label)427 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs,
428                                Label* label) {
429   ma_b(lhs, rhs, label, cond);
430 }
431 
branchPtr(Condition cond,Register lhs,ImmWord rhs,Label * label)432 void MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs,
433                                Label* label) {
434   ma_b(lhs, rhs, label, cond);
435 }
436 
437 template <class L>
branchPtr(Condition cond,const Address & lhs,Register rhs,L label)438 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs,
439                                L label) {
440   loadPtr(lhs, SecondScratchReg);
441   branchPtr(cond, SecondScratchReg, rhs, label);
442 }
443 
branchPtr(Condition cond,const Address & lhs,ImmPtr rhs,Label * label)444 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs,
445                                Label* label) {
446   loadPtr(lhs, SecondScratchReg);
447   branchPtr(cond, SecondScratchReg, rhs, label);
448 }
449 
branchPtr(Condition cond,const Address & lhs,ImmGCPtr rhs,Label * label)450 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs,
451                                Label* label) {
452   loadPtr(lhs, SecondScratchReg);
453   branchPtr(cond, SecondScratchReg, rhs, label);
454 }
455 
branchPtr(Condition cond,const Address & lhs,ImmWord rhs,Label * label)456 void MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs,
457                                Label* label) {
458   loadPtr(lhs, SecondScratchReg);
459   branchPtr(cond, SecondScratchReg, rhs, label);
460 }
461 
branchPtr(Condition cond,const AbsoluteAddress & lhs,Register rhs,Label * label)462 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs,
463                                Register rhs, Label* label) {
464   loadPtr(lhs, SecondScratchReg);
465   branchPtr(cond, SecondScratchReg, rhs, label);
466 }
467 
branchPtr(Condition cond,const AbsoluteAddress & lhs,ImmWord rhs,Label * label)468 void MacroAssembler::branchPtr(Condition cond, const AbsoluteAddress& lhs,
469                                ImmWord rhs, Label* label) {
470   loadPtr(lhs, SecondScratchReg);
471   branchPtr(cond, SecondScratchReg, rhs, label);
472 }
473 
branchPtr(Condition cond,wasm::SymbolicAddress lhs,Register rhs,Label * label)474 void MacroAssembler::branchPtr(Condition cond, wasm::SymbolicAddress lhs,
475                                Register rhs, Label* label) {
476   loadPtr(lhs, SecondScratchReg);
477   branchPtr(cond, SecondScratchReg, rhs, label);
478 }
479 
branchPtr(Condition cond,const BaseIndex & lhs,ImmWord rhs,Label * label)480 void MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs,
481                                ImmWord rhs, Label* label) {
482   loadPtr(lhs, SecondScratchReg);
483   branchPtr(cond, SecondScratchReg, rhs, label);
484 }
485 
branchFloat(DoubleCondition cond,FloatRegister lhs,FloatRegister rhs,Label * label)486 void MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs,
487                                  FloatRegister rhs, Label* label) {
488   ma_bc1s(lhs, rhs, label, cond);
489 }
490 
branchTruncateFloat32ToInt32(FloatRegister src,Register dest,Label * fail)491 void MacroAssembler::branchTruncateFloat32ToInt32(FloatRegister src,
492                                                   Register dest, Label* fail) {
493   convertFloat32ToInt32(src, dest, fail, false);
494 }
495 
branchDouble(DoubleCondition cond,FloatRegister lhs,FloatRegister rhs,Label * label)496 void MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs,
497                                   FloatRegister rhs, Label* label) {
498   ma_bc1d(lhs, rhs, label, cond);
499 }
500 
branchTruncateDoubleToInt32(FloatRegister src,Register dest,Label * fail)501 void MacroAssembler::branchTruncateDoubleToInt32(FloatRegister src,
502                                                  Register dest, Label* fail) {
503   convertDoubleToInt32(src, dest, fail, false);
504 }
505 
506 template <typename T>
branchAdd32(Condition cond,T src,Register dest,Label * overflow)507 void MacroAssembler::branchAdd32(Condition cond, T src, Register dest,
508                                  Label* overflow) {
509   switch (cond) {
510     case Overflow:
511       ma_addTestOverflow(dest, dest, src, overflow);
512       break;
513     case CarryClear:
514     case CarrySet:
515       ma_addTestCarry(cond, dest, dest, src, overflow);
516       break;
517     default:
518       MOZ_CRASH("NYI");
519   }
520 }
521 
522 template <typename T>
branchSub32(Condition cond,T src,Register dest,Label * overflow)523 void MacroAssembler::branchSub32(Condition cond, T src, Register dest,
524                                  Label* overflow) {
525   switch (cond) {
526     case Overflow:
527       ma_subTestOverflow(dest, dest, src, overflow);
528       break;
529     case NonZero:
530     case Zero:
531     case Signed:
532     case NotSigned:
533       ma_subu(dest, src);
534       ma_b(dest, dest, overflow, cond);
535       break;
536     default:
537       MOZ_CRASH("NYI");
538   }
539 }
540 
541 template <typename T>
branchMul32(Condition cond,T src,Register dest,Label * overflow)542 void MacroAssembler::branchMul32(Condition cond, T src, Register dest,
543                                  Label* overflow) {
544   MOZ_ASSERT(cond == Assembler::Overflow);
545   ma_mul_branch_overflow(dest, dest, src, overflow);
546 }
547 
548 template <typename T>
branchRshift32(Condition cond,T src,Register dest,Label * label)549 void MacroAssembler::branchRshift32(Condition cond, T src, Register dest,
550                                     Label* label) {
551   MOZ_ASSERT(cond == Zero || cond == NonZero);
552   rshift32(src, dest);
553   branch32(cond == Zero ? Equal : NotEqual, dest, Imm32(0), label);
554 }
555 
branchNeg32(Condition cond,Register reg,Label * label)556 void MacroAssembler::branchNeg32(Condition cond, Register reg, Label* label) {
557   MOZ_ASSERT(cond == Overflow);
558   neg32(reg);
559   branch32(Assembler::Equal, reg, Imm32(INT32_MIN), label);
560 }
561 
decBranchPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)562 void MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs,
563                                   Label* label) {
564   subPtr(rhs, lhs);
565   branchPtr(cond, lhs, Imm32(0), label);
566 }
567 
568 template <class L>
branchTest32(Condition cond,Register lhs,Register rhs,L label)569 void MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs,
570                                   L label) {
571   MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
572              cond == NotSigned);
573   if (lhs == rhs) {
574     ma_b(lhs, rhs, label, cond);
575   } else {
576     as_and(ScratchRegister, lhs, rhs);
577     ma_b(ScratchRegister, ScratchRegister, label, cond);
578   }
579 }
580 
581 template <class L>
branchTest32(Condition cond,Register lhs,Imm32 rhs,L label)582 void MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs,
583                                   L label) {
584   MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
585              cond == NotSigned);
586   ma_and(ScratchRegister, lhs, rhs);
587   ma_b(ScratchRegister, ScratchRegister, label, cond);
588 }
589 
branchTest32(Condition cond,const Address & lhs,Imm32 rhs,Label * label)590 void MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs,
591                                   Label* label) {
592   load32(lhs, SecondScratchReg);
593   branchTest32(cond, SecondScratchReg, rhs, label);
594 }
595 
branchTest32(Condition cond,const AbsoluteAddress & lhs,Imm32 rhs,Label * label)596 void MacroAssembler::branchTest32(Condition cond, const AbsoluteAddress& lhs,
597                                   Imm32 rhs, Label* label) {
598   load32(lhs, SecondScratchReg);
599   branchTest32(cond, SecondScratchReg, rhs, label);
600 }
601 
602 template <class L>
branchTestPtr(Condition cond,Register lhs,Register rhs,L label)603 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs,
604                                    L label) {
605   MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
606              cond == NotSigned);
607   if (lhs == rhs) {
608     ma_b(lhs, rhs, label, cond);
609   } else {
610     as_and(ScratchRegister, lhs, rhs);
611     ma_b(ScratchRegister, ScratchRegister, label, cond);
612   }
613 }
614 
branchTestPtr(Condition cond,Register lhs,Imm32 rhs,Label * label)615 void MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs,
616                                    Label* label) {
617   MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed ||
618              cond == NotSigned);
619   ma_and(ScratchRegister, lhs, rhs);
620   ma_b(ScratchRegister, ScratchRegister, label, cond);
621 }
622 
branchTestPtr(Condition cond,const Address & lhs,Imm32 rhs,Label * label)623 void MacroAssembler::branchTestPtr(Condition cond, const Address& lhs,
624                                    Imm32 rhs, Label* label) {
625   loadPtr(lhs, SecondScratchReg);
626   branchTestPtr(cond, SecondScratchReg, rhs, label);
627 }
628 
branchTestUndefined(Condition cond,Register tag,Label * label)629 void MacroAssembler::branchTestUndefined(Condition cond, Register tag,
630                                          Label* label) {
631   MOZ_ASSERT(cond == Equal || cond == NotEqual);
632   ma_b(tag, ImmTag(JSVAL_TAG_UNDEFINED), label, cond);
633 }
634 
branchTestUndefined(Condition cond,const Address & address,Label * label)635 void MacroAssembler::branchTestUndefined(Condition cond, const Address& address,
636                                          Label* label) {
637   SecondScratchRegisterScope scratch2(*this);
638   Register tag = extractTag(address, scratch2);
639   branchTestUndefined(cond, tag, label);
640 }
641 
branchTestUndefined(Condition cond,const BaseIndex & address,Label * label)642 void MacroAssembler::branchTestUndefined(Condition cond,
643                                          const BaseIndex& address,
644                                          Label* label) {
645   SecondScratchRegisterScope scratch2(*this);
646   Register tag = extractTag(address, scratch2);
647   branchTestUndefined(cond, tag, label);
648 }
649 
branchTestInt32(Condition cond,Register tag,Label * label)650 void MacroAssembler::branchTestInt32(Condition cond, Register tag,
651                                      Label* label) {
652   MOZ_ASSERT(cond == Equal || cond == NotEqual);
653   ma_b(tag, ImmTag(JSVAL_TAG_INT32), label, cond);
654 }
655 
branchTestInt32(Condition cond,const Address & address,Label * label)656 void MacroAssembler::branchTestInt32(Condition cond, const Address& address,
657                                      Label* label) {
658   SecondScratchRegisterScope scratch2(*this);
659   Register tag = extractTag(address, scratch2);
660   branchTestInt32(cond, tag, label);
661 }
662 
branchTestInt32(Condition cond,const BaseIndex & address,Label * label)663 void MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address,
664                                      Label* label) {
665   SecondScratchRegisterScope scratch2(*this);
666   Register tag = extractTag(address, scratch2);
667   branchTestInt32(cond, tag, label);
668 }
669 
branchTestDouble(Condition cond,const Address & address,Label * label)670 void MacroAssembler::branchTestDouble(Condition cond, const Address& address,
671                                       Label* label) {
672   SecondScratchRegisterScope scratch2(*this);
673   Register tag = extractTag(address, scratch2);
674   branchTestDouble(cond, tag, label);
675 }
676 
branchTestDouble(Condition cond,const BaseIndex & address,Label * label)677 void MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address,
678                                       Label* label) {
679   SecondScratchRegisterScope scratch2(*this);
680   Register tag = extractTag(address, scratch2);
681   branchTestDouble(cond, tag, label);
682 }
683 
branchTestDoubleTruthy(bool b,FloatRegister value,Label * label)684 void MacroAssembler::branchTestDoubleTruthy(bool b, FloatRegister value,
685                                             Label* label) {
686   ma_lid(ScratchDoubleReg, 0.0);
687   DoubleCondition cond = b ? DoubleNotEqual : DoubleEqualOrUnordered;
688   ma_bc1d(value, ScratchDoubleReg, label, cond);
689 }
690 
branchTestNumber(Condition cond,Register tag,Label * label)691 void MacroAssembler::branchTestNumber(Condition cond, Register tag,
692                                       Label* label) {
693   MOZ_ASSERT(cond == Equal || cond == NotEqual);
694   Condition actual = cond == Equal ? BelowOrEqual : Above;
695   ma_b(tag, ImmTag(JS::detail::ValueUpperInclNumberTag), label, actual);
696 }
697 
branchTestBoolean(Condition cond,Register tag,Label * label)698 void MacroAssembler::branchTestBoolean(Condition cond, Register tag,
699                                        Label* label) {
700   MOZ_ASSERT(cond == Equal || cond == NotEqual);
701   ma_b(tag, ImmTag(JSVAL_TAG_BOOLEAN), label, cond);
702 }
703 
branchTestBoolean(Condition cond,const Address & address,Label * label)704 void MacroAssembler::branchTestBoolean(Condition cond, const Address& address,
705                                        Label* label) {
706   SecondScratchRegisterScope scratch2(*this);
707   Register tag = extractTag(address, scratch2);
708   branchTestBoolean(cond, tag, label);
709 }
710 
branchTestBoolean(Condition cond,const BaseIndex & address,Label * label)711 void MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address,
712                                        Label* label) {
713   SecondScratchRegisterScope scratch2(*this);
714   Register tag = extractTag(address, scratch2);
715   branchTestBoolean(cond, tag, label);
716 }
717 
branchTestString(Condition cond,Register tag,Label * label)718 void MacroAssembler::branchTestString(Condition cond, Register tag,
719                                       Label* label) {
720   MOZ_ASSERT(cond == Equal || cond == NotEqual);
721   ma_b(tag, ImmTag(JSVAL_TAG_STRING), label, cond);
722 }
723 
branchTestString(Condition cond,const Address & address,Label * label)724 void MacroAssembler::branchTestString(Condition cond, const Address& address,
725                                       Label* label) {
726   SecondScratchRegisterScope scratch2(*this);
727   Register tag = extractTag(address, scratch2);
728   branchTestString(cond, tag, label);
729 }
730 
branchTestString(Condition cond,const BaseIndex & address,Label * label)731 void MacroAssembler::branchTestString(Condition cond, const BaseIndex& address,
732                                       Label* label) {
733   SecondScratchRegisterScope scratch2(*this);
734   Register tag = extractTag(address, scratch2);
735   branchTestString(cond, tag, label);
736 }
737 
branchTestSymbol(Condition cond,Register tag,Label * label)738 void MacroAssembler::branchTestSymbol(Condition cond, Register tag,
739                                       Label* label) {
740   MOZ_ASSERT(cond == Equal || cond == NotEqual);
741   ma_b(tag, ImmTag(JSVAL_TAG_SYMBOL), label, cond);
742 }
743 
branchTestSymbol(Condition cond,const BaseIndex & address,Label * label)744 void MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address,
745                                       Label* label) {
746   SecondScratchRegisterScope scratch2(*this);
747   Register tag = extractTag(address, scratch2);
748   branchTestSymbol(cond, tag, label);
749 }
750 
branchTestSymbol(Condition cond,const Address & address,Label * label)751 void MacroAssembler::branchTestSymbol(Condition cond, const Address& address,
752                                       Label* label) {
753   SecondScratchRegisterScope scratch2(*this);
754   Register tag = extractTag(address, scratch2);
755   branchTestSymbol(cond, tag, label);
756 }
757 
branchTestBigInt(Condition cond,Register tag,Label * label)758 void MacroAssembler::branchTestBigInt(Condition cond, Register tag,
759                                       Label* label) {
760   MOZ_ASSERT(cond == Equal || cond == NotEqual);
761   ma_b(tag, ImmTag(JSVAL_TAG_BIGINT), label, cond);
762 }
763 
branchTestBigInt(Condition cond,const Address & address,Label * label)764 void MacroAssembler::branchTestBigInt(Condition cond, const Address& address,
765                                       Label* label) {
766   SecondScratchRegisterScope scratch2(*this);
767   Register tag = extractTag(address, scratch2);
768   branchTestBigInt(cond, tag, label);
769 }
770 
branchTestNull(Condition cond,Register tag,Label * label)771 void MacroAssembler::branchTestNull(Condition cond, Register tag,
772                                     Label* label) {
773   MOZ_ASSERT(cond == Equal || cond == NotEqual);
774   ma_b(tag, ImmTag(JSVAL_TAG_NULL), label, cond);
775 }
776 
branchTestNull(Condition cond,const Address & address,Label * label)777 void MacroAssembler::branchTestNull(Condition cond, const Address& address,
778                                     Label* label) {
779   SecondScratchRegisterScope scratch2(*this);
780   Register tag = extractTag(address, scratch2);
781   branchTestNull(cond, tag, label);
782 }
783 
branchTestNull(Condition cond,const BaseIndex & address,Label * label)784 void MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address,
785                                     Label* label) {
786   SecondScratchRegisterScope scratch2(*this);
787   Register tag = extractTag(address, scratch2);
788   branchTestNull(cond, tag, label);
789 }
790 
branchTestObject(Condition cond,Register tag,Label * label)791 void MacroAssembler::branchTestObject(Condition cond, Register tag,
792                                       Label* label) {
793   MOZ_ASSERT(cond == Equal || cond == NotEqual);
794   ma_b(tag, ImmTag(JSVAL_TAG_OBJECT), label, cond);
795 }
796 
branchTestObject(Condition cond,const Address & address,Label * label)797 void MacroAssembler::branchTestObject(Condition cond, const Address& address,
798                                       Label* label) {
799   SecondScratchRegisterScope scratch2(*this);
800   Register tag = extractTag(address, scratch2);
801   branchTestObject(cond, tag, label);
802 }
803 
branchTestObject(Condition cond,const BaseIndex & address,Label * label)804 void MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address,
805                                       Label* label) {
806   SecondScratchRegisterScope scratch2(*this);
807   Register tag = extractTag(address, scratch2);
808   branchTestObject(cond, tag, label);
809 }
810 
branchTestGCThing(Condition cond,const Address & address,Label * label)811 void MacroAssembler::branchTestGCThing(Condition cond, const Address& address,
812                                        Label* label) {
813   branchTestGCThingImpl(cond, address, label);
814 }
815 
branchTestGCThing(Condition cond,const BaseIndex & address,Label * label)816 void MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address,
817                                        Label* label) {
818   branchTestGCThingImpl(cond, address, label);
819 }
820 
branchTestGCThing(Condition cond,const ValueOperand & address,Label * label)821 void MacroAssembler::branchTestGCThing(Condition cond,
822                                        const ValueOperand& address,
823                                        Label* label) {
824   branchTestGCThingImpl(cond, address, label);
825 }
826 
827 template <typename T>
branchTestGCThingImpl(Condition cond,const T & address,Label * label)828 void MacroAssembler::branchTestGCThingImpl(Condition cond, const T& address,
829                                            Label* label) {
830   MOZ_ASSERT(cond == Equal || cond == NotEqual);
831   SecondScratchRegisterScope scratch2(*this);
832   Register tag = extractTag(address, scratch2);
833   ma_b(tag, ImmTag(JS::detail::ValueLowerInclGCThingTag), label,
834        (cond == Equal) ? AboveOrEqual : Below);
835 }
836 
branchTestPrimitive(Condition cond,Register tag,Label * label)837 void MacroAssembler::branchTestPrimitive(Condition cond, Register tag,
838                                          Label* label) {
839   MOZ_ASSERT(cond == Equal || cond == NotEqual);
840   ma_b(tag, ImmTag(JS::detail::ValueUpperExclPrimitiveTag), label,
841        (cond == Equal) ? Below : AboveOrEqual);
842 }
843 
branchTestMagic(Condition cond,Register tag,Label * label)844 void MacroAssembler::branchTestMagic(Condition cond, Register tag,
845                                      Label* label) {
846   MOZ_ASSERT(cond == Equal || cond == NotEqual);
847   ma_b(tag, ImmTag(JSVAL_TAG_MAGIC), label, cond);
848 }
849 
branchTestMagic(Condition cond,const Address & address,Label * label)850 void MacroAssembler::branchTestMagic(Condition cond, const Address& address,
851                                      Label* label) {
852   SecondScratchRegisterScope scratch2(*this);
853   Register tag = extractTag(address, scratch2);
854   branchTestMagic(cond, tag, label);
855 }
856 
branchTestMagic(Condition cond,const BaseIndex & address,Label * label)857 void MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address,
858                                      Label* label) {
859   SecondScratchRegisterScope scratch2(*this);
860   Register tag = extractTag(address, scratch2);
861   branchTestMagic(cond, tag, label);
862 }
863 
branchToComputedAddress(const BaseIndex & addr)864 void MacroAssembler::branchToComputedAddress(const BaseIndex& addr) {
865   loadPtr(addr, ScratchRegister);
866   branch(ScratchRegister);
867 }
868 
cmp32Move32(Condition cond,Register lhs,Register rhs,Register src,Register dest)869 void MacroAssembler::cmp32Move32(Condition cond, Register lhs, Register rhs,
870                                  Register src, Register dest) {
871   Register scratch = ScratchRegister;
872   MOZ_ASSERT(src != scratch && dest != scratch);
873   cmp32Set(cond, lhs, rhs, scratch);
874 #ifdef MIPSR6
875   as_selnez(src, src, scratch);
876   as_seleqz(dest, dest, scratch);
877   as_or(dest, dest, src);
878 #else
879   as_movn(dest, src, scratch);
880 #endif
881 }
882 
cmp32MovePtr(Condition cond,Register lhs,Imm32 rhs,Register src,Register dest)883 void MacroAssembler::cmp32MovePtr(Condition cond, Register lhs, Imm32 rhs,
884                                   Register src, Register dest) {
885   Register scratch = ScratchRegister;
886   MOZ_ASSERT(src != scratch && dest != scratch);
887   cmp32Set(cond, lhs, rhs, scratch);
888 #ifdef MIPSR6
889   as_selnez(src, src, scratch);
890   as_seleqz(dest, dest, scratch);
891   as_or(dest, dest, src);
892 #else
893   as_movn(dest, src, scratch);
894 #endif
895 }
896 
cmp32Move32(Condition cond,Register lhs,const Address & rhs,Register src,Register dest)897 void MacroAssembler::cmp32Move32(Condition cond, Register lhs,
898                                  const Address& rhs, Register src,
899                                  Register dest) {
900   SecondScratchRegisterScope scratch2(*this);
901   MOZ_ASSERT(lhs != scratch2 && src != scratch2 && dest != scratch2);
902   load32(rhs, scratch2);
903   cmp32Move32(cond, lhs, scratch2, src, dest);
904 }
905 
cmp32Load32(Condition cond,Register lhs,const Address & rhs,const Address & src,Register dest)906 void MacroAssembler::cmp32Load32(Condition cond, Register lhs,
907                                  const Address& rhs, const Address& src,
908                                  Register dest) {
909   ScratchRegisterScope scratch(*this);
910   MOZ_ASSERT(lhs != scratch && dest != scratch);
911   load32(rhs, scratch);
912   cmp32Load32(cond, lhs, scratch, src, dest);
913 }
914 
cmp32Load32(Condition cond,Register lhs,Register rhs,const Address & src,Register dest)915 void MacroAssembler::cmp32Load32(Condition cond, Register lhs, Register rhs,
916                                  const Address& src, Register dest) {
917   Label skip;
918   branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip);
919   load32(src, dest);
920   bind(&skip);
921 }
922 
cmp32LoadPtr(Condition cond,const Address & lhs,Imm32 rhs,const Address & src,Register dest)923 void MacroAssembler::cmp32LoadPtr(Condition cond, const Address& lhs, Imm32 rhs,
924                                   const Address& src, Register dest) {
925   Label skip;
926   branch32(Assembler::InvertCondition(cond), lhs, rhs, &skip);
927   loadPtr(src, dest);
928   bind(&skip);
929 }
930 
test32LoadPtr(Condition cond,const Address & addr,Imm32 mask,const Address & src,Register dest)931 void MacroAssembler::test32LoadPtr(Condition cond, const Address& addr,
932                                    Imm32 mask, const Address& src,
933                                    Register dest) {
934   MOZ_RELEASE_ASSERT(!JitOptions.spectreStringMitigations);
935   Label skip;
936   branchTest32(Assembler::InvertCondition(cond), addr, mask, &skip);
937   loadPtr(src, dest);
938   bind(&skip);
939 }
940 
test32MovePtr(Condition cond,const Address & addr,Imm32 mask,Register src,Register dest)941 void MacroAssembler::test32MovePtr(Condition cond, const Address& addr,
942                                    Imm32 mask, Register src, Register dest) {
943   MOZ_CRASH();
944 }
945 
spectreBoundsCheck32(Register index,Register length,Register maybeScratch,Label * failure)946 void MacroAssembler::spectreBoundsCheck32(Register index, Register length,
947                                           Register maybeScratch,
948                                           Label* failure) {
949   MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
950   branch32(Assembler::BelowOrEqual, length, index, failure);
951 }
952 
spectreBoundsCheck32(Register index,const Address & length,Register maybeScratch,Label * failure)953 void MacroAssembler::spectreBoundsCheck32(Register index, const Address& length,
954                                           Register maybeScratch,
955                                           Label* failure) {
956   MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
957   branch32(Assembler::BelowOrEqual, length, index, failure);
958 }
959 
spectreMovePtr(Condition cond,Register src,Register dest)960 void MacroAssembler::spectreMovePtr(Condition cond, Register src,
961                                     Register dest) {
962   MOZ_CRASH();
963 }
964 
spectreZeroRegister(Condition cond,Register scratch,Register dest)965 void MacroAssembler::spectreZeroRegister(Condition cond, Register scratch,
966                                          Register dest) {
967   MOZ_CRASH();
968 }
969 
970 // ========================================================================
971 // Memory access primitives.
storeFloat32x3(FloatRegister src,const Address & dest)972 void MacroAssembler::storeFloat32x3(FloatRegister src, const Address& dest) {
973   MOZ_CRASH("NYI");
974 }
storeFloat32x3(FloatRegister src,const BaseIndex & dest)975 void MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest) {
976   MOZ_CRASH("NYI");
977 }
978 
storeUncanonicalizedDouble(FloatRegister src,const Address & addr)979 void MacroAssembler::storeUncanonicalizedDouble(FloatRegister src,
980                                                 const Address& addr) {
981   ma_sd(src, addr);
982 }
storeUncanonicalizedDouble(FloatRegister src,const BaseIndex & addr)983 void MacroAssembler::storeUncanonicalizedDouble(FloatRegister src,
984                                                 const BaseIndex& addr) {
985   ma_sd(src, addr);
986 }
987 
storeUncanonicalizedFloat32(FloatRegister src,const Address & addr)988 void MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src,
989                                                  const Address& addr) {
990   ma_ss(src, addr);
991 }
storeUncanonicalizedFloat32(FloatRegister src,const BaseIndex & addr)992 void MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src,
993                                                  const BaseIndex& addr) {
994   ma_ss(src, addr);
995 }
996 
memoryBarrier(MemoryBarrierBits barrier)997 void MacroAssembler::memoryBarrier(MemoryBarrierBits barrier) {
998   if (barrier) {
999     as_sync();
1000   }
1001 }
1002 
1003 // ===============================================================
1004 // Clamping functions.
1005 
clampIntToUint8(Register reg)1006 void MacroAssembler::clampIntToUint8(Register reg) {
1007   // If reg is < 0, then we want to clamp to 0.
1008   as_slti(ScratchRegister, reg, 0);
1009 #ifdef MIPSR6
1010   as_seleqz(reg, reg, ScratchRegister);
1011 #else
1012   as_movn(reg, zero, ScratchRegister);
1013 #endif
1014   // If reg is >= 255, then we want to clamp to 255.
1015   ma_li(SecondScratchReg, Imm32(255));
1016   as_slti(ScratchRegister, reg, 255);
1017 #ifdef MIPSR6
1018   as_seleqz(SecondScratchReg, SecondScratchReg, ScratchRegister);
1019   as_selnez(reg, reg, ScratchRegister);
1020   as_or(reg, reg, SecondScratchReg);
1021 #else
1022   as_movz(reg, SecondScratchReg, ScratchRegister);
1023 #endif
1024 }
1025 
1026 //}}} check_macroassembler_style
1027 // ===============================================================
1028 
1029 }  // namespace jit
1030 }  // namespace js
1031 
1032 #endif /* jit_mips_shared_MacroAssembler_mips_shared_inl_h */
1033