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