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 763316 : class MacroAssemblerX86 : public MacroAssemblerX86Common {
42 : public:
43 763316 : MacroAssemblerX86()
44 763316 : : m_isSSE2Present(isSSE2Present())
45 : {
46 763316 : }
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 5028715 : void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
64 : {
65 5028715 : m_assembler.leal_mr(imm.m_value, src, dest);
66 5028715 : }
67 :
68 216 : void lea(Address address, RegisterID dest)
69 : {
70 216 : m_assembler.leal_mr(address.offset, address.base, dest);
71 216 : }
72 :
73 2 : void lea(BaseIndex address, RegisterID dest)
74 : {
75 2 : m_assembler.leal_mr(address.offset, address.base, address.index, address.scale, dest);
76 2 : }
77 :
78 5197 : void add32(Imm32 imm, AbsoluteAddress address)
79 : {
80 5197 : m_assembler.addl_im(imm.m_value, address.m_ptr);
81 5197 : }
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(TrustedImm32 imm, AbsoluteAddress address)
94 : {
95 : m_assembler.orl_im(imm.m_value, address.m_ptr);
96 : }
97 :
98 2582 : void sub32(TrustedImm32 imm, AbsoluteAddress address)
99 : {
100 2582 : m_assembler.subl_im(imm.m_value, address.m_ptr);
101 2582 : }
102 :
103 431088 : void load32(void* address, RegisterID dest)
104 : {
105 431088 : m_assembler.movl_mr(address, dest);
106 431088 : }
107 :
108 22 : void storeDouble(ImmDouble imm, Address address)
109 : {
110 22 : store32(Imm32(imm.u.s.lsb), address);
111 22 : store32(Imm32(imm.u.s.msb), Address(address.base, address.offset + 4));
112 22 : }
113 :
114 24 : void storeDouble(ImmDouble imm, BaseIndex address)
115 : {
116 24 : store32(Imm32(imm.u.s.lsb), address);
117 : store32(Imm32(imm.u.s.msb),
118 24 : BaseIndex(address.base, address.index, address.scale, address.offset + 4));
119 24 : }
120 :
121 280569 : DataLabelPtr loadDouble(const void* address, FPRegisterID dest)
122 : {
123 280569 : ASSERT(isSSE2Present());
124 280569 : m_assembler.movsd_mr(address, dest);
125 280569 : 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 195 : 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 195 : sub32(Imm32(0x80000000), srcDest);
140 :
141 : // Now src is [-2^31, 2^31-1] - int range, but not the same value.
142 195 : zeroDouble(dest);
143 195 : convertInt32ToDouble(srcDest, dest);
144 :
145 : // dest is now a double with the int range.
146 : // correct the double value by adding (0x80000000).
147 195 : move(ImmPtr(&NegativeOne), srcDest);
148 195 : addDouble(Address(srcDest), dest);
149 195 : }
150 :
151 : void store32(TrustedImm32 imm, void* address)
152 : {
153 : m_assembler.movl_i32m(imm.m_value, address);
154 : }
155 :
156 19127 : void store32(RegisterID src, void* address)
157 : {
158 19127 : m_assembler.movl_rm(src, address);
159 19127 : }
160 :
161 19127 : Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
162 : {
163 19127 : m_assembler.cmpl_rm(right, left.m_ptr);
164 19127 : return Jump(m_assembler.jCC(x86Condition(cond)));
165 : }
166 :
167 362293 : Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
168 : {
169 362293 : m_assembler.cmpl_im(right.m_value, left.m_ptr);
170 362293 : return Jump(m_assembler.jCC(x86Condition(cond)));
171 : }
172 :
173 4905615 : Call call()
174 : {
175 4905615 : 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 1567338 : DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
190 : {
191 1567338 : m_assembler.movl_i32r(initialValue.asIntptr(), dest);
192 1567338 : return DataLabelPtr(this);
193 : }
194 :
195 1032948 : Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
196 : {
197 1032948 : m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
198 1032948 : dataLabel = DataLabelPtr(this);
199 1032948 : 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 1875405 : DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
210 : {
211 1875405 : m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
212 1875405 : return DataLabelPtr(this);
213 : }
214 :
215 476707 : Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
216 : {
217 476707 : Label label(this);
218 476707 : 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 2226187 : bool supportsFloatingPoint() const { return m_isSSE2Present; }
233 : // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
234 : bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
235 392 : 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 4905105 : static void linkCall(void* code, Call call, FunctionPtr function)
244 : {
245 4905105 : X86Assembler::linkCall(code, call.m_jmp, function.value());
246 4905105 : }
247 :
248 : static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
249 : {
250 : X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
251 : }
252 :
253 66466 : static void repatchCall(CodeLocationCall call, FunctionPtr destination)
254 : {
255 66466 : X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
256 66466 : }
257 : };
258 :
259 : } // namespace JSC
260 :
261 : #endif // ENABLE(ASSEMBLER)
262 :
263 : #endif // MacroAssemblerX86_h
|