blob: ef869b4485e6aa77afe60a0070cc4051d1b97e9f [file] [log] [blame]
barraclough@apple.coma36d9992009-02-05 03:40:39 +00001/*
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_h
27#define MacroAssemblerX86_h
28
mjs@apple.comcc668212010-01-04 11:38:56 +000029#if ENABLE(ASSEMBLER) && CPU(X86)
barraclough@apple.coma36d9992009-02-05 03:40:39 +000030
31#include "MacroAssemblerX86Common.h"
32
oliver@apple.come9743fd2013-07-25 04:00:16 +000033#if USE(MASM_PROBE)
34#include <wtf/StdLibExtras.h>
35#endif
36
barraclough@apple.coma36d9992009-02-05 03:40:39 +000037namespace JSC {
38
39class MacroAssemblerX86 : public MacroAssemblerX86Common {
40public:
41 static const Scale ScalePtr = TimesFour;
42
43 using MacroAssemblerX86Common::add32;
barraclough@apple.comc32f32e2009-05-13 09:10:02 +000044 using MacroAssemblerX86Common::and32;
fpizlo@apple.com594887a2011-09-06 09:23:55 +000045 using MacroAssemblerX86Common::branchAdd32;
barraclough@apple.com70558a32011-10-04 01:16:46 +000046 using MacroAssemblerX86Common::branchSub32;
barraclough@apple.coma36d9992009-02-05 03:40:39 +000047 using MacroAssemblerX86Common::sub32;
barraclough@apple.comc32f32e2009-05-13 09:10:02 +000048 using MacroAssemblerX86Common::or32;
barraclough@apple.coma36d9992009-02-05 03:40:39 +000049 using MacroAssemblerX86Common::load32;
50 using MacroAssemblerX86Common::store32;
fpizlo@apple.com69e27842012-09-19 21:43:10 +000051 using MacroAssemblerX86Common::store8;
barraclough@apple.coma36d9992009-02-05 03:40:39 +000052 using MacroAssemblerX86Common::branch32;
barraclough@apple.comd7e13382009-02-19 22:51:40 +000053 using MacroAssemblerX86Common::call;
fpizlo@apple.com46211712011-11-10 01:08:50 +000054 using MacroAssemblerX86Common::jump;
barraclough@apple.come1227fc2011-09-22 01:10:31 +000055 using MacroAssemblerX86Common::addDouble;
ggaren@apple.com540d71a62009-07-30 20:57:44 +000056 using MacroAssemblerX86Common::loadDouble;
barraclough@apple.comd910c0d2011-09-24 05:04:08 +000057 using MacroAssemblerX86Common::storeDouble;
ggaren@apple.com540d71a62009-07-30 20:57:44 +000058 using MacroAssemblerX86Common::convertInt32ToDouble;
fpizlo@apple.comb75911b2012-06-13 20:53:52 +000059 using MacroAssemblerX86Common::branchTest8;
barraclough@apple.coma36d9992009-02-05 03:40:39 +000060
oliver@apple.combe4e0672011-03-28 17:14:57 +000061 void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
barraclough@apple.coma36d9992009-02-05 03:40:39 +000062 {
63 m_assembler.leal_mr(imm.m_value, src, dest);
64 }
65
oliver@apple.combe4e0672011-03-28 17:14:57 +000066 void add32(TrustedImm32 imm, AbsoluteAddress address)
barraclough@apple.coma36d9992009-02-05 03:40:39 +000067 {
68 m_assembler.addl_im(imm.m_value, address.m_ptr);
69 }
70
fpizlo@apple.com327f2372012-07-15 04:02:16 +000071 void add32(AbsoluteAddress address, RegisterID dest)
72 {
73 m_assembler.addl_mr(address.m_ptr, dest);
74 }
75
barraclough@apple.com6d410b02011-11-10 20:24:06 +000076 void add64(TrustedImm32 imm, AbsoluteAddress address)
barraclough@apple.comc32f32e2009-05-13 09:10:02 +000077 {
barraclough@apple.com6d410b02011-11-10 20:24:06 +000078 m_assembler.addl_im(imm.m_value, address.m_ptr);
79 m_assembler.adcl_im(imm.m_value >> 31, reinterpret_cast<const char*>(address.m_ptr) + sizeof(int32_t));
barraclough@apple.comc32f32e2009-05-13 09:10:02 +000080 }
barraclough@apple.com6d410b02011-11-10 20:24:06 +000081
oliver@apple.combe4e0672011-03-28 17:14:57 +000082 void and32(TrustedImm32 imm, AbsoluteAddress address)
barraclough@apple.comc32f32e2009-05-13 09:10:02 +000083 {
84 m_assembler.andl_im(imm.m_value, address.m_ptr);
85 }
86
oliver@apple.combe4e0672011-03-28 17:14:57 +000087 void or32(TrustedImm32 imm, AbsoluteAddress address)
barraclough@apple.comc32f32e2009-05-13 09:10:02 +000088 {
89 m_assembler.orl_im(imm.m_value, address.m_ptr);
90 }
fpizlo@apple.com327f2372012-07-15 04:02:16 +000091
fpizlo@apple.comc7be5be02012-09-17 19:07:32 +000092 void or32(RegisterID reg, AbsoluteAddress address)
93 {
94 m_assembler.orl_rm(reg, address.m_ptr);
95 }
96
oliver@apple.combe4e0672011-03-28 17:14:57 +000097 void sub32(TrustedImm32 imm, AbsoluteAddress address)
barraclough@apple.coma36d9992009-02-05 03:40:39 +000098 {
99 m_assembler.subl_im(imm.m_value, address.m_ptr);
100 }
101
barraclough@apple.com8328f632011-09-21 18:33:43 +0000102 void load32(const void* address, RegisterID dest)
eric@webkit.org667fa8a2010-08-08 06:04:59 +0000103 {
eric@webkit.orgb8130982010-08-08 07:22:06 +0000104 m_assembler.movl_mr(address, dest);
eric@webkit.org667fa8a2010-08-08 06:04:59 +0000105 }
106
fpizlo@apple.comd68b1f82012-07-05 22:55:51 +0000107 ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
108 {
109 ConvertibleLoadLabel result = ConvertibleLoadLabel(this);
110 m_assembler.movl_mr(address.offset, address.base, dest);
111 return result;
112 }
113
barraclough@apple.come1227fc2011-09-22 01:10:31 +0000114 void addDouble(AbsoluteAddress address, FPRegisterID dest)
115 {
116 m_assembler.addsd_mr(address.m_ptr, dest);
117 }
118
barraclough@apple.comd910c0d2011-09-24 05:04:08 +0000119 void storeDouble(FPRegisterID src, const void* address)
120 {
121 ASSERT(isSSE2Present());
122 m_assembler.movsd_rm(src, address);
123 }
124
ggaren@apple.com540d71a62009-07-30 20:57:44 +0000125 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
126 {
127 m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
128 }
129
oliver@apple.combe4e0672011-03-28 17:14:57 +0000130 void store32(TrustedImm32 imm, void* address)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000131 {
132 m_assembler.movl_i32m(imm.m_value, address);
133 }
134
mjs@apple.com93553702009-05-09 08:35:57 +0000135 void store32(RegisterID src, void* address)
136 {
eric@webkit.orgb8130982010-08-08 07:22:06 +0000137 m_assembler.movl_rm(src, address);
mjs@apple.com93553702009-05-09 08:35:57 +0000138 }
139
fpizlo@apple.com69e27842012-09-19 21:43:10 +0000140 void store8(TrustedImm32 imm, void* address)
141 {
142 ASSERT(-128 <= imm.m_value && imm.m_value < 128);
143 m_assembler.movb_i8m(imm.m_value, address);
144 }
fpizlo@apple.comc14c8d32012-10-10 02:14:42 +0000145
146 // Possibly clobbers src.
147 void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
148 {
149 movePackedToInt32(src, dest1);
150 rshiftPacked(TrustedImm32(32), src);
151 movePackedToInt32(src, dest2);
152 }
153
154 void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch)
155 {
156 moveInt32ToPacked(src1, dest);
157 moveInt32ToPacked(src2, scratch);
158 lshiftPacked(TrustedImm32(32), scratch);
159 orPacked(scratch, dest);
160 }
fpizlo@apple.com69e27842012-09-19 21:43:10 +0000161
barraclough@apple.com70558a32011-10-04 01:16:46 +0000162 Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
fpizlo@apple.com594887a2011-09-06 09:23:55 +0000163 {
barraclough@apple.com70558a32011-10-04 01:16:46 +0000164 m_assembler.addl_im(imm.m_value, dest.m_ptr);
165 return Jump(m_assembler.jCC(x86Condition(cond)));
166 }
167
168 Jump branchSub32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
169 {
170 m_assembler.subl_im(imm.m_value, dest.m_ptr);
fpizlo@apple.com594887a2011-09-06 09:23:55 +0000171 return Jump(m_assembler.jCC(x86Condition(cond)));
172 }
173
barraclough@apple.com03cd2482011-04-20 18:44:35 +0000174 Jump branch32(RelationalCondition cond, AbsoluteAddress left, RegisterID right)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000175 {
176 m_assembler.cmpl_rm(right, left.m_ptr);
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000177 return Jump(m_assembler.jCC(x86Condition(cond)));
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000178 }
179
barraclough@apple.com03cd2482011-04-20 18:44:35 +0000180 Jump branch32(RelationalCondition cond, AbsoluteAddress left, TrustedImm32 right)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000181 {
182 m_assembler.cmpl_im(right.m_value, left.m_ptr);
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000183 return Jump(m_assembler.jCC(x86Condition(cond)));
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000184 }
185
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000186 Call call()
187 {
188 return Call(m_assembler.call(), Call::Linkable);
189 }
190
fpizlo@apple.com46211712011-11-10 01:08:50 +0000191 // Address is a memory location containing the address to jump to
192 void jump(AbsoluteAddress address)
193 {
194 m_assembler.jmp_m(address.m_ptr);
195 }
196
barraclough@apple.comd7e13382009-02-19 22:51:40 +0000197 Call tailRecursiveCall()
198 {
199 return Call::fromTailJump(jump());
200 }
201
202 Call makeTailRecursiveCall(Jump oldJump)
203 {
204 return Call::fromTailJump(oldJump);
205 }
206
207
oliver@apple.combe4e0672011-03-28 17:14:57 +0000208 DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
barraclough@apple.com07173242009-05-23 01:48:32 +0000209 {
fpizlo@apple.com0712be82012-08-21 23:30:19 +0000210 padBeforePatch();
barraclough@apple.com07173242009-05-23 01:48:32 +0000211 m_assembler.movl_i32r(initialValue.asIntptr(), dest);
212 return DataLabelPtr(this);
213 }
fpizlo@apple.comb75911b2012-06-13 20:53:52 +0000214
215 Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
216 {
217 ASSERT(mask.m_value >= -128 && mask.m_value <= 255);
218 if (mask.m_value == -1)
219 m_assembler.cmpb_im(0, address.m_ptr);
220 else
221 m_assembler.testb_im(mask.m_value, address.m_ptr);
222 return Jump(m_assembler.jCC(x86Condition(cond)));
223 }
barraclough@apple.com07173242009-05-23 01:48:32 +0000224
barraclough@apple.com03cd2482011-04-20 18:44:35 +0000225 Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000226 {
fpizlo@apple.com0712be82012-08-21 23:30:19 +0000227 padBeforePatch();
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000228 m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
229 dataLabel = DataLabelPtr(this);
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000230 return Jump(m_assembler.jCC(x86Condition(cond)));
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000231 }
232
barraclough@apple.com03cd2482011-04-20 18:44:35 +0000233 Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0))
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000234 {
fpizlo@apple.com0712be82012-08-21 23:30:19 +0000235 padBeforePatch();
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000236 m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base);
237 dataLabel = DataLabelPtr(this);
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000238 return Jump(m_assembler.jCC(x86Condition(cond)));
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000239 }
240
oliver@apple.combe4e0672011-03-28 17:14:57 +0000241 DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000242 {
fpizlo@apple.com0712be82012-08-21 23:30:19 +0000243 padBeforePatch();
barraclough@apple.comfb4e1a72009-06-06 02:39:36 +0000244 m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000245 return DataLabelPtr(this);
246 }
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000247
barraclough@apple.com2326f422011-11-09 20:01:24 +0000248 static bool supportsFloatingPoint() { return isSSE2Present(); }
barraclough@apple.com7a53a832009-06-09 08:14:09 +0000249 // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
barraclough@apple.com2326f422011-11-09 20:01:24 +0000250 static bool supportsFloatingPointTruncate() { return isSSE2Present(); }
251 static bool supportsFloatingPointSqrt() { return isSSE2Present(); }
252 static bool supportsFloatingPointAbs() { return isSSE2Present(); }
fpizlo@apple.coma147a4d2011-11-21 04:45:17 +0000253
254 static FunctionPtr readCallTarget(CodeLocationCall call)
255 {
256 intptr_t offset = reinterpret_cast<int32_t*>(call.dataLocation())[-1];
257 return FunctionPtr(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(call.dataLocation()) + offset));
258 }
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000259
fpizlo@apple.comdb010872012-11-13 01:55:42 +0000260 static bool canJumpReplacePatchableBranchPtrWithPatch() { return true; }
261
fpizlo@apple.com32d42ce2012-11-21 00:22:08 +0000262 static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
263 {
264 const int opcodeBytes = 1;
265 const int modRMBytes = 1;
266 const int immediateBytes = 4;
267 const int totalBytes = opcodeBytes + modRMBytes + immediateBytes;
268 ASSERT(totalBytes >= maxJumpReplacementSize());
269 return label.labelAtOffset(-totalBytes);
270 }
271
272 static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr label)
fpizlo@apple.comdb010872012-11-13 01:55:42 +0000273 {
274 const int opcodeBytes = 1;
275 const int modRMBytes = 1;
276 const int offsetBytes = 0;
277 const int immediateBytes = 4;
278 const int totalBytes = opcodeBytes + modRMBytes + offsetBytes + immediateBytes;
279 ASSERT(totalBytes >= maxJumpReplacementSize());
280 return label.labelAtOffset(-totalBytes);
281 }
282
fpizlo@apple.com32d42ce2012-11-21 00:22:08 +0000283 static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID reg, void* initialValue)
284 {
285 X86Assembler::revertJumpTo_cmpl_ir_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), reg);
286 }
287
fpizlo@apple.comdb010872012-11-13 01:55:42 +0000288 static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address address, void* initialValue)
289 {
290 ASSERT(!address.offset);
291 X86Assembler::revertJumpTo_cmpl_im_force32(instructionStart.executableAddress(), reinterpret_cast<intptr_t>(initialValue), 0, address.base);
292 }
293
oliver@apple.come9743fd2013-07-25 04:00:16 +0000294#if USE(MASM_PROBE)
oliver@apple.comc3a5b8c2013-07-25 04:01:38 +0000295 // For details about probe(), see comment in MacroAssemblerX86_64.h.
oliver@apple.come9743fd2013-07-25 04:00:16 +0000296 void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0);
297#endif // USE(MASM_PROBE)
298
barraclough@apple.com8f939c22009-05-15 21:11:10 +0000299private:
barraclough@apple.com96e73432009-07-22 03:24:34 +0000300 friend class LinkBuffer;
301 friend class RepatchBuffer;
302
303 static void linkCall(void* code, Call call, FunctionPtr function)
304 {
barraclough@apple.com0d15b9e2011-05-26 04:12:41 +0000305 X86Assembler::linkCall(code, call.m_label, function.value());
barraclough@apple.com96e73432009-07-22 03:24:34 +0000306 }
307
308 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
309 {
310 X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
311 }
312
313 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
314 {
315 X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
316 }
oliver@apple.come9743fd2013-07-25 04:00:16 +0000317
318#if USE(MASM_PROBE)
319 inline TrustedImm32 trustedImm32FromPtr(void* ptr)
320 {
321 return TrustedImm32(TrustedImmPtr(ptr));
322 }
323
324 inline TrustedImm32 trustedImm32FromPtr(ProbeFunction function)
325 {
326 return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
327 }
328
329 inline TrustedImm32 trustedImm32FromPtr(void (*function)())
330 {
331 return TrustedImm32(TrustedImmPtr(reinterpret_cast<void*>(function)));
332 }
333#endif
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000334};
335
oliver@apple.come9743fd2013-07-25 04:00:16 +0000336#if USE(MASM_PROBE)
337
338extern "C" void ctiMasmProbeTrampoline();
339
oliver@apple.comc3a5b8c2013-07-25 04:01:38 +0000340// For details on "What code is emitted for the probe?" and "What values are in
341// the saved registers?", see comment for MacroAssemblerX86::probe() in
342// MacroAssemblerX86_64.h.
oliver@apple.come9743fd2013-07-25 04:00:16 +0000343
344inline void MacroAssemblerX86::probe(MacroAssemblerX86::ProbeFunction function, void* arg1, void* arg2)
345{
oliver@apple.comc3a5b8c2013-07-25 04:01:38 +0000346 push(RegisterID::esp);
347 push(RegisterID::eax);
348 push(trustedImm32FromPtr(arg2));
349 push(trustedImm32FromPtr(arg1));
350 push(trustedImm32FromPtr(function));
oliver@apple.come9743fd2013-07-25 04:00:16 +0000351
352 move(trustedImm32FromPtr(ctiMasmProbeTrampoline), RegisterID::eax);
353 call(RegisterID::eax);
oliver@apple.come9743fd2013-07-25 04:00:16 +0000354}
355#endif // USE(MASM_PROBE)
356
barraclough@apple.coma36d9992009-02-05 03:40:39 +0000357} // namespace JSC
358
359#endif // ENABLE(ASSEMBLER)
360
361#endif // MacroAssemblerX86_h