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_h
27 #define MacroAssemblerX86_h
28 
29 #include <wtf/Platform.h>
30 
31 #if ENABLE(ASSEMBLER) && CPU(X86)
32 
33 #include "MacroAssemblerX86Common.h"
34 
35 namespace JSC {
36 
37 class MacroAssemblerX86 : public MacroAssemblerX86Common {
38 public:
MacroAssemblerX86()39     MacroAssemblerX86()
40         : m_isSSE2Present(isSSE2Present())
41     {
42     }
43 
44     static const Scale ScalePtr = TimesFour;
45 
46     using MacroAssemblerX86Common::add32;
47     using MacroAssemblerX86Common::and32;
48     using MacroAssemblerX86Common::sub32;
49     using MacroAssemblerX86Common::or32;
50     using MacroAssemblerX86Common::load32;
51     using MacroAssemblerX86Common::store32;
52     using MacroAssemblerX86Common::branch32;
53     using MacroAssemblerX86Common::call;
54     using MacroAssemblerX86Common::loadDouble;
55     using MacroAssemblerX86Common::convertInt32ToDouble;
56 
add32(Imm32 imm,RegisterID src,RegisterID dest)57     void add32(Imm32 imm, RegisterID src, RegisterID dest)
58     {
59         m_assembler.leal_mr(imm.m_value, src, dest);
60     }
61 
add32(Imm32 imm,AbsoluteAddress address)62     void add32(Imm32 imm, AbsoluteAddress address)
63     {
64         m_assembler.addl_im(imm.m_value, address.m_ptr);
65     }
66 
addWithCarry32(Imm32 imm,AbsoluteAddress address)67     void addWithCarry32(Imm32 imm, AbsoluteAddress address)
68     {
69         m_assembler.adcl_im(imm.m_value, address.m_ptr);
70     }
71 
and32(Imm32 imm,AbsoluteAddress address)72     void and32(Imm32 imm, AbsoluteAddress address)
73     {
74         m_assembler.andl_im(imm.m_value, address.m_ptr);
75     }
76 
or32(Imm32 imm,AbsoluteAddress address)77     void or32(Imm32 imm, AbsoluteAddress address)
78     {
79         m_assembler.orl_im(imm.m_value, address.m_ptr);
80     }
81 
sub32(Imm32 imm,AbsoluteAddress address)82     void sub32(Imm32 imm, AbsoluteAddress address)
83     {
84         m_assembler.subl_im(imm.m_value, address.m_ptr);
85     }
86 
load32(void * address,RegisterID dest)87     void load32(void* address, RegisterID dest)
88     {
89         m_assembler.movl_mr(address, dest);
90     }
91 
loadDouble(void * address,FPRegisterID dest)92     void loadDouble(void* address, FPRegisterID dest)
93     {
94         ASSERT(isSSE2Present());
95         m_assembler.movsd_mr(address, dest);
96     }
97 
convertInt32ToDouble(AbsoluteAddress src,FPRegisterID dest)98     void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
99     {
100         m_assembler.cvtsi2sd_mr(src.m_ptr, dest);
101     }
102 
store32(Imm32 imm,void * address)103     void store32(Imm32 imm, void* address)
104     {
105         m_assembler.movl_i32m(imm.m_value, address);
106     }
107 
store32(RegisterID src,void * address)108     void store32(RegisterID src, void* address)
109     {
110         m_assembler.movl_rm(src, address);
111     }
112 
branch32(Condition cond,AbsoluteAddress left,RegisterID right)113     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
114     {
115         m_assembler.cmpl_rm(right, left.m_ptr);
116         return Jump(m_assembler.jCC(x86Condition(cond)));
117     }
118 
branch32(Condition cond,AbsoluteAddress left,Imm32 right)119     Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
120     {
121         m_assembler.cmpl_im(right.m_value, left.m_ptr);
122         return Jump(m_assembler.jCC(x86Condition(cond)));
123     }
124 
call()125     Call call()
126     {
127         return Call(m_assembler.call(), Call::Linkable);
128     }
129 
tailRecursiveCall()130     Call tailRecursiveCall()
131     {
132         return Call::fromTailJump(jump());
133     }
134 
makeTailRecursiveCall(Jump oldJump)135     Call makeTailRecursiveCall(Jump oldJump)
136     {
137         return Call::fromTailJump(oldJump);
138     }
139 
140 
moveWithPatch(ImmPtr initialValue,RegisterID dest)141     DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
142     {
143         m_assembler.movl_i32r(initialValue.asIntptr(), dest);
144         return DataLabelPtr(this);
145     }
146 
147     Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
148     {
149         m_assembler.cmpl_ir_force32(initialRightValue.asIntptr(), left);
150         dataLabel = DataLabelPtr(this);
151         return Jump(m_assembler.jCC(x86Condition(cond)));
152     }
153 
154     Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
155     {
156         m_assembler.cmpl_im_force32(initialRightValue.asIntptr(), left.offset, left.base);
157         dataLabel = DataLabelPtr(this);
158         return Jump(m_assembler.jCC(x86Condition(cond)));
159     }
160 
storePtrWithPatch(ImmPtr initialValue,ImplicitAddress address)161     DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
162     {
163         m_assembler.movl_i32m(initialValue.asIntptr(), address.offset, address.base);
164         return DataLabelPtr(this);
165     }
166 
loadPtrWithPatchToLEA(Address address,RegisterID dest)167     Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
168     {
169         Label label(this);
170         load32(address, dest);
171         return label;
172     }
173 
supportsFloatingPoint()174     bool supportsFloatingPoint() const { return m_isSSE2Present; }
175     // See comment on MacroAssemblerARMv7::supportsFloatingPointTruncate()
supportsFloatingPointTruncate()176     bool supportsFloatingPointTruncate() const { return m_isSSE2Present; }
177 
178 private:
179     const bool m_isSSE2Present;
180 
181     friend class LinkBuffer;
182     friend class RepatchBuffer;
183 
linkCall(void * code,Call call,FunctionPtr function)184     static void linkCall(void* code, Call call, FunctionPtr function)
185     {
186         X86Assembler::linkCall(code, call.m_jmp, function.value());
187     }
188 
repatchCall(CodeLocationCall call,CodeLocationLabel destination)189     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
190     {
191         X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
192     }
193 
repatchCall(CodeLocationCall call,FunctionPtr destination)194     static void repatchCall(CodeLocationCall call, FunctionPtr destination)
195     {
196         X86Assembler::relinkCall(call.dataLocation(), destination.executableAddress());
197     }
198 };
199 
200 } // namespace JSC
201 
202 #endif // ENABLE(ASSEMBLER)
203 
204 #endif // MacroAssemblerX86_h
205