Merge "Save and re-bind previously bounded texture when using cairo_gl_surface_set_bi...
[framework/web/webkit-efl.git] / Source / JavaScriptCore / assembler / MacroAssemblerX86_64.h
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
35 namespace JSC {
36
37 class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
38 public:
39     static const Scale ScalePtr = TimesEight;
40
41     using MacroAssemblerX86Common::add32;
42     using MacroAssemblerX86Common::and32;
43     using MacroAssemblerX86Common::branchAdd32;
44     using MacroAssemblerX86Common::or32;
45     using MacroAssemblerX86Common::sub32;
46     using MacroAssemblerX86Common::load32;
47     using MacroAssemblerX86Common::store32;
48     using MacroAssemblerX86Common::call;
49     using MacroAssemblerX86Common::jump;
50     using MacroAssemblerX86Common::addDouble;
51     using MacroAssemblerX86Common::loadDouble;
52     using MacroAssemblerX86Common::convertInt32ToDouble;
53
54     void add32(TrustedImm32 imm, AbsoluteAddress address)
55     {
56         move(TrustedImmPtr(address.m_ptr), scratchRegister);
57         add32(imm, Address(scratchRegister));
58     }
59     
60     void and32(TrustedImm32 imm, AbsoluteAddress address)
61     {
62         move(TrustedImmPtr(address.m_ptr), scratchRegister);
63         and32(imm, Address(scratchRegister));
64     }
65     
66     void add32(AbsoluteAddress address, RegisterID dest)
67     {
68         move(TrustedImmPtr(address.m_ptr), scratchRegister);
69         add32(Address(scratchRegister), dest);
70     }
71     
72     void or32(TrustedImm32 imm, AbsoluteAddress address)
73     {
74         move(TrustedImmPtr(address.m_ptr), scratchRegister);
75         or32(imm, Address(scratchRegister));
76     }
77
78     void sub32(TrustedImm32 imm, AbsoluteAddress address)
79     {
80         move(TrustedImmPtr(address.m_ptr), scratchRegister);
81         sub32(imm, Address(scratchRegister));
82     }
83
84     void load32(const void* address, RegisterID dest)
85     {
86         if (dest == X86Registers::eax)
87             m_assembler.movl_mEAX(address);
88         else {
89             move(TrustedImmPtr(address), dest);
90             load32(dest, dest);
91         }
92     }
93
94     void addDouble(AbsoluteAddress address, FPRegisterID dest)
95     {
96         move(TrustedImmPtr(address.m_ptr), scratchRegister);
97         m_assembler.addsd_mr(0, scratchRegister, dest);
98     }
99
100     void convertInt32ToDouble(TrustedImm32 imm, FPRegisterID dest)
101     {
102         move(imm, scratchRegister);
103         m_assembler.cvtsi2sd_rr(scratchRegister, dest);
104     }
105
106     void store32(TrustedImm32 imm, void* address)
107     {
108         move(TrustedImmPtr(address), scratchRegister);
109         store32(imm, scratchRegister);
110     }
111
112     Call call()
113     {
114         DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
115         Call result = Call(m_assembler.call(scratchRegister), Call::Linkable);
116         ASSERT_UNUSED(label, differenceBetween(label, result) == REPTACH_OFFSET_CALL_R11);
117         return result;
118     }
119
120     // Address is a memory location containing the address to jump to
121     void jump(AbsoluteAddress address)
122     {
123         move(TrustedImmPtr(address.m_ptr), scratchRegister);
124         jump(Address(scratchRegister));
125     }
126
127     Call tailRecursiveCall()
128     {
129         DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
130         Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
131         ASSERT_UNUSED(label, differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
132         return Call::fromTailJump(newJump);
133     }
134
135     Call makeTailRecursiveCall(Jump oldJump)
136     {
137         oldJump.link(this);
138         DataLabelPtr label = moveWithPatch(TrustedImmPtr(0), scratchRegister);
139         Jump newJump = Jump(m_assembler.jmp_r(scratchRegister));
140         ASSERT_UNUSED(label, differenceBetween(label, newJump) == REPTACH_OFFSET_CALL_R11);
141         return Call::fromTailJump(newJump);
142     }
143
144
145     void addPtr(RegisterID src, RegisterID dest)
146     {
147         m_assembler.addq_rr(src, dest);
148     }
149     
150     void addPtr(Address src, RegisterID dest)
151     {
152         m_assembler.addq_mr(src.offset, src.base, dest);
153     }
154
155     void addPtr(AbsoluteAddress src, RegisterID dest)
156     {
157         move(TrustedImmPtr(src.m_ptr), scratchRegister);
158         addPtr(Address(scratchRegister), dest);
159     }
160
161     void addPtr(TrustedImm32 imm, RegisterID srcDest)
162     {
163         m_assembler.addq_ir(imm.m_value, srcDest);
164     }
165
166     void addPtr(TrustedImmPtr imm, RegisterID dest)
167     {
168         move(imm, scratchRegister);
169         m_assembler.addq_rr(scratchRegister, dest);
170     }
171
172     void addPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
173     {
174         m_assembler.leaq_mr(imm.m_value, src, dest);
175     }
176
177     void addPtr(TrustedImm32 imm, Address address)
178     {
179         m_assembler.addq_im(imm.m_value, address.offset, address.base);
180     }
181
182     void addPtr(TrustedImm32 imm, AbsoluteAddress address)
183     {
184         move(TrustedImmPtr(address.m_ptr), scratchRegister);
185         addPtr(imm, Address(scratchRegister));
186     }
187
188     void add64(TrustedImm32 imm, AbsoluteAddress address)
189     {
190         addPtr(imm, address);
191     }
192
193     void andPtr(RegisterID src, RegisterID dest)
194     {
195         m_assembler.andq_rr(src, dest);
196     }
197
198     void andPtr(TrustedImm32 imm, RegisterID srcDest)
199     {
200         m_assembler.andq_ir(imm.m_value, srcDest);
201     }
202     
203     void negPtr(RegisterID dest)
204     {
205         m_assembler.negq_r(dest);
206     }
207
208     void orPtr(RegisterID src, RegisterID dest)
209     {
210         m_assembler.orq_rr(src, dest);
211     }
212
213     void orPtr(TrustedImmPtr imm, RegisterID dest)
214     {
215         move(imm, scratchRegister);
216         m_assembler.orq_rr(scratchRegister, dest);
217     }
218
219     void orPtr(TrustedImm32 imm, RegisterID dest)
220     {
221         m_assembler.orq_ir(imm.m_value, dest);
222     }
223
224     void orPtr(RegisterID op1, RegisterID op2, RegisterID dest)
225     {
226         if (op1 == op2)
227             move(op1, dest);
228         else if (op1 == dest)
229             orPtr(op2, dest);
230         else {
231             move(op2, dest);
232             orPtr(op1, dest);
233         }
234     }
235
236     void orPtr(TrustedImm32 imm, RegisterID src, RegisterID dest)
237     {
238         move(src, dest);
239         orPtr(imm, dest);
240     }
241     
242     void rotateRightPtr(TrustedImm32 imm, RegisterID srcDst)
243     {
244         m_assembler.rorq_i8r(imm.m_value, srcDst);
245     }
246
247     void subPtr(RegisterID src, RegisterID dest)
248     {
249         m_assembler.subq_rr(src, dest);
250     }
251     
252     void subPtr(TrustedImm32 imm, RegisterID dest)
253     {
254         m_assembler.subq_ir(imm.m_value, dest);
255     }
256     
257     void subPtr(TrustedImmPtr imm, RegisterID dest)
258     {
259         move(imm, scratchRegister);
260         m_assembler.subq_rr(scratchRegister, dest);
261     }
262
263     void xorPtr(RegisterID src, RegisterID dest)
264     {
265         m_assembler.xorq_rr(src, dest);
266     }
267     
268     void xorPtr(RegisterID src, Address dest)
269     {
270         m_assembler.xorq_rm(src, dest.offset, dest.base);
271     }
272
273     void xorPtr(TrustedImm32 imm, RegisterID srcDest)
274     {
275         m_assembler.xorq_ir(imm.m_value, srcDest);
276     }
277
278     void loadPtr(ImplicitAddress address, RegisterID dest)
279     {
280         m_assembler.movq_mr(address.offset, address.base, dest);
281     }
282
283     ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
284     {
285         ConvertibleLoadLabel result = ConvertibleLoadLabel(this);
286         m_assembler.movq_mr(address.offset, address.base, dest);
287         return result;
288     }
289
290     void loadPtr(BaseIndex address, RegisterID dest)
291     {
292         m_assembler.movq_mr(address.offset, address.base, address.index, address.scale, dest);
293     }
294
295     void loadPtr(const void* address, RegisterID dest)
296     {
297         if (dest == X86Registers::eax)
298             m_assembler.movq_mEAX(address);
299         else {
300             move(TrustedImmPtr(address), dest);
301             loadPtr(dest, dest);
302         }
303     }
304
305     DataLabel32 loadPtrWithAddressOffsetPatch(Address address, RegisterID dest)
306     {
307         m_assembler.movq_mr_disp32(address.offset, address.base, dest);
308         return DataLabel32(this);
309     }
310     
311     DataLabelCompact loadPtrWithCompactAddressOffsetPatch(Address address, RegisterID dest)
312     {
313         m_assembler.movq_mr_disp8(address.offset, address.base, dest);
314         return DataLabelCompact(this);
315     }
316
317     void storePtr(RegisterID src, ImplicitAddress address)
318     {
319         m_assembler.movq_rm(src, address.offset, address.base);
320     }
321
322     void storePtr(RegisterID src, BaseIndex address)
323     {
324         m_assembler.movq_rm(src, address.offset, address.base, address.index, address.scale);
325     }
326     
327     void storePtr(RegisterID src, void* address)
328     {
329         if (src == X86Registers::eax)
330             m_assembler.movq_EAXm(address);
331         else {
332             move(TrustedImmPtr(address), scratchRegister);
333             storePtr(src, scratchRegister);
334         }
335     }
336
337     void storePtr(TrustedImmPtr imm, ImplicitAddress address)
338     {
339         move(imm, scratchRegister);
340         storePtr(scratchRegister, address);
341     }
342
343     void storePtr(TrustedImmPtr imm, BaseIndex address)
344     {
345         move(imm, scratchRegister);
346         m_assembler.movq_rm(scratchRegister, address.offset, address.base, address.index, address.scale);
347     }
348     
349     DataLabel32 storePtrWithAddressOffsetPatch(RegisterID src, Address address)
350     {
351         m_assembler.movq_rm_disp32(src, address.offset, address.base);
352         return DataLabel32(this);
353     }
354
355     void movePtrToDouble(RegisterID src, FPRegisterID dest)
356     {
357         m_assembler.movq_rr(src, dest);
358     }
359
360     void moveDoubleToPtr(FPRegisterID src, RegisterID dest)
361     {
362         m_assembler.movq_rr(src, dest);
363     }
364
365     void comparePtr(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest)
366     {
367         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
368             m_assembler.testq_rr(left, left);
369         else
370             m_assembler.cmpq_ir(right.m_value, left);
371         m_assembler.setCC_r(x86Condition(cond), dest);
372         m_assembler.movzbl_rr(dest, dest);
373     }
374     
375     void comparePtr(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest)
376     {
377         m_assembler.cmpq_rr(right, left);
378         m_assembler.setCC_r(x86Condition(cond), dest);
379         m_assembler.movzbl_rr(dest, dest);
380     }
381     
382     Jump branchAdd32(ResultCondition cond, TrustedImm32 src, AbsoluteAddress dest)
383     {
384         move(TrustedImmPtr(dest.m_ptr), scratchRegister);
385         add32(src, Address(scratchRegister));
386         return Jump(m_assembler.jCC(x86Condition(cond)));
387     }
388
389     Jump branchPtr(RelationalCondition cond, RegisterID left, RegisterID right)
390     {
391         m_assembler.cmpq_rr(right, left);
392         return Jump(m_assembler.jCC(x86Condition(cond)));
393     }
394
395     Jump branchPtr(RelationalCondition cond, RegisterID left, TrustedImmPtr right)
396     {
397         if (((cond == Equal) || (cond == NotEqual)) && !right.m_value) {
398             m_assembler.testq_rr(left, left);
399             return Jump(m_assembler.jCC(x86Condition(cond)));
400         }
401         move(right, scratchRegister);
402         return branchPtr(cond, left, scratchRegister);
403     }
404
405     Jump branchPtr(RelationalCondition cond, RegisterID left, Address right)
406     {
407         m_assembler.cmpq_mr(right.offset, right.base, left);
408         return Jump(m_assembler.jCC(x86Condition(cond)));
409     }
410
411     Jump branchPtr(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
412     {
413         move(TrustedImmPtr(left.m_ptr), scratchRegister);
414         return branchPtr(cond, Address(scratchRegister), right);
415     }
416
417     Jump branchPtr(RelationalCondition cond, Address left, RegisterID right)
418     {
419         m_assembler.cmpq_rm(right, left.offset, left.base);
420         return Jump(m_assembler.jCC(x86Condition(cond)));
421     }
422
423     Jump branchPtr(RelationalCondition cond, Address left, TrustedImmPtr right)
424     {
425         move(right, scratchRegister);
426         return branchPtr(cond, left, scratchRegister);
427     }
428
429     Jump branchTestPtr(ResultCondition cond, RegisterID reg, RegisterID mask)
430     {
431         m_assembler.testq_rr(reg, mask);
432         return Jump(m_assembler.jCC(x86Condition(cond)));
433     }
434     
435     Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
436     {
437         // if we are only interested in the low seven bits, this can be tested with a testb
438         if (mask.m_value == -1)
439             m_assembler.testq_rr(reg, reg);
440         else if ((mask.m_value & ~0x7f) == 0)
441             m_assembler.testb_i8r(mask.m_value, reg);
442         else
443             m_assembler.testq_i32r(mask.m_value, reg);
444         return Jump(m_assembler.jCC(x86Condition(cond)));
445     }
446
447     void testPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
448     {
449         if (mask.m_value == -1)
450             m_assembler.testq_rr(reg, reg);
451         else if ((mask.m_value & ~0x7f) == 0)
452             m_assembler.testb_i8r(mask.m_value, reg);
453         else
454             m_assembler.testq_i32r(mask.m_value, reg);
455         set32(x86Condition(cond), dest);
456     }
457
458     void testPtr(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest)
459     {
460         m_assembler.testq_rr(reg, mask);
461         set32(x86Condition(cond), dest);
462     }
463
464     Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
465     {
466         loadPtr(address.m_ptr, scratchRegister);
467         return branchTestPtr(cond, scratchRegister, mask);
468     }
469
470     Jump branchTestPtr(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
471     {
472         if (mask.m_value == -1)
473             m_assembler.cmpq_im(0, address.offset, address.base);
474         else
475             m_assembler.testq_i32m(mask.m_value, address.offset, address.base);
476         return Jump(m_assembler.jCC(x86Condition(cond)));
477     }
478
479     Jump branchTestPtr(ResultCondition cond, Address address, RegisterID reg)
480     {
481         m_assembler.testq_rm(reg, address.offset, address.base);
482         return Jump(m_assembler.jCC(x86Condition(cond)));
483     }
484
485     Jump branchTestPtr(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
486     {
487         if (mask.m_value == -1)
488             m_assembler.cmpq_im(0, address.offset, address.base, address.index, address.scale);
489         else
490             m_assembler.testq_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
491         return Jump(m_assembler.jCC(x86Condition(cond)));
492     }
493
494
495     Jump branchAddPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
496     {
497         addPtr(imm, dest);
498         return Jump(m_assembler.jCC(x86Condition(cond)));
499     }
500
501     Jump branchAddPtr(ResultCondition cond, RegisterID src, RegisterID dest)
502     {
503         addPtr(src, dest);
504         return Jump(m_assembler.jCC(x86Condition(cond)));
505     }
506
507     Jump branchSubPtr(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
508     {
509         subPtr(imm, dest);
510         return Jump(m_assembler.jCC(x86Condition(cond)));
511     }
512
513     Jump branchSubPtr(ResultCondition cond, RegisterID src1, TrustedImm32 src2, RegisterID dest)
514     {
515         move(src1, dest);
516         return branchSubPtr(cond, src2, dest);
517     }
518
519     DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
520     {
521         m_assembler.movq_i64r(initialValue.asIntptr(), dest);
522         return DataLabelPtr(this);
523     }
524
525     Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
526     {
527         dataLabel = moveWithPatch(initialRightValue, scratchRegister);
528         return branchPtr(cond, left, scratchRegister);
529     }
530
531     Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
532     {
533         dataLabel = moveWithPatch(initialRightValue, scratchRegister);
534         return branchPtr(cond, left, scratchRegister);
535     }
536
537     DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
538     {
539         DataLabelPtr label = moveWithPatch(initialValue, scratchRegister);
540         storePtr(scratchRegister, address);
541         return label;
542     }
543
544     using MacroAssemblerX86Common::branchTest8;
545     Jump branchTest8(ResultCondition cond, ExtendedAddress address, TrustedImm32 mask = TrustedImm32(-1))
546     {
547         TrustedImmPtr addr(reinterpret_cast<void*>(address.offset));
548         MacroAssemblerX86Common::move(addr, scratchRegister);
549         return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask);
550     }
551     
552     Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
553     {
554         MacroAssemblerX86Common::move(TrustedImmPtr(address.m_ptr), scratchRegister);
555         return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister), mask);
556     }
557
558     static bool supportsFloatingPoint() { return true; }
559     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
560     static bool supportsFloatingPointTruncate() { return true; }
561     static bool supportsFloatingPointSqrt() { return true; }
562     static bool supportsFloatingPointAbs() { return true; }
563     
564     static FunctionPtr readCallTarget(CodeLocationCall call)
565     {
566         return FunctionPtr(X86Assembler::readPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation()));
567     }
568
569     static RegisterID scratchRegisterForBlinding() { return scratchRegister; }
570
571 private:
572     friend class LinkBuffer;
573     friend class RepatchBuffer;
574
575     static void linkCall(void* code, Call call, FunctionPtr function)
576     {
577         if (!call.isFlagSet(Call::Near))
578             X86Assembler::linkPointer(code, call.m_label.labelAtOffset(-REPTACH_OFFSET_CALL_R11), function.value());
579         else
580             X86Assembler::linkCall(code, call.m_label, function.value());
581     }
582
583     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
584     {
585         X86Assembler::repatchPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation(), destination.executableAddress());
586     }
587
588     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
589     {
590         X86Assembler::repatchPointer(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11).dataLocation(), destination.executableAddress());
591     }
592
593 };
594
595 } // namespace JSC
596
597 #endif // ENABLE(ASSEMBLER)
598
599 #endif // MacroAssemblerX86_64_h