1/*
2 * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef MacroAssemblerX86_64_h
27#define MacroAssemblerX86_64_h
28
29#if ENABLE(ASSEMBLER) && CPU(X86_64)
30
31#include "MacroAssemblerX86Common.h"
32
33#define REPTACH_OFFSET_CALL_R11 3
34
35namespace JSC {
36
37class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
38public:
39 static const Scale ScalePtr = TimesEight;
40 static const int PointerSize = 8;
41
42 using MacroAssemblerX86Common::add32;
43 using MacroAssemblerX86Common::and32;
44 using MacroAssemblerX86Common::branchAdd32;
45 using MacroAssemblerX86Common::or32;
46 using MacroAssemblerX86Common::sub32;
47 using MacroAssemblerX86Common::load32;
48 using MacroAssemblerX86Common::store32;
49 using MacroAssemblerX86Common::store8;
50 using MacroAssemblerX86Common::call;
51 using MacroAssemblerX86Common::jump;
52 using MacroAssemblerX86Common::addDouble;
53 using MacroAssemblerX86Common::loadDouble;
54 using MacroAssemblerX86Common::convertInt32ToDouble;
55
56 void add32(TrustedImm32 imm, AbsoluteAddress address)
57 {
58 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
59 add32(imm, address: Address(scratchRegister));
60 }
61
62 void and32(TrustedImm32 imm, AbsoluteAddress address)
63 {
64 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
65 and32(imm, address: Address(scratchRegister));
66 }
67
68 void add32(AbsoluteAddress address, RegisterID dest)
69 {
70 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
71 add32(src: Address(scratchRegister), dest);
72 }
73
74 void or32(TrustedImm32 imm, AbsoluteAddress address)
75 {
76 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
77 or32(imm, address: Address(scratchRegister));
78 }
79
80 void or32(RegisterID reg, AbsoluteAddress address)
81 {
82 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
83 or32(src: reg, dest: Address(scratchRegister));
84 }
85
86 void sub32(TrustedImm32 imm, AbsoluteAddress address)
87 {
88 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
89 sub32(imm, address: Address(scratchRegister));
90 }
91
92 void load16(ExtendedAddress address, RegisterID dest)
93 {
94 TrustedImmPtr addr(reinterpret_cast<void*>(address.offset));
95 MacroAssemblerX86Common::move(imm: addr, dest: scratchRegister);
96 MacroAssemblerX86Common::load16(address: BaseIndex(scratchRegister, address.base, TimesTwo), dest);
97 }
98
99 void load16(BaseIndex address, RegisterID dest)
100 {
101 MacroAssemblerX86Common::load16(address, dest);
102 }
103
104 void load16(Address address, RegisterID dest)
105 {
106 MacroAssemblerX86Common::load16(address, dest);
107 }
108
109 void load32(const void* address, RegisterID dest)
110 {
111 if (dest == X86Registers::eax)
112 m_assembler.movl_mEAX(addr: address);
113 else {
114 move(imm: TrustedImmPtr(address), dest);
115 load32(address: dest, dest);
116 }
117 }
118
119 void addDouble(AbsoluteAddress address, FPRegisterID dest)
120 {
121 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
122 m_assembler.addsd_mr(offset: 0, base: scratchRegister, dst: dest);
123 }
124
125 void convertInt32ToDouble(TrustedImm32 imm, FPRegisterID dest)
126 {
127 move(imm, dest: scratchRegister);
128 m_assembler.cvtsi2sd_rr(src: scratchRegister, dst: dest);
129 }
130
131 void convertUInt32ToDouble(RegisterID src, FPRegisterID dest, RegisterID /*scratch*/)
132 {
133 zeroExtend32ToPtr(src, dest: src);
134 m_assembler.cvtsiq2sd_rr(src, dst: dest);
135 }
136
137 void store32(TrustedImm32 imm, void* address)
138 {
139 move(imm: TrustedImmPtr(address), dest: scratchRegister);
140 store32(imm, address: scratchRegister);
141 }
142
143 void store8(TrustedImm32 imm, void* address)
144 {
145 move(imm: TrustedImmPtr(address), dest: scratchRegister);
146 store8(imm, address: Address(scratchRegister));
147 }
148
149 Call call()
150 {
151 DataLabelPtr label = moveWithPatch(initialValue: TrustedImmPtr(0), dest: scratchRegister);
152 Call result = Call(m_assembler.call(dst: scratchRegister), Call::Linkable);
153 ASSERT_UNUSED(label, differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11);
154 return result;
155 }
156
157 void callToRetrieveIP()
158 {
159 m_assembler.call();
160 }
161
162 // Address is a memory location containing the address to jump to
163 void jump(AbsoluteAddress address)
164 {
165 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
166 jump(address: Address(scratchRegister));
167 }
168
169 Call tailRecursiveCall()
170 {
171 DataLabelPtr label = moveWithPatch(initialValue: TrustedImmPtr(0), dest: scratchRegister);
172 Jump newJump = Jump(m_assembler.jmp_r(dst: scratchRegister));
173 ASSERT_UNUSED(label, differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
174 return Call::fromTailJump(jump: newJump);
175 }
176
177 Call makeTailRecursiveCall(Jump oldJump)
178 {
179 oldJump.link(masm: this);
180 DataLabelPtr label = moveWithPatch(initialValue: TrustedImmPtr(0), dest: scratchRegister);
181 Jump newJump = Jump(m_assembler.jmp_r(dst: scratchRegister));
182 ASSERT_UNUSED(label, differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
183 return Call::fromTailJump(jump: newJump);
184 }
185
186 Jump branchAdd32(ResultCondition cond, TrustedImm32 src, AbsoluteAddress dest)
187 {
188 move(imm: TrustedImmPtr(dest.m_ptr), dest: scratchRegister);
189 add32(imm: src, address: Address(scratchRegister));
190 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
191 }
192
193 void add64(RegisterID src, RegisterID dest)
194 {
195 m_assembler.addq_rr(src, dst: dest);
196 }
197
198 void add64(Address src, RegisterID dest)
199 {
200 m_assembler.addq_mr(offset: src.offset, base: src.base, dst: dest);
201 }
202
203 void add64(AbsoluteAddress src, RegisterID dest)
204 {
205 move(imm: TrustedImmPtr(src.m_ptr), dest: scratchRegister);
206 add64(src: Address(scratchRegister), dest);
207 }
208
209 void add64(TrustedImm32 imm, RegisterID srcDest)
210 {
211 m_assembler.addq_ir(imm: imm.m_value, dst: srcDest);
212 }
213
214 void add64(TrustedImm64 imm, RegisterID dest)
215 {
216 move(imm, dest: scratchRegister);
217 add64(src: scratchRegister, dest);
218 }
219
220 void add64(TrustedImm32 imm, RegisterID src, RegisterID dest)
221 {
222 m_assembler.leaq_mr(offset: imm.m_value, base: src, dst: dest);
223 }
224
225 void add64(TrustedImm32 imm, Address address)
226 {
227 m_assembler.addq_im(imm: imm.m_value, offset: address.offset, base: address.base);
228 }
229
230 void add64(TrustedImm32 imm, AbsoluteAddress address)
231 {
232 move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
233 add64(imm, address: Address(scratchRegister));
234 }
235
236 void x86Lea64(BaseIndex index, RegisterID dest)
237 {
238 if (!index.scale && !index.offset) {
239 if (index.base == dest) {
240 add64(src: index.index, dest);
241 return;
242 }
243 if (index.index == dest) {
244 add64(src: index.base, dest);
245 return;
246 }
247 }
248 m_assembler.leaq_mr(offset: index.offset, base: index.base, index: index.index, scale: index.scale, dst: dest);
249 }
250
251 void getEffectiveAddress(BaseIndex address, RegisterID dest)
252 {
253 return x86Lea64(index: address, dest);
254 }
255
256 void and64(RegisterID src, RegisterID dest)
257 {
258 m_assembler.andq_rr(src, dst: dest);
259 }
260
261 void and64(TrustedImm32 imm, RegisterID srcDest)
262 {
263 m_assembler.andq_ir(imm: imm.m_value, dst: srcDest);
264 }
265
266 void neg64(RegisterID dest)
267 {
268 m_assembler.negq_r(dst: dest);
269 }
270
271 void or64(RegisterID src, RegisterID dest)
272 {
273 m_assembler.orq_rr(src, dst: dest);
274 }
275
276 void or64(TrustedImm64 imm, RegisterID dest)
277 {
278 move(imm, dest: scratchRegister);
279 or64(src: scratchRegister, dest);
280 }
281
282 void or64(TrustedImm32 imm, RegisterID dest)
283 {
284 m_assembler.orq_ir(imm: imm.m_value, dst: dest);
285 }
286
287 void or64(RegisterID op1, RegisterID op2, RegisterID dest)
288 {
289 if (op1 == op2)
290 move(src: op1, dest);
291 else if (op1 == dest)
292 or64(src: op2, dest);
293 else {
294 move(src: op2, dest);
295 or64(src: op1, dest);
296 }
297 }
298
299 void or64(TrustedImm32 imm, RegisterID src, RegisterID dest)
300 {
301 move(src, dest);
302 or64(imm, dest);
303 }
304
305 void or64(TrustedImm64 imm, RegisterID src, RegisterID dest)
306 {
307 move(src, dest);
308 or64(imm, dest);
309 }
310
311 void rotateRight64(TrustedImm32 imm, RegisterID srcDst)
312 {
313 m_assembler.rorq_i8r(imm: imm.m_value, dst: srcDst);
314 }
315
316 void sub64(RegisterID src, RegisterID dest)
317 {
318 m_assembler.subq_rr(src, dst: dest);
319 }
320
321 void sub64(TrustedImm32 imm, RegisterID dest)
322 {
323 m_assembler.subq_ir(imm: imm.m_value, dst: dest);
324 }
325
326 void sub64(TrustedImm64 imm, RegisterID dest)
327 {
328 move(imm, dest: scratchRegister);
329 sub64(src: scratchRegister, dest);
330 }
331
332 void xor64(RegisterID src, RegisterID dest)
333 {
334 m_assembler.xorq_rr(src, dst: dest);
335 }
336
337 void xor64(RegisterID src, Address dest)
338 {
339 m_assembler.xorq_rm(src, offset: dest.offset, base: dest.base);
340 }
341
342 void xor64(TrustedImm32 imm, RegisterID srcDest)
343 {
344 m_assembler.xorq_ir(imm: imm.m_value, dst: srcDest);
345 }
346
347 void lshift64(TrustedImm32 imm, RegisterID dest)
348 {
349 m_assembler.shlq_i8r(imm: imm.m_value, dst: dest);
350 }
351
352 void lshift64(RegisterID src, RegisterID dest)
353 {
354 if (src == X86Registers::ecx)
355 m_assembler.shlq_CLr(dst: dest);
356 else {
357 ASSERT(src != dest);
358
359 // Can only shift by ecx, so we do some swapping if we see anything else.
360 swap(reg1: src, reg2: X86Registers::ecx);
361 m_assembler.shlq_CLr(dst: dest == X86Registers::ecx ? src : dest);
362 swap(reg1: src, reg2: X86Registers::ecx);
363 }
364 }
365
366 void rshift64(TrustedImm32 imm, RegisterID dest)
367 {
368 m_assembler.sarq_i8r(imm: imm.m_value, dst: dest);
369 }
370
371 void rshift64(RegisterID src, RegisterID dest)
372 {
373 if (src == X86Registers::ecx)
374 m_assembler.sarq_CLr(dst: dest);
375 else {
376 ASSERT(src != dest);
377
378 // Can only shift by ecx, so we do some swapping if we see anything else.
379 swap(reg1: src, reg2: X86Registers::ecx);
380 m_assembler.sarq_CLr(dst: dest == X86Registers::ecx ? src : dest);
381 swap(reg1: src, reg2: X86Registers::ecx);
382 }
383 }
384
385 void urshift64(RegisterID src, TrustedImm32 imm, RegisterID dest)
386 {
387 if (src != dest)
388 move(src, dest);
389 urshift64(imm, dest);
390 }
391
392 void urshift64(TrustedImm32 imm, RegisterID dest)
393 {
394 m_assembler.shrq_i8r(imm: imm.m_value, dst: dest);
395 }
396
397 void urshift64(RegisterID src, RegisterID dest)
398 {
399 if (src == X86Registers::ecx)
400 m_assembler.shrq_CLr(dst: dest);
401 else {
402 ASSERT(src != dest);
403
404 // Can only shift by ecx, so we do some swapping if we see anything else.
405 swap(reg1: src, reg2: X86Registers::ecx);
406 m_assembler.shrq_CLr(dst: dest == X86Registers::ecx ? src : dest);
407 swap(reg1: src, reg2: X86Registers::ecx);
408 }
409 }
410
411 void load64(ImplicitAddress address, RegisterID dest)
412 {
413 m_assembler.movq_mr(offset: address.offset, base: address.base, dst: dest);
414 }
415
416 void load64(BaseIndex address, RegisterID dest)
417 {
418 m_assembler.movq_mr(offset: address.offset, base: address.base, index: address.index, scale: address.scale, dst: dest);
419 }
420
421 void load64(const void* address, RegisterID dest)
422 {
423 if (dest == X86Registers::eax)
424 m_assembler.movq_mEAX(addr: address);
425 else {
426 move(imm: TrustedImmPtr(address), dest);
427 load64(address: dest, dest);
428 }
429 }
430
431 DataLabel32 load64WithAddressOffsetPatch(Address address, RegisterID dest)
432 {
433 padBeforePatch();
434 m_assembler.movq_mr_disp32(offset: address.offset, base: address.base, dst: dest);
435 return DataLabel32(this);
436 }
437
438 DataLabelCompact load64WithCompactAddressOffsetPatch(Address address, RegisterID dest)
439 {
440 padBeforePatch();
441 m_assembler.movq_mr_disp8(offset: address.offset, base: address.base, dst: dest);
442 return DataLabelCompact(this);
443 }
444
445 void store64(RegisterID src, ImplicitAddress address)
446 {
447 m_assembler.movq_rm(src, offset: address.offset, base: address.base);
448 }
449
450 void store64(RegisterID src, BaseIndex address)
451 {
452 m_assembler.movq_rm(src, offset: address.offset, base: address.base, index: address.index, scale: address.scale);
453 }
454
455 void store64(RegisterID src, void* address)
456 {
457 if (src == X86Registers::eax)
458 m_assembler.movq_EAXm(addr: address);
459 else {
460 move(imm: TrustedImmPtr(address), dest: scratchRegister);
461 store64(src, address: scratchRegister);
462 }
463 }
464
465 void store64(TrustedImm64 imm, ImplicitAddress address)
466 {
467 move(imm, dest: scratchRegister);
468 store64(src: scratchRegister, address);
469 }
470
471 void store64(TrustedImm64 imm, BaseIndex address)
472 {
473 move(imm, dest: scratchRegister);
474 m_assembler.movq_rm(src: scratchRegister, offset: address.offset, base: address.base, index: address.index, scale: address.scale);
475 }
476
477 DataLabel32 store64WithAddressOffsetPatch(RegisterID src, Address address)
478 {
479 padBeforePatch();
480 m_assembler.movq_rm_disp32(src, offset: address.offset, base: address.base);
481 return DataLabel32(this);
482 }
483
484 void move64ToDouble(RegisterID src, FPRegisterID dest)
485 {
486 m_assembler.movq_rr(src, dst: dest);
487 }
488
489 void moveDoubleTo64(FPRegisterID src, RegisterID dest)
490 {
491 m_assembler.movq_rr(src, dst: dest);
492 }
493
494 void compare64(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
495 {
496 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
497 m_assembler.testq_rr(src: left, dst: left);
498 else
499 m_assembler.cmpq_ir(imm: right.m_value, dst: left);
500 m_assembler.setCC_r(cond: x86Condition(cond), dst: dest);
501 m_assembler.movzbl_rr(src: dest, dst: dest);
502 }
503
504 void compare64(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
505 {
506 m_assembler.cmpq_rr(src: right, dst: left);
507 m_assembler.setCC_r(cond: x86Condition(cond), dst: dest);
508 m_assembler.movzbl_rr(src: dest, dst: dest);
509 }
510
511 Jump branch64(RelationalCondition cond, RegisterID left, RegisterID right)
512 {
513 m_assembler.cmpq_rr(src: right, dst: left);
514 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
515 }
516
517 Jump branch64(RelationalCondition cond, RegisterID left, TrustedImm64 right)
518 {
519 if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) {
520 m_assembler.testq_rr(src: left, dst: left);
521 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
522 }
523 move(imm: right, dest: scratchRegister);
524 return branch64(cond, left, right: scratchRegister);
525 }
526
527 Jump branch64(RelationalCondition cond, RegisterID left, Address right)
528 {
529 m_assembler.cmpq_mr(offset: right.offset, base: right.base, src: left);
530 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
531 }
532
533 Jump branch64(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
534 {
535 move(imm: TrustedImmPtr(left.m_ptr), dest: scratchRegister);
536 return branch64(cond, left: Address(scratchRegister), right);
537 }
538
539 Jump branch64(RelationalCondition cond, Address left, RegisterID right)
540 {
541 m_assembler.cmpq_rm(src: right, offset: left.offset, base: left.base);
542 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
543 }
544
545 Jump branch64(RelationalCondition cond, Address left, TrustedImm64 right)
546 {
547 move(imm: right, dest: scratchRegister);
548 return branch64(cond, left, right: scratchRegister);
549 }
550
551 Jump branchTest64(ResultCondition cond, RegisterID reg, RegisterID mask)
552 {
553 m_assembler.testq_rr(src: reg, dst: mask);
554 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
555 }
556
557 Jump branchTest64(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
558 {
559 // if we are only interested in the low seven bits, this can be tested with a testb
560 if (mask.m_value == -1)
561 m_assembler.testq_rr(src: reg, dst: reg);
562 else if ((mask.m_value & ~0x7f) == 0)
563 m_assembler.testb_i8r(imm: mask.m_value, dst: reg);
564 else
565 m_assembler.testq_i32r(imm: mask.m_value, dst: reg);
566 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
567 }
568
569 void test64(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
570 {
571 if (mask.m_value == -1)
572 m_assembler.testq_rr(src: reg, dst: reg);
573 else if ((mask.m_value & ~0x7f) == 0)
574 m_assembler.testb_i8r(imm: mask.m_value, dst: reg);
575 else
576 m_assembler.testq_i32r(imm: mask.m_value, dst: reg);
577 set32(cond: x86Condition(cond), dest);
578 }
579
580 void test64(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest)
581 {
582 m_assembler.testq_rr(src: reg, dst: mask);
583 set32(cond: x86Condition(cond), dest);
584 }
585
586 Jump branchTest64(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
587 {
588 load64(address: address.m_ptr, dest: scratchRegister);
589 return branchTest64(cond, reg: scratchRegister, mask);
590 }
591
592 Jump branchTest64(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
593 {
594 if (mask.m_value == -1)
595 m_assembler.cmpq_im(imm: 0, offset: address.offset, base: address.base);
596 else
597 m_assembler.testq_i32m(imm: mask.m_value, offset: address.offset, base: address.base);
598 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
599 }
600
601 Jump branchTest64(ResultCondition cond, Address address, RegisterID reg)
602 {
603 m_assembler.testq_rm(src: reg, offset: address.offset, base: address.base);
604 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
605 }
606
607 Jump branchTest64(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
608 {
609 if (mask.m_value == -1)
610 m_assembler.cmpq_im(imm: 0, offset: address.offset, base: address.base, index: address.index, scale: address.scale);
611 else
612 m_assembler.testq_i32m(imm: mask.m_value, offset: address.offset, base: address.base, index: address.index, scale: address.scale);
613 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
614 }
615
616
617 Jump branchAdd64(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
618 {
619 add64(imm, srcDest: dest);
620 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
621 }
622
623 Jump branchAdd64(ResultCondition cond, RegisterID src, RegisterID dest)
624 {
625 add64(src, dest);
626 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
627 }
628
629 Jump branchSub64(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
630 {
631 sub64(imm, dest);
632 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
633 }
634
635 Jump branchSub64(ResultCondition cond, RegisterID src, RegisterID dest)
636 {
637 sub64(src, dest);
638 return Jump(m_assembler.jCC(cond: x86Condition(cond)));
639 }
640
641 Jump branchSub64(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
642 {
643 move(src: src1, dest);
644 return branchSub64(cond, imm: src2, dest);
645 }
646
647 ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
648 {
649 ConvertibleLoadLabel result = ConvertibleLoadLabel(this);
650 m_assembler.movq_mr(offset: address.offset, base: address.base, dst: dest);
651 return result;
652 }
653
654 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
655 {
656 padBeforePatch();
657 m_assembler.movq_i64r(imm: initialValue.asIntptr(), dst: dest);
658 return DataLabelPtr(this);
659 }
660
661 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
662 {
663 dataLabel = moveWithPatch(initialValue: initialRightValue, dest: scratchRegister);
664 return branch64(cond, left, right: scratchRegister);
665 }
666
667 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
668 {
669 dataLabel = moveWithPatch(initialValue: initialRightValue, dest: scratchRegister);
670 return branch64(cond, left, right: scratchRegister);
671 }
672
673 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
674 {
675 DataLabelPtr label = moveWithPatch(initialValue, dest: scratchRegister);
676 store64(src: scratchRegister, address);
677 return label;
678 }
679
680 using MacroAssemblerX86Common::branchTest8;
681 Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
682 {
683 TrustedImmPtr addr(reinterpret_cast<void*>(address.offset));
684 MacroAssemblerX86Common::move(imm: addr, dest: scratchRegister);
685 return MacroAssemblerX86Common::branchTest8(cond, address: BaseIndex(scratchRegister, address.base, TimesOne), mask);
686 }
687
688 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
689 {
690 MacroAssemblerX86Common::move(imm: TrustedImmPtr(address.m_ptr), dest: scratchRegister);
691 return MacroAssemblerX86Common::branchTest8(cond, address: Address(scratchRegister), mask);
692 }
693
694 static bool supportsFloatingPoint() { return true; }
695 // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
696 static bool supportsFloatingPointTruncate() { return true; }
697 static bool supportsFloatingPointSqrt() { return true; }
698 static bool supportsFloatingPointAbs() { return true; }
699
700 static FunctionPtr readCallTarget(CodeLocationCall call)
701 {
702 return FunctionPtr(X86Assembler::readPointer(where: call.dataLabelPtrAtOffset(offset: -REPTACH_OFFSET_CALL_R11).dataLocation()));
703 }
704
705 static RegisterID scratchRegisterForBlinding() { return scratchRegister; }
706
707 static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; }
708
709 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
710 {
711 const int rexBytes = 1;
712 const int opcodeBytes = 1;
713 const int immediateBytes = 8;
714 const int totalBytes = rexBytes + opcodeBytes + immediateBytes;
715 ASSERT(totalBytes >= maxJumpReplacementSize());
716 return label.labelAtOffset(offset: -totalBytes);
717 }
718
719 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label)
720 {
721 return startOfBranchPtrWithPatchOnRegister(label);
722 }
723
724 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue)
725 {
726 X86Assembler::revertJumpTo_movq_i64r(instructionStart: instructionStart.executableAddress(), imm: reinterpret_cast<intptr_t>(initialValue), dst: scratchRegister);
727 }
728
729 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue)
730 {
731 X86Assembler::revertJumpTo_movq_i64r(instructionStart: instructionStart.executableAddress(), imm: reinterpret_cast<intptr_t>(initialValue), dst: scratchRegister);
732 }
733
734private:
735 template <typename, template <typename> class> friend class LinkBufferBase;
736
737 static void linkCall(void* code, Call call, FunctionPtr function)
738 {
739 if (!call.isFlagSet(flag: Call::Near))
740 X86Assembler::linkPointer(code, where: call.m_label.labelAtOffset(offset: -REPTACH_OFFSET_CALL_R11), value: function.value());
741 else
742 X86Assembler::linkCall(code, from: call.m_label, to: function.value());
743 }
744
745 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
746 {
747 X86Assembler::repatchPointer(where: call.dataLabelPtrAtOffset(offset: -REPTACH_OFFSET_CALL_R11).dataLocation(), value: destination.executableAddress());
748 }
749
750 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
751 {
752 X86Assembler::repatchPointer(where: call.dataLabelPtrAtOffset(offset: -REPTACH_OFFSET_CALL_R11).dataLocation(), value: destination.executableAddress());
753 }
754
755};
756
757} // namespace JSC
758
759#endif // ENABLE(ASSEMBLER)
760
761#endif // MacroAssemblerX86_64_h
762

source code of qtdeclarative/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h