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