Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef assembler_assembler_MacroAssemblerSparc_h
8 #define assembler_assembler_MacroAssemblerSparc_h
10 #include "assembler/wtf/Platform.h"
12 #if ENABLE_ASSEMBLER && WTF_CPU_SPARC
14 #include "assembler/assembler/SparcAssembler.h"
15 #include "assembler/assembler/AbstractMacroAssembler.h"
17 namespace JSC {
19 class MacroAssemblerSparc : public AbstractMacroAssembler<SparcAssembler> {
20 public:
21 enum Condition {
22 Equal = SparcAssembler::ConditionE,
23 NotEqual = SparcAssembler::ConditionNE,
24 Above = SparcAssembler::ConditionGU,
25 AboveOrEqual = SparcAssembler::ConditionCC,
26 Below = SparcAssembler::ConditionCS,
27 BelowOrEqual = SparcAssembler::ConditionLEU,
28 GreaterThan = SparcAssembler::ConditionG,
29 GreaterThanOrEqual = SparcAssembler::ConditionGE,
30 LessThan = SparcAssembler::ConditionL,
31 LessThanOrEqual = SparcAssembler::ConditionLE,
32 Overflow = SparcAssembler::ConditionVS,
33 Signed = SparcAssembler::ConditionNEG,
34 Zero = SparcAssembler::ConditionE,
35 NonZero = SparcAssembler::ConditionNE
36 };
38 enum DoubleCondition {
39 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
40 DoubleEqual = SparcAssembler::DoubleConditionE,
41 DoubleNotEqual = SparcAssembler::DoubleConditionNE,
42 DoubleGreaterThan = SparcAssembler::DoubleConditionG,
43 DoubleGreaterThanOrEqual = SparcAssembler::DoubleConditionGE,
44 DoubleLessThan = SparcAssembler::DoubleConditionL,
45 DoubleLessThanOrEqual = SparcAssembler::DoubleConditionLE,
46 // If either operand is NaN, these conditions always evaluate to true.
47 DoubleEqualOrUnordered = SparcAssembler::DoubleConditionUE,
48 DoubleNotEqualOrUnordered = SparcAssembler::DoubleConditionNE,
49 DoubleGreaterThanOrUnordered = SparcAssembler::DoubleConditionUG,
50 DoubleGreaterThanOrEqualOrUnordered = SparcAssembler::DoubleConditionUGE,
51 DoubleLessThanOrUnordered = SparcAssembler::DoubleConditionUL,
52 DoubleLessThanOrEqualOrUnordered = SparcAssembler::DoubleConditionULE
53 };
55 static const RegisterID stackPointerRegister = SparcRegisters::sp;
57 static const Scale ScalePtr = TimesFour;
58 static const unsigned int TotalRegisters = 24;
60 void add32(RegisterID src, RegisterID dest)
61 {
62 m_assembler.addcc_r(dest, src, dest);
63 }
65 void add32(TrustedImm32 imm, Address address)
66 {
67 load32(address, SparcRegisters::g2);
68 add32(imm, SparcRegisters::g2);
69 store32(SparcRegisters::g2, address);
70 }
72 void add32(TrustedImm32 imm, RegisterID dest)
73 {
74 if (m_assembler.isimm13(imm.m_value))
75 m_assembler.addcc_imm(dest, imm.m_value, dest);
76 else {
77 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
78 m_assembler.addcc_r(dest, SparcRegisters::g3, dest);
79 }
80 }
82 void add32(Address src, RegisterID dest)
83 {
84 load32(src, SparcRegisters::g2);
85 m_assembler.addcc_r(dest, SparcRegisters::g2, dest);
86 }
88 void and32(Address src, RegisterID dest)
89 {
90 load32(src, SparcRegisters::g2);
91 m_assembler.andcc_r(dest, SparcRegisters::g2, dest);
92 }
94 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
95 {
96 if (m_assembler.isimm13(imm.m_value))
97 m_assembler.addcc_imm(src, imm.m_value, dest);
98 else {
99 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
100 m_assembler.addcc_r(src, SparcRegisters::g3, dest);
101 }
102 }
104 void and32(RegisterID src, RegisterID dest)
105 {
106 m_assembler.andcc_r(dest, src, dest);
107 }
109 void and32(Imm32 imm, RegisterID dest)
110 {
111 if (m_assembler.isimm13(imm.m_value))
112 m_assembler.andcc_imm(dest, imm.m_value, dest);
113 else {
114 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
115 m_assembler.andcc_r(dest, SparcRegisters::g3, dest);
116 }
117 }
120 void lshift32(RegisterID shift_amount, RegisterID dest)
121 {
122 m_assembler.sll_r(dest, shift_amount, dest);
123 }
125 void lshift32(Imm32 imm, RegisterID dest)
126 {
127 // No need to check if imm.m_value.
128 // The last 5 bit of imm.m_value will be used anyway.
129 m_assembler.sll_imm(dest, imm.m_value, dest);
130 }
132 void mul32(RegisterID src, RegisterID dest)
133 {
134 m_assembler.smulcc_r(dest, src, dest);
135 }
137 void mul32(Imm32 imm, RegisterID src, RegisterID dest)
138 {
139 if (m_assembler.isimm13(imm.m_value))
140 m_assembler.smulcc_imm(dest, imm.m_value, dest);
141 else {
142 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
143 m_assembler.smulcc_r(SparcRegisters::g3, dest, dest);
144 }
145 }
147 void neg32(RegisterID srcDest)
148 {
149 m_assembler.subcc_r(SparcRegisters::g0, srcDest, srcDest);
150 }
152 void not32(RegisterID dest)
153 {
154 m_assembler.xnorcc_r(dest, SparcRegisters::g0, dest);
155 }
157 void or32(RegisterID src, RegisterID dest)
158 {
159 m_assembler.orcc_r(dest, src, dest);
160 }
162 void or32(TrustedImm32 imm, RegisterID dest)
163 {
164 if (m_assembler.isimm13(imm.m_value))
165 m_assembler.orcc_imm(dest, imm.m_value, dest);
166 else {
167 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
168 m_assembler.or_r(SparcRegisters::g3, dest, dest);
169 }
170 }
173 void or32(Address address, RegisterID dest)
174 {
175 load32(address, SparcRegisters::g2);
176 or32(SparcRegisters::g2, dest);
177 }
179 void rshift32(RegisterID shift_amount, RegisterID dest)
180 {
181 m_assembler.sra_r(dest, shift_amount, dest);
182 }
184 void rshift32(Imm32 imm, RegisterID dest)
185 {
186 // No need to check if imm.m_value.
187 // The last 5 bit of imm.m_value will be used anyway.
188 m_assembler.sra_imm(dest, imm.m_value, dest);
189 }
191 void urshift32(RegisterID shift_amount, RegisterID dest)
192 {
193 m_assembler.srl_r(dest, shift_amount, dest);
194 }
196 void urshift32(Imm32 imm, RegisterID dest)
197 {
198 // No need to check if imm.m_value.
199 // The last 5 bit of imm.m_value will be used anyway.
200 m_assembler.srl_imm(dest, imm.m_value, dest);
201 }
203 void sub32(RegisterID src, RegisterID dest)
204 {
205 m_assembler.subcc_r(dest, src, dest);
206 }
208 void sub32(TrustedImm32 imm, RegisterID dest)
209 {
210 if (m_assembler.isimm13(imm.m_value))
211 m_assembler.subcc_imm(dest, imm.m_value, dest);
212 else {
213 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
214 m_assembler.subcc_r(dest, SparcRegisters::g3, dest);
215 }
216 }
218 void sub32(TrustedImm32 imm, Address address)
219 {
220 load32(address, SparcRegisters::g2);
221 sub32(imm, SparcRegisters::g2);
222 store32(SparcRegisters::g2, address);
223 }
225 void sub32(Address src, RegisterID dest)
226 {
227 load32(src, SparcRegisters::g2);
228 sub32(SparcRegisters::g2, dest);
229 }
231 void xor32(RegisterID src, RegisterID dest)
232 {
233 m_assembler.xorcc_r(src, dest, dest);
234 }
236 void xor32(TrustedImm32 imm, RegisterID dest)
237 {
238 if (m_assembler.isimm13(imm.m_value))
239 m_assembler.xorcc_imm(dest, imm.m_value, dest);
240 else {
241 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
242 m_assembler.xorcc_r(dest, SparcRegisters::g3, dest);
243 }
244 }
246 void xor32(Address src, RegisterID dest)
247 {
248 load32(src, SparcRegisters::g2);
249 xor32(SparcRegisters::g2, dest);
250 }
252 void load8(ImplicitAddress address, RegisterID dest)
253 {
254 if (m_assembler.isimm13(address.offset))
255 m_assembler.ldub_imm(address.base, address.offset, dest);
256 else {
257 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
258 m_assembler.ldub_r(address.base, SparcRegisters::g3, dest);
259 }
260 }
262 void load32(ImplicitAddress address, RegisterID dest)
263 {
264 if (m_assembler.isimm13(address.offset))
265 m_assembler.lduw_imm(address.base, address.offset, dest);
266 else {
267 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
268 m_assembler.lduw_r(address.base, SparcRegisters::g3, dest);
269 }
270 }
272 void load32(BaseIndex address, RegisterID dest)
273 {
274 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
275 add32(Imm32(address.offset), SparcRegisters::g2);
276 m_assembler.lduw_r(address.base, SparcRegisters::g2, dest);
277 }
279 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
280 {
281 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
282 add32(Imm32(address.offset+3), SparcRegisters::g2);
283 m_assembler.ldub_r(address.base, SparcRegisters::g2, dest);
284 m_assembler.subcc_imm(SparcRegisters::g2, 1, SparcRegisters::g2);
285 m_assembler.ldub_r(address.base, SparcRegisters::g2, SparcRegisters::g3);
286 m_assembler.sll_imm(SparcRegisters::g3, 8, SparcRegisters::g3);
287 m_assembler.or_r(SparcRegisters::g3, dest, dest);
288 m_assembler.subcc_imm(SparcRegisters::g2, 1, SparcRegisters::g2);
289 m_assembler.ldub_r(address.base, SparcRegisters::g2, SparcRegisters::g3);
290 m_assembler.sll_imm(SparcRegisters::g3, 16, SparcRegisters::g3);
291 m_assembler.or_r(SparcRegisters::g3, dest, dest);
292 m_assembler.subcc_imm(SparcRegisters::g2, 1, SparcRegisters::g2);
293 m_assembler.ldub_r(address.base, SparcRegisters::g2, SparcRegisters::g3);
294 m_assembler.sll_imm(SparcRegisters::g3, 24, SparcRegisters::g3);
295 m_assembler.or_r(SparcRegisters::g3, dest, dest);
296 }
298 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
299 {
300 DataLabel32 dataLabel(this);
301 m_assembler.move_nocheck(0, SparcRegisters::g3);
302 m_assembler.lduw_r(address.base, SparcRegisters::g3, dest);
303 return dataLabel;
304 }
306 DataLabel32 load64WithAddressOffsetPatch(Address address, RegisterID hi, RegisterID lo)
307 {
308 DataLabel32 dataLabel(this);
309 m_assembler.move_nocheck(0, SparcRegisters::g3);
310 m_assembler.add_imm(SparcRegisters::g3, 4, SparcRegisters::g2);
311 m_assembler.lduw_r(address.base, SparcRegisters::g3, hi);
312 m_assembler.lduw_r(address.base, SparcRegisters::g2, lo);
313 return dataLabel;
314 }
316 Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
317 {
318 Label label(this);
319 load32(address, dest);
320 return label;
321 }
323 void load16(BaseIndex address, RegisterID dest)
324 {
325 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
326 add32(Imm32(address.offset), SparcRegisters::g2);
327 m_assembler.lduh_r(address.base, SparcRegisters::g2, dest);
328 }
330 void load16(ImplicitAddress address, RegisterID dest)
331 {
332 if (m_assembler.isimm13(address.offset))
333 m_assembler.lduh_imm(address.base, address.offset, dest);
334 else {
335 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
336 m_assembler.lduh_r(address.base, SparcRegisters::g3, dest);
337 }
338 }
340 void store8(RegisterID src, ImplicitAddress address)
341 {
342 if (m_assembler.isimm13(address.offset))
343 m_assembler.stb_imm(src, address.base, address.offset);
344 else {
345 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
346 m_assembler.stb_r(src, address.base, SparcRegisters::g3);
347 }
348 }
350 void store8(RegisterID src, BaseIndex address)
351 {
352 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
353 add32(Imm32(address.offset), SparcRegisters::g2);
354 m_assembler.stb_r(src, address.base, SparcRegisters::g2);
355 }
357 void store8(Imm32 imm, ImplicitAddress address)
358 {
359 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
360 store8(SparcRegisters::g2, address);
361 }
363 void store8(Imm32 imm, BaseIndex address)
364 {
365 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
366 add32(Imm32(address.offset), SparcRegisters::g2);
367 move(imm, SparcRegisters::g3);
368 m_assembler.stb_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
369 }
371 void store16(RegisterID src, ImplicitAddress address)
372 {
373 if (m_assembler.isimm13(address.offset))
374 m_assembler.sth_imm(src, address.base, address.offset);
375 else {
376 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
377 m_assembler.sth_r(src, address.base, SparcRegisters::g3);
378 }
379 }
381 void store16(RegisterID src, BaseIndex address)
382 {
383 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
384 add32(Imm32(address.offset), SparcRegisters::g2);
385 m_assembler.sth_r(src, address.base, SparcRegisters::g2);
386 }
388 void store16(Imm32 imm, ImplicitAddress address)
389 {
390 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
391 store16(SparcRegisters::g2, address);
392 }
394 void store16(Imm32 imm, BaseIndex address)
395 {
396 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
397 add32(Imm32(address.offset), SparcRegisters::g2);
398 move(imm, SparcRegisters::g3);
399 m_assembler.sth_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
400 }
402 void load8ZeroExtend(BaseIndex address, RegisterID dest)
403 {
404 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
405 add32(Imm32(address.offset), SparcRegisters::g2);
406 m_assembler.ldub_r(address.base, SparcRegisters::g2, dest);
407 }
409 void load8ZeroExtend(Address address, RegisterID dest)
410 {
411 if (m_assembler.isimm13(address.offset))
412 m_assembler.ldub_imm(address.base, address.offset, dest);
413 else {
414 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
415 m_assembler.ldub_r(address.base, SparcRegisters::g3, dest);
416 }
417 }
419 void load8SignExtend(BaseIndex address, RegisterID dest)
420 {
421 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
422 add32(Imm32(address.offset), SparcRegisters::g2);
423 m_assembler.ldsb_r(address.base, SparcRegisters::g2, dest);
424 }
426 void load8SignExtend(Address address, RegisterID dest)
427 {
428 if (m_assembler.isimm13(address.offset))
429 m_assembler.ldsb_imm(address.base, address.offset, dest);
430 else {
431 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
432 m_assembler.ldsb_r(address.base, SparcRegisters::g3, dest);
433 }
434 }
436 void load16SignExtend(BaseIndex address, RegisterID dest)
437 {
438 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
439 add32(Imm32(address.offset), SparcRegisters::g2);
440 m_assembler.ldsh_r(address.base, SparcRegisters::g2, dest);
441 }
443 void load16SignExtend(Address address, RegisterID dest)
444 {
445 if (m_assembler.isimm13(address.offset))
446 m_assembler.ldsh_imm(address.base, address.offset, dest);
447 else {
448 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
449 m_assembler.ldsh_r(address.base, SparcRegisters::g3, dest);
450 }
451 }
453 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
454 {
455 DataLabel32 dataLabel(this);
456 // Since this is for patch, we don't check is offset is imm13.
457 m_assembler.move_nocheck(0, SparcRegisters::g3);
458 m_assembler.stw_r(src, address.base, SparcRegisters::g3);
459 return dataLabel;
460 }
463 DataLabel32 store64WithAddressOffsetPatch(RegisterID hi, RegisterID lo, Address address)
464 {
465 DataLabel32 dataLabel(this);
466 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
467 m_assembler.add_r(SparcRegisters::g3, address.base, SparcRegisters::g3);
468 m_assembler.stw_imm(lo, SparcRegisters::g3, 4);
469 m_assembler.stw_imm(hi, SparcRegisters::g3, 0);
470 return dataLabel;
471 }
473 DataLabel32 store64WithAddressOffsetPatch(Imm32 hi, RegisterID lo, Address address)
474 {
475 DataLabel32 dataLabel(this);
476 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
477 m_assembler.add_r(SparcRegisters::g3, address.base, SparcRegisters::g3);
478 m_assembler.stw_imm(lo, SparcRegisters::g3, 4);
479 move(hi, SparcRegisters::g2);
480 m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::g3, 0);
482 return dataLabel;
483 }
485 DataLabel32 store64WithAddressOffsetPatch(Imm32 hi, Imm32 lo, Address address)
486 {
487 DataLabel32 dataLabel(this);
488 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
489 m_assembler.add_r(SparcRegisters::g3, address.base, SparcRegisters::g3);
490 move(lo, SparcRegisters::g2);
491 m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::g3, 4);
492 move(hi, SparcRegisters::g2);
493 m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::g3, 0);
495 return dataLabel;
496 }
499 void store32(RegisterID src, ImplicitAddress address)
500 {
501 if (m_assembler.isimm13(address.offset))
502 m_assembler.stw_imm(src, address.base, address.offset);
503 else {
504 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
505 m_assembler.stw_r(src, address.base, SparcRegisters::g3);
506 }
507 }
509 void store32(RegisterID src, BaseIndex address)
510 {
511 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
512 add32(Imm32(address.offset), SparcRegisters::g2);
513 m_assembler.stw_r(src, address.base, SparcRegisters::g2);
514 }
516 void store32(TrustedImm32 imm, BaseIndex address)
517 {
518 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
519 add32(Imm32(address.offset), SparcRegisters::g2);
520 move(imm, SparcRegisters::g3);
521 m_assembler.stw_r(SparcRegisters::g3, SparcRegisters::g2, address.base);
522 }
524 void store32(TrustedImm32 imm, ImplicitAddress address)
525 {
526 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g2);
527 store32(SparcRegisters::g2, address);
528 }
530 void store32(RegisterID src, void* address)
531 {
532 m_assembler.move_nocheck((int)address, SparcRegisters::g3);
533 m_assembler.stw_r(src, SparcRegisters::g0, SparcRegisters::g3);
534 }
536 void store32(TrustedImm32 imm, void* address)
537 {
538 move(imm, SparcRegisters::g2);
539 store32(SparcRegisters::g2, address);
540 }
542 void pop(RegisterID dest)
543 {
544 m_assembler.lduw_imm(SparcRegisters::sp, 0x68, dest);
545 m_assembler.addcc_imm(SparcRegisters::sp, 4, SparcRegisters::sp);
546 }
548 void push(RegisterID src)
549 {
550 m_assembler.subcc_imm(SparcRegisters::sp, 4, SparcRegisters::sp);
551 m_assembler.stw_imm(src, SparcRegisters::sp, 0x68);
552 }
554 void push(Address address)
555 {
556 load32(address, SparcRegisters::g2);
557 push(SparcRegisters::g2);
558 }
560 void push(Imm32 imm)
561 {
562 move(imm, SparcRegisters::g2);
563 push(SparcRegisters::g2);
564 }
566 void move(TrustedImm32 imm, RegisterID dest)
567 {
568 if (m_assembler.isimm13(imm.m_value))
569 m_assembler.or_imm(SparcRegisters::g0, imm.m_value, dest);
570 else
571 m_assembler.move_nocheck(imm.m_value, dest);
572 }
574 void move(RegisterID src, RegisterID dest)
575 {
576 m_assembler.or_r(src, SparcRegisters::g0, dest);
577 }
579 void move(TrustedImmPtr imm, RegisterID dest)
580 {
581 move(Imm32(imm), dest);
582 }
584 void swap(RegisterID reg1, RegisterID reg2)
585 {
586 m_assembler.or_r(reg1, SparcRegisters::g0, SparcRegisters::g3);
587 m_assembler.or_r(reg2, SparcRegisters::g0, reg1);
588 m_assembler.or_r(SparcRegisters::g3, SparcRegisters::g0, reg2);
589 }
591 void signExtend32ToPtr(RegisterID src, RegisterID dest)
592 {
593 if (src != dest)
594 move(src, dest);
595 }
597 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
598 {
599 if (src != dest)
600 move(src, dest);
601 }
603 Jump branch8(Condition cond, Address left, Imm32 right)
604 {
605 load8(left, SparcRegisters::g2);
606 return branch32(cond, SparcRegisters::g2, right);
607 }
609 Jump branch32_force32(Condition cond, RegisterID left, TrustedImm32 right)
610 {
611 m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
612 m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
613 return Jump(m_assembler.branch(SparcCondition(cond)));
614 }
616 Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
617 {
618 m_assembler.move_nocheck(right.m_value, SparcRegisters::g2);
619 return branch32(cond, left, SparcRegisters::g2);
620 }
622 Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32 &dataLabel)
623 {
624 // Always use move_nocheck, since the value is to be patched.
625 dataLabel = DataLabel32(this);
626 m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
627 m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
628 return Jump(m_assembler.branch(SparcCondition(cond)));
629 }
631 Jump branch32(Condition cond, RegisterID left, RegisterID right)
632 {
633 m_assembler.subcc_r(left, right, SparcRegisters::g0);
634 return Jump(m_assembler.branch(SparcCondition(cond)));
635 }
637 Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
638 {
639 if (m_assembler.isimm13(right.m_value))
640 m_assembler.subcc_imm(left, right.m_value, SparcRegisters::g0);
641 else {
642 m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
643 m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
644 }
645 return Jump(m_assembler.branch(SparcCondition(cond)));
646 }
648 Jump branch32(Condition cond, RegisterID left, Address right)
649 {
650 load32(right, SparcRegisters::g2);
651 return branch32(cond, left, SparcRegisters::g2);
652 }
654 Jump branch32(Condition cond, Address left, RegisterID right)
655 {
656 load32(left, SparcRegisters::g2);
657 return branch32(cond, SparcRegisters::g2, right);
658 }
660 Jump branch32(Condition cond, Address left, TrustedImm32 right)
661 {
662 load32(left, SparcRegisters::g2);
663 return branch32(cond, SparcRegisters::g2, right);
664 }
666 Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
667 {
669 load32(left, SparcRegisters::g2);
670 return branch32(cond, SparcRegisters::g2, right);
671 }
673 Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
674 {
675 load32WithUnalignedHalfWords(left, SparcRegisters::g4);
676 return branch32(cond, SparcRegisters::g4, right);
677 }
679 Jump branch16(Condition cond, BaseIndex left, RegisterID right)
680 {
681 (void)(cond);
682 (void)(left);
683 (void)(right);
684 ASSERT_NOT_REACHED();
685 return jump();
686 }
688 Jump branch16(Condition cond, BaseIndex left, Imm32 right)
689 {
690 load16(left, SparcRegisters::g3);
691 move(right, SparcRegisters::g2);
692 m_assembler.subcc_r(SparcRegisters::g3, SparcRegisters::g2, SparcRegisters::g0);
693 return Jump(m_assembler.branch(SparcCondition(cond)));
694 }
696 Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
697 {
698 load8(address, SparcRegisters::g2);
699 return branchTest32(cond, SparcRegisters::g2, mask);
700 }
702 Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
703 {
704 m_assembler.andcc_r(reg, mask, SparcRegisters::g0);
705 return Jump(m_assembler.branch(SparcCondition(cond)));
706 }
708 Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
709 {
710 if (m_assembler.isimm13(mask.m_value))
711 m_assembler.andcc_imm(reg, mask.m_value, SparcRegisters::g0);
712 else {
713 m_assembler.move_nocheck(mask.m_value, SparcRegisters::g3);
714 m_assembler.andcc_r(reg, SparcRegisters::g3, SparcRegisters::g0);
715 }
716 return Jump(m_assembler.branch(SparcCondition(cond)));
717 }
719 Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
720 {
721 load32(address, SparcRegisters::g2);
722 return branchTest32(cond, SparcRegisters::g2, mask);
723 }
725 Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
726 {
727 // FIXME. branchTest32 only used by PolyIC.
728 // PolyIC is not enabled for sparc now.
729 ASSERT(0);
730 return jump();
731 }
733 Jump jump()
734 {
735 return Jump(m_assembler.jmp());
736 }
738 void jump(RegisterID target)
739 {
740 m_assembler.jmpl_r(SparcRegisters::g0, target, SparcRegisters::g0);
741 m_assembler.nop();
742 }
744 void jump(Address address)
745 {
746 load32(address, SparcRegisters::g2);
747 m_assembler.jmpl_r(SparcRegisters::g2, SparcRegisters::g0, SparcRegisters::g0);
748 m_assembler.nop();
749 }
751 void jump(BaseIndex address)
752 {
753 load32(address, SparcRegisters::g2);
754 m_assembler.jmpl_r(SparcRegisters::g2, SparcRegisters::g0, SparcRegisters::g0);
755 m_assembler.nop();
756 }
758 Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
759 {
760 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
761 m_assembler.addcc_r(src, dest, dest);
762 return Jump(m_assembler.branch(SparcCondition(cond)));
763 }
765 Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
766 {
767 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
768 if (m_assembler.isimm13(imm.m_value))
769 m_assembler.addcc_imm(dest, imm.m_value, dest);
770 else {
771 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
772 m_assembler.addcc_r(dest, SparcRegisters::g3, dest);
773 }
774 return Jump(m_assembler.branch(SparcCondition(cond)));
775 }
777 Jump branchAdd32(Condition cond, Address src, RegisterID dest)
778 {
779 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
780 load32(src, SparcRegisters::g2);
781 return branchAdd32(cond, SparcRegisters::g2, dest);
782 }
784 void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
785 {
786 m_assembler.smulcc_r(src1, src2, dest);
787 }
789 Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
790 {
791 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
792 m_assembler.smulcc_r(src, dest, dest);
793 if (cond == Overflow) {
794 m_assembler.rdy(SparcRegisters::g2);
795 m_assembler.sra_imm(dest, 31, SparcRegisters::g3);
796 m_assembler.subcc_r(SparcRegisters::g2, SparcRegisters::g3, SparcRegisters::g2);
797 cond = NotEqual;
798 }
799 return Jump(m_assembler.branch(SparcCondition(cond)));
800 }
802 Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
803 {
804 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
805 if (m_assembler.isimm13(imm.m_value))
806 m_assembler.smulcc_imm(src, imm.m_value, dest);
807 else {
808 m_assembler.move_nocheck(imm.m_value, SparcRegisters::g3);
809 m_assembler.smulcc_r(src, SparcRegisters::g3, dest);
810 }
811 if (cond == Overflow) {
812 m_assembler.rdy(SparcRegisters::g2);
813 m_assembler.sra_imm(dest, 31, SparcRegisters::g3);
814 m_assembler.subcc_r(SparcRegisters::g2, SparcRegisters::g3, SparcRegisters::g2);
815 cond = NotEqual;
816 }
817 return Jump(m_assembler.branch(SparcCondition(cond)));
818 }
820 Jump branchMul32(Condition cond, Address src, RegisterID dest)
821 {
822 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
823 load32(src, SparcRegisters::g2);
824 return branchMul32(cond, SparcRegisters::g2, dest);
825 }
827 Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
828 {
829 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
830 m_assembler.subcc_r(dest, src, dest);
831 return Jump(m_assembler.branch(SparcCondition(cond)));
832 }
834 Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
835 {
836 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
837 sub32(imm, dest);
838 return Jump(m_assembler.branch(SparcCondition(cond)));
839 }
841 Jump branchSub32(Condition cond, Address src, RegisterID dest)
842 {
843 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
844 load32(src, SparcRegisters::g2);
845 return branchSub32(cond, SparcRegisters::g2, dest);
846 }
848 Jump branchSub32(Condition cond, Imm32 imm, Address dest)
849 {
850 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
851 sub32(imm, dest);
852 return Jump(m_assembler.branch(SparcCondition(cond)));
853 }
855 Jump branchNeg32(Condition cond, RegisterID srcDest)
856 {
857 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
858 neg32(srcDest);
859 return Jump(m_assembler.branch(SparcCondition(cond)));
860 }
862 Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
863 {
864 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
865 m_assembler.orcc_r(src, dest, dest);
866 return Jump(m_assembler.branch(SparcCondition(cond)));
867 }
869 void breakpoint()
870 {
871 m_assembler.ta_imm(8);
872 }
874 Call nearCall()
875 {
876 return Call(m_assembler.call(), Call::LinkableNear);
877 }
879 Call call(RegisterID target)
880 {
881 m_assembler.jmpl_r(target, SparcRegisters::g0, SparcRegisters::o7);
882 m_assembler.nop();
883 JmpSrc jmpSrc;
884 return Call(jmpSrc, Call::None);
885 }
887 void call(Address address)
888 {
889 if (m_assembler.isimm13(address.offset)) {
890 m_assembler.jmpl_imm(address.base, address.offset, SparcRegisters::o7);
891 m_assembler.nop();
892 } else {
893 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
894 m_assembler.jmpl_r(address.base, SparcRegisters::g3, SparcRegisters::o7);
895 m_assembler.nop();
896 }
897 }
899 void ret()
900 {
901 m_assembler.jmpl_imm(SparcRegisters::i7, 8, SparcRegisters::g0);
902 m_assembler.nop();
903 }
905 void ret_and_restore()
906 {
907 m_assembler.jmpl_imm(SparcRegisters::i7, 8, SparcRegisters::g0);
908 m_assembler.restore_r(SparcRegisters::g0, SparcRegisters::g0, SparcRegisters::g0);
909 }
911 void save(Imm32 size)
912 {
913 if (m_assembler.isimm13(size.m_value)) {
914 m_assembler.save_imm(SparcRegisters::sp, size.m_value, SparcRegisters::sp);
915 } else {
916 m_assembler.move_nocheck(size.m_value, SparcRegisters::g3);
917 m_assembler.save_r(SparcRegisters::sp, SparcRegisters::g3, SparcRegisters::sp);
918 }
919 }
921 void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
922 {
923 load32(left, SparcRegisters::g2);
924 set32(cond, SparcRegisters::g2, right, dest);
925 }
927 void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
928 {
929 load32(right, SparcRegisters::g2);
930 set32(cond, left, SparcRegisters::g2, dest);
931 }
933 void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
934 {
935 m_assembler.subcc_r(left, right, SparcRegisters::g0);
936 m_assembler.or_imm(SparcRegisters::g0, 0, dest);
937 m_assembler.movcc_imm(1, dest, SparcCondition(cond));
938 }
940 void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
941 {
942 if (m_assembler.isimm13(right.m_value))
943 m_assembler.subcc_imm(left, right.m_value, SparcRegisters::g0);
944 else {
945 m_assembler.move_nocheck(right.m_value, SparcRegisters::g3);
946 m_assembler.subcc_r(left, SparcRegisters::g3, SparcRegisters::g0);
947 }
948 m_assembler.or_imm(SparcRegisters::g0, 0, dest);
949 m_assembler.movcc_imm(1, dest, SparcCondition(cond));
950 }
952 void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
953 {
954 load32(left, SparcRegisters::g2);
955 set32(cond, SparcRegisters::g2, right, dest);
956 }
958 void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
959 {
960 // Sparc does not have byte register.
961 set32(cond, left, right, dest);
962 }
964 void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
965 {
966 // Sparc doesn't have byte registers
967 load32(left, SparcRegisters::g2);
968 set32(cond, SparcRegisters::g2, right, dest);
969 }
971 void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
972 {
973 // Sparc does not have byte register.
974 set32(cond, left, right, dest);
975 }
977 void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
978 {
979 load32(address, SparcRegisters::g2);
980 if (m_assembler.isimm13(mask.m_value))
981 m_assembler.andcc_imm(SparcRegisters::g2, mask.m_value, SparcRegisters::g0);
982 else {
983 m_assembler.move_nocheck(mask.m_value, SparcRegisters::g3);
984 m_assembler.andcc_r(SparcRegisters::g3, SparcRegisters::g2, SparcRegisters::g0);
985 }
986 m_assembler.or_imm(SparcRegisters::g0, 0, dest);
987 m_assembler.movcc_imm(1, dest, SparcCondition(cond));
988 }
990 void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
991 {
992 // Sparc does not have byte register.
993 setTest32(cond, address, mask, dest);
994 }
996 void lea(Address address, RegisterID dest)
997 {
998 if (m_assembler.isimm13(address.offset))
999 m_assembler.add_imm(address.base, address.offset, dest);
1000 else {
1001 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
1002 m_assembler.add_r(address.base, SparcRegisters::g3, dest);
1003 }
1004 }
1006 void lea(BaseIndex address, RegisterID dest)
1007 {
1008 // lea only used by PolyIC.
1009 // PolyIC is not enabled for sparc now.
1010 ASSERT(0);
1011 }
1013 void add32(Imm32 imm, AbsoluteAddress address)
1014 {
1015 load32(address.m_ptr, SparcRegisters::g2);
1016 add32(imm, SparcRegisters::g2);
1017 store32(SparcRegisters::g2, address.m_ptr);
1018 }
1020 void sub32(TrustedImm32 imm, AbsoluteAddress address)
1021 {
1022 load32(address.m_ptr, SparcRegisters::g2);
1023 sub32(imm, SparcRegisters::g2);
1024 store32(SparcRegisters::g2, address.m_ptr);
1025 }
1027 void load32(const void* address, RegisterID dest)
1028 {
1029 m_assembler.move_nocheck((int)address, SparcRegisters::g3);
1030 m_assembler.lduw_r(SparcRegisters::g3, SparcRegisters::g0, dest);
1031 }
1033 Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
1034 {
1035 load32(left.m_ptr, SparcRegisters::g2);
1036 return branch32(cond, SparcRegisters::g2, right);
1037 }
1039 Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
1040 {
1041 load32(left.m_ptr, SparcRegisters::g2);
1042 return branch32(cond, SparcRegisters::g2, right);
1043 }
1045 Call call()
1046 {
1047 m_assembler.rdpc(SparcRegisters::g2);
1048 m_assembler.add_imm(SparcRegisters::g2, 32, SparcRegisters::g2);
1049 m_assembler.stw_imm(SparcRegisters::g2, SparcRegisters::fp, -8);
1050 Call cl = Call(m_assembler.call(), Call::Linkable);
1051 m_assembler.lduw_imm(SparcRegisters::fp, -8, SparcRegisters::g2);
1052 m_assembler.jmpl_imm(SparcRegisters::g2, 0, SparcRegisters::g0);
1053 m_assembler.nop();
1054 return cl;
1055 }
1057 Call tailRecursiveCall()
1058 {
1059 return Call::fromTailJump(jump());
1060 }
1062 Call makeTailRecursiveCall(Jump oldJump)
1063 {
1064 return Call::fromTailJump(oldJump);
1065 }
1067 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
1068 {
1069 DataLabelPtr dataLabel(this);
1070 Imm32 imm = Imm32(initialValue);
1071 m_assembler.move_nocheck(imm.m_value, dest);
1072 return dataLabel;
1073 }
1075 DataLabel32 moveWithPatch(TrustedImm32 initialValue, RegisterID dest)
1076 {
1077 DataLabel32 dataLabel(this);
1078 m_assembler.move_nocheck(initialValue.m_value, dest);
1079 return dataLabel;
1080 }
1082 Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
1083 {
1084 dataLabel = moveWithPatch(initialRightValue, SparcRegisters::g2);
1085 Jump jump = branch32(cond, left, SparcRegisters::g2);
1086 return jump;
1087 }
1089 Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
1090 {
1091 load32(left, SparcRegisters::g2);
1092 dataLabel = moveWithPatch(initialRightValue, SparcRegisters::g3);
1093 Jump jump = branch32(cond, SparcRegisters::g3, SparcRegisters::g2);
1094 return jump;
1095 }
1097 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
1098 {
1099 DataLabelPtr dataLabel = moveWithPatch(initialValue, SparcRegisters::g2);
1100 store32(SparcRegisters::g2, address);
1101 return dataLabel;
1102 }
1104 DataLabelPtr storePtrWithPatch(ImplicitAddress address)
1105 {
1106 return storePtrWithPatch(ImmPtr(0), address);
1107 }
1109 // Floating point operators
1110 static bool supportsFloatingPoint()
1111 {
1112 return true;
1113 }
1115 static bool supportsFloatingPointTruncate()
1116 {
1117 return true;
1118 }
1120 static bool supportsFloatingPointSqrt()
1121 {
1122 return true;
1123 }
1125 void moveDouble(FPRegisterID src, FPRegisterID dest)
1126 {
1127 m_assembler.fmovd_r(src, dest);
1128 }
1130 void loadFloat(BaseIndex address, FPRegisterID dest)
1131 {
1132 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
1133 add32(Imm32(address.offset), SparcRegisters::g2);
1134 m_assembler.ldf_r(address.base, SparcRegisters::g2, dest);
1135 m_assembler.fstod_r(dest, dest);
1136 }
1138 void loadFloat(ImplicitAddress address, FPRegisterID dest)
1139 {
1140 if (m_assembler.isimm13(address.offset))
1141 m_assembler.ldf_imm(address.base, address.offset, dest);
1142 else {
1143 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
1144 m_assembler.ldf_r(address.base, SparcRegisters::g3, dest);
1145 }
1146 m_assembler.fstod_r(dest, dest);
1147 }
1149 void loadFloat(const void* address, FPRegisterID dest)
1150 {
1151 m_assembler.move_nocheck((int)address, SparcRegisters::g3);
1152 m_assembler.ldf_r(SparcRegisters::g3, SparcRegisters::g0, dest);
1153 m_assembler.fstod_r(dest, dest);
1154 }
1156 void loadDouble(BaseIndex address, FPRegisterID dest)
1157 {
1158 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
1159 add32(Imm32(address.offset), SparcRegisters::g2);
1160 m_assembler.ldf_r(address.base, SparcRegisters::g2, dest);
1161 m_assembler.add_imm(SparcRegisters::g2, 4, SparcRegisters::g2);
1162 m_assembler.ldf_r(address.base, SparcRegisters::g2, dest + 1);
1163 }
1165 void loadDouble(ImplicitAddress address, FPRegisterID dest)
1166 {
1167 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
1168 m_assembler.ldf_r(address.base, SparcRegisters::g3, dest);
1169 m_assembler.add_imm(SparcRegisters::g3, 4, SparcRegisters::g3);
1170 m_assembler.ldf_r(address.base, SparcRegisters::g3, dest + 1);
1171 }
1173 DataLabelPtr loadDouble(const void* address, FPRegisterID dest)
1174 {
1175 DataLabelPtr dataLabel(this);
1176 m_assembler.move_nocheck((int)address, SparcRegisters::g3);
1177 m_assembler.ldf_imm(SparcRegisters::g3, 0, dest);
1178 m_assembler.ldf_imm(SparcRegisters::g3, 4, dest + 1);
1179 return dataLabel;
1180 }
1182 void storeFloat(FPRegisterID src, BaseIndex address)
1183 {
1184 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
1185 add32(Imm32(address.offset), SparcRegisters::g2);
1186 m_assembler.stf_r(src, address.base, SparcRegisters::g2);
1187 }
1189 void storeFloat(FPRegisterID src, ImplicitAddress address)
1190 {
1191 if (m_assembler.isimm13(address.offset))
1192 m_assembler.stf_imm(src, address.base, address.offset);
1193 else {
1194 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
1195 m_assembler.stf_r(src, address.base, SparcRegisters::g3);
1196 }
1197 }
1199 void storeFloat(ImmDouble imm, Address address)
1200 {
1201 union {
1202 float f;
1203 uint32_t u32;
1204 } u;
1205 u.f = imm.u.d;
1206 store32(Imm32(u.u32), address);
1207 }
1209 void storeFloat(ImmDouble imm, BaseIndex address)
1210 {
1211 union {
1212 float f;
1213 uint32_t u32;
1214 } u;
1215 u.f = imm.u.d;
1216 store32(Imm32(u.u32), address);
1217 }
1219 void storeDouble(FPRegisterID src, BaseIndex address)
1220 {
1221 m_assembler.sll_imm(address.index, address.scale, SparcRegisters::g2);
1222 add32(Imm32(address.offset), SparcRegisters::g2);
1223 m_assembler.stf_r(src, address.base, SparcRegisters::g2);
1224 m_assembler.add_imm(SparcRegisters::g2, 4, SparcRegisters::g2);
1225 m_assembler.stf_r(src + 1, address.base, SparcRegisters::g2);
1226 }
1228 void storeDouble(FPRegisterID src, ImplicitAddress address)
1229 {
1230 if (m_assembler.isimm13(address.offset + 4)) {
1231 m_assembler.stf_imm(src, address.base, address.offset);
1232 m_assembler.stf_imm(src + 1, address.base, address.offset + 4);
1233 } else {
1234 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
1235 m_assembler.stf_r(src, address.base, SparcRegisters::g3);
1236 m_assembler.add_imm(SparcRegisters::g3, 4, SparcRegisters::g3);
1237 m_assembler.stf_r(src + 1, address.base, SparcRegisters::g3);
1238 }
1239 }
1241 void storeDouble(ImmDouble imm, Address address)
1242 {
1243 store32(Imm32(imm.u.s.msb), address);
1244 store32(Imm32(imm.u.s.lsb), Address(address.base, address.offset + 4));
1245 }
1247 void storeDouble(ImmDouble imm, BaseIndex address)
1248 {
1249 store32(Imm32(imm.u.s.msb), address);
1250 store32(Imm32(imm.u.s.lsb),
1251 BaseIndex(address.base, address.index, address.scale, address.offset + 4));
1252 }
1254 void addDouble(FPRegisterID src, FPRegisterID dest)
1255 {
1256 m_assembler.faddd_r(src, dest, dest);
1257 }
1259 void addDouble(Address src, FPRegisterID dest)
1260 {
1261 loadDouble(src, SparcRegisters::f30);
1262 m_assembler.faddd_r(SparcRegisters::f30, dest, dest);
1263 }
1265 void divDouble(FPRegisterID src, FPRegisterID dest)
1266 {
1267 m_assembler.fdivd_r(dest, src, dest);
1268 }
1270 void divDouble(Address src, FPRegisterID dest)
1271 {
1272 loadDouble(src, SparcRegisters::f30);
1273 m_assembler.fdivd_r(dest, SparcRegisters::f30, dest);
1274 }
1276 void subDouble(FPRegisterID src, FPRegisterID dest)
1277 {
1278 m_assembler.fsubd_r(dest, src, dest);
1279 }
1281 void subDouble(Address src, FPRegisterID dest)
1282 {
1283 loadDouble(src, SparcRegisters::f30);
1284 m_assembler.fsubd_r(dest, SparcRegisters::f30, dest);
1285 }
1287 void mulDouble(FPRegisterID src, FPRegisterID dest)
1288 {
1289 m_assembler.fmuld_r(src, dest, dest);
1290 }
1292 void mulDouble(Address src, FPRegisterID dest)
1293 {
1294 loadDouble(src, SparcRegisters::f30);
1295 m_assembler.fmuld_r(SparcRegisters::f30, dest, dest);
1296 }
1298 void absDouble(FPRegisterID src, FPRegisterID dest)
1299 {
1300 m_assembler.fabsd_r(src, dest);
1301 }
1303 void sqrtDouble(FPRegisterID src, FPRegisterID dest)
1304 {
1305 m_assembler.fsqrtd_r(src, dest);
1306 }
1308 void negDouble(FPRegisterID src, FPRegisterID dest)
1309 {
1310 m_assembler.fnegd_r(src, dest);
1311 }
1313 void convertUInt32ToDouble(RegisterID src, FPRegisterID dest)
1314 {
1315 m_assembler.move_nocheck(0x43300000, SparcRegisters::g1);
1316 m_assembler.stw_imm(SparcRegisters::g1, SparcRegisters::sp, 0x60);
1317 m_assembler.stw_imm(src, SparcRegisters::sp, 0x64);
1318 m_assembler.ldf_imm(SparcRegisters::sp, 0x60, SparcRegisters::f30);
1319 m_assembler.ldf_imm(SparcRegisters::sp, 0x64, SparcRegisters::f31);
1320 m_assembler.stw_imm(SparcRegisters::g0, SparcRegisters::sp, 0x64);
1321 m_assembler.ldf_imm(SparcRegisters::sp, 0x60, dest);
1322 m_assembler.ldf_imm(SparcRegisters::sp, 0x64, dest + 1);
1323 m_assembler.fsubd_r(SparcRegisters::f30, dest, dest);
1324 m_assembler.fabss_r(dest, dest);
1325 }
1327 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
1328 {
1329 m_assembler.stw_imm(src, SparcRegisters::sp, 0x60);
1330 m_assembler.ldf_imm(SparcRegisters::sp, 0x60, dest);
1331 m_assembler.fitod_r(dest, dest);
1332 }
1334 void convertInt32ToDouble(Address address, FPRegisterID dest)
1335 {
1336 if (m_assembler.isimm13(address.offset))
1337 m_assembler.ldf_imm(address.base, address.offset, dest);
1338 else {
1339 m_assembler.move_nocheck(address.offset, SparcRegisters::g3);
1340 m_assembler.ldf_r(address.base, SparcRegisters::g3, dest);
1341 }
1342 m_assembler.fitod_r(dest, dest);
1343 }
1345 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
1346 {
1347 m_assembler.move_nocheck((int)src.m_ptr, SparcRegisters::g3);
1348 m_assembler.ldf_r(SparcRegisters::g3, SparcRegisters::g0, dest);
1349 m_assembler.fitod_r(dest, dest);
1350 }
1352 void fastLoadDouble(RegisterID lo, RegisterID hi, FPRegisterID fpReg)
1353 {
1354 m_assembler.stw_imm(lo, SparcRegisters::sp, 0x64);
1355 m_assembler.stw_imm(hi, SparcRegisters::sp, 0x60);
1356 m_assembler.ldf_imm(SparcRegisters::sp, 0x60, fpReg);
1357 m_assembler.ldf_imm(SparcRegisters::sp, 0x64, fpReg + 1);
1358 }
1360 void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
1361 {
1362 m_assembler.fdtos_r(src, dest);
1363 }
1365 void breakDoubleTo32(FPRegisterID srcDest, RegisterID typeReg, RegisterID dataReg) {
1366 // We don't assume stack is aligned to 8.
1367 // Always using stf, ldf instead of stdf, lddf.
1368 m_assembler.stf_imm(srcDest, SparcRegisters::sp, 0x60);
1369 m_assembler.stf_imm(srcDest + 1, SparcRegisters::sp, 0x64);
1370 m_assembler.lduw_imm(SparcRegisters::sp, 0x60, typeReg);
1371 m_assembler.lduw_imm(SparcRegisters::sp, 0x64, dataReg);
1372 }
1374 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
1375 {
1376 m_assembler.fcmpd_r(left, right);
1377 return Jump(m_assembler.fbranch(SparcDoubleCondition(cond)));
1378 }
1380 // Truncates 'src' to an integer, and places the resulting 'dest'.
1381 // If the result is not representable as a 32 bit value, branch.
1382 // May also branch for some values that are representable in 32 bits
1383 // (specifically, in this case, INT_MIN).
1384 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
1385 {
1386 m_assembler.fdtoi_r(src, SparcRegisters::f30);
1387 m_assembler.stf_imm(SparcRegisters::f30, SparcRegisters::sp, 0x60);
1388 m_assembler.lduw_imm(SparcRegisters::sp, 0x60, dest);
1390 m_assembler.or_r(SparcRegisters::g0, SparcRegisters::g0, SparcRegisters::g2);
1391 m_assembler.move_nocheck(0x80000000, SparcRegisters::g3);
1392 m_assembler.subcc_r(SparcRegisters::g3, dest, SparcRegisters::g0);
1393 m_assembler.movcc_imm(1, SparcRegisters::g2, SparcCondition(Equal));
1394 m_assembler.move_nocheck(0x7fffffff, SparcRegisters::g3);
1395 m_assembler.subcc_r(SparcRegisters::g3, dest, SparcRegisters::g0);
1396 m_assembler.movcc_imm(1, SparcRegisters::g2, SparcCondition(Equal));
1398 return branch32(Equal, SparcRegisters::g2, Imm32(1));
1399 }
1401 // Convert 'src' to an integer, and places the resulting 'dest'.
1402 // If the result is not representable as a 32 bit value, branch.
1403 // May also branch for some values that are representable in 32 bits
1404 // (specifically, in this case, 0).
1405 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
1406 {
1407 m_assembler.fdtoi_r(src, SparcRegisters::f30);
1408 m_assembler.stf_imm(SparcRegisters::f30, SparcRegisters::sp, 0x60);
1409 m_assembler.lduw_imm(SparcRegisters::sp, 0x60, dest);
1411 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
1412 m_assembler.fitod_r(SparcRegisters::f30, SparcRegisters::f30);
1413 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, SparcRegisters::f30));
1415 // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
1416 failureCases.append(branchTest32(Zero, dest));
1417 }
1419 void zeroDouble(FPRegisterID srcDest)
1420 {
1421 fastLoadDouble(SparcRegisters::g0, SparcRegisters::g0, srcDest);
1422 }
1424 protected:
1425 SparcAssembler::Condition SparcCondition(Condition cond)
1426 {
1427 return static_cast<SparcAssembler::Condition>(cond);
1428 }
1430 SparcAssembler::DoubleCondition SparcDoubleCondition(DoubleCondition cond)
1431 {
1432 return static_cast<SparcAssembler::DoubleCondition>(cond);
1433 }
1435 private:
1436 friend class LinkBuffer;
1437 friend class RepatchBuffer;
1439 static void linkCall(void* code, Call call, FunctionPtr function)
1440 {
1441 SparcAssembler::linkCall(code, call.m_jmp, function.value());
1442 }
1444 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
1445 {
1446 SparcAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1447 }
1449 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
1450 {
1451 SparcAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1452 }
1454 };
1456 }
1459 #endif // ENABLE(ASSEMBLER) && CPU(SPARC)
1461 #endif /* assembler_assembler_MacroAssemblerSparc_h */