Imported Upstream version 1.0.0
[platform/upstream/js.git] / js / src / assembler / assembler / MacroAssemblerX86.h
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sw=4 et tw=79:
3  *
4  * ***** BEGIN LICENSE BLOCK *****
5  * Copyright (C) 2008 Apple Inc. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  * 
28  * ***** END LICENSE BLOCK ***** */
29
30 #ifndef MacroAssemblerX86_h
31 #define MacroAssemblerX86_h
32
33 #include "assembler/wtf/Platform.h"
34
35 #if ENABLE_ASSEMBLER && WTF_CPU_X86
36
37 #include "MacroAssemblerX86Common.h"
38
39 namespace JSC {
40
41 class MacroAssemblerX86 : public MacroAssemblerX86Common {
42 public:
43     MacroAssemblerX86()
44         : m_isSSE2Present(isSSE2Present())
45     {
46     }
47
48     static const Scale ScalePtr = TimesFour;
49     static const unsigned int TotalRegisters = 8;
50
51     using MacroAssemblerX86Common::add32;
52     using MacroAssemblerX86Common::and32;
53     using MacroAssemblerX86Common::sub32;
54     using MacroAssemblerX86Common::or32;
55     using MacroAssemblerX86Common::load32;
56     using MacroAssemblerX86Common::store32;
57     using MacroAssemblerX86Common::branch32;
58     using MacroAssemblerX86Common::call;
59     using MacroAssemblerX86Common::loadDouble;
60     using MacroAssemblerX86Common::storeDouble;
61     using MacroAssemblerX86Common::convertInt32ToDouble;
62
63     void add32(Imm32 imm, RegisterID src, RegisterID dest)
64     {
65         m_assembler.leal_mr(imm.m_value, src, dest);
66     }
67
68     void lea(Address address, RegisterID dest)
69     {
70         m_assembler.leal_mr(address.offset, address.base, dest);
71     }
72
73     void lea(BaseIndex address, RegisterID dest)
74     {
75         m_assembler.leal_mr(address.offset, address.base, address.index, address.scale, dest);
76     }
77
78     void add32(Imm32 imm, AbsoluteAddress address)
79     {
80         m_assembler.addl_im(imm.m_value, address.m_ptr);
81     }
82     
83     void addWithCarry32(Imm32 imm, AbsoluteAddress address)
84     {
85         m_assembler.adcl_im(imm.m_value, address.m_ptr);
86     }
87     
88     void and32(Imm32 imm, AbsoluteAddress address)
89     {
90         m_assembler.andl_im(imm.m_value, address.m_ptr);
91     }
92     
93     void or32(Imm32 imm, AbsoluteAddress address)
94     {
95         m_assembler.orl_im(imm.m_value, address.m_ptr);
96     }
97
98     void sub32(Imm32 imm, AbsoluteAddress address)
99     {
100         m_assembler.subl_im(imm.m_value, address.m_ptr);
101     }
102
103     void load32(void* address, RegisterID dest)
104     {
105         m_assembler.movl_mr(address, dest);
106     }
107
108     void storeDouble(ImmDouble imm, Address address)
109     {
110         store32(Imm32(imm.u.s.lsb), address);
111         store32(Imm32(imm.u.s.msb), Address(address.base, address.offset + 4));
112     }
113
114     void storeDouble(ImmDouble imm, BaseIndex address)
115     {
116         store32(Imm32(imm.u.s.lsb), address);
117         store32(Imm32(imm.u.s.msb),
118                 BaseIndex(address.base, address.index, address.scale, address.offset + 4));
119     }
120
121     DataLabelPtr loadDouble(const void* address, FPRegisterID dest)
122     {
123         ASSERT(isSSE2Present());
124         m_assembler.movsd_mr(address, dest);
125         return DataLabelPtr(this);
126     }
127
128     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
129     {
130         m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
131     }
132
133     void convertUInt32ToDouble(RegisterID srcDest, FPRegisterID dest)
134     {
135         // Trick is from nanojit/Nativei386.cpp, asm_ui2d.
136         static const double NegativeOne = 2147483648.0;
137
138         // src is [0, 2^32-1]
139         sub32(Imm32(0x80000000), srcDest);
140
141         // Now src is [-2^31, 2^31-1] - int range, but not the same value.
142         zeroDouble(dest);
143         convertInt32ToDouble(srcDest, dest);
144
145         // dest is now a double with the int range.
146         // correct the double value by adding (0x80000000).
147         move(ImmPtr(&NegativeOne), srcDest);
148         addDouble(Address(srcDest), dest);
149     }
150
151     void store32(Imm32 imm, void* address)
152     {
153         m_assembler.movl_i32m(imm.m_value, address);
154     }
155
156     void store32(RegisterID src, void* address)
157     {
158         m_assembler.movl_rm(src, address);
159     }
160
161     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
162     {
163         m_assembler.cmpl_rm(right, left.m_ptr);
164         return Jump(m_assembler.jCC(x86Condition(cond)));
165     }
166
167     Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
168     {
169         m_assembler.cmpl_im(right.m_value, left.m_ptr);
170         return Jump(m_assembler.jCC(x86Condition(cond)));
171     }
172
173     Call call()
174     {
175         return Call(m_assembler.call(), Call::Linkable);
176     }
177
178     Call tailRecursiveCall()
179     {
180         return Call::fromTailJump(jump());
181     }
182
183     Call makeTailRecursiveCall(Jump oldJump)
184     {
185         return Call::fromTailJump(oldJump);
186     }
187
188
189     DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
190     {
191         m_assembler.movl_i32r(initialValue.asIntptr(), dest);
192         return DataLabelPtr(this);
193     }
194
195     Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
196     {
197         m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
198         dataLabel = DataLabelPtr(this);
199         return Jump(m_assembler.jCC(x86Condition(cond)));
200     }
201
202     Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
203     {
204         m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base);
205         dataLabel = DataLabelPtr(this);
206         return Jump(m_assembler.jCC(x86Condition(cond)));
207     }
208
209     DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
210     {
211         m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
212         return DataLabelPtr(this);
213     }
214
215     Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
216     {
217         Label label(this);
218         load32(address, dest);
219         return label;
220     }
221
222     void pushAllRegs()
223     {
224         m_assembler.pusha();
225     }
226
227     void popAllRegs()
228     {
229         m_assembler.popa();
230     }
231
232     bool supportsFloatingPoint() const { return m_isSSE2Present; }
233     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
234     bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
235     bool supportsFloatingPointSqrt() const { return m_isSSE2Present; }
236
237 private:
238     const bool m_isSSE2Present;
239
240     friend class LinkBuffer;
241     friend class RepatchBuffer;
242
243     static void linkCall(void* code, Call call, FunctionPtr function)
244     {
245         X86Assembler::linkCall(code, call.m_jmp, function.value());
246     }
247
248     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
249     {
250         X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
251     }
252
253     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
254     {
255         X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
256     }
257 };
258
259 } // namespace JSC
260
261 #endif // ENABLE(ASSEMBLER)
262
263 #endif // MacroAssemblerX86_h