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