1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // 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 are
6 // met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2006-2008 the V8 project authors. All rights reserved.
34
35 // A light-weight IA32 Assembler.
36
37 #ifndef V8_IA32_ASSEMBLER_IA32_INL_H_
38 #define V8_IA32_ASSEMBLER_IA32_INL_H_
39
40 #include "cpu.h"
41
42 namespace v8 {
43 namespace internal {
44
NegateCondition(Condition cc)45 Condition NegateCondition(Condition cc) {
46 return static_cast<Condition>(cc ^ 1);
47 }
48
49
50 // The modes possibly affected by apply must be in kApplyMask.
apply(intptr_t delta)51 void RelocInfo::apply(intptr_t delta) {
52 if (rmode_ == RUNTIME_ENTRY || IsCodeTarget(rmode_)) {
53 int32_t* p = reinterpret_cast<int32_t*>(pc_);
54 *p -= delta; // relocate entry
55 } else if (rmode_ == JS_RETURN && IsCallInstruction()) {
56 // Special handling of js_return when a break point is set (call
57 // instruction has been inserted).
58 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
59 *p -= delta; // relocate entry
60 } else if (IsInternalReference(rmode_)) {
61 // absolute code pointer inside code object moves with the code object.
62 int32_t* p = reinterpret_cast<int32_t*>(pc_);
63 *p += delta; // relocate entry
64 }
65 }
66
67
target_address()68 Address RelocInfo::target_address() {
69 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
70 return Assembler::target_address_at(pc_);
71 }
72
73
target_address_address()74 Address RelocInfo::target_address_address() {
75 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
76 return reinterpret_cast<Address>(pc_);
77 }
78
79
set_target_address(Address target)80 void RelocInfo::set_target_address(Address target) {
81 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
82 Assembler::set_target_address_at(pc_, target);
83 }
84
85
target_object()86 Object* RelocInfo::target_object() {
87 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
88 return *reinterpret_cast<Object**>(pc_);
89 }
90
91
target_object_address()92 Object** RelocInfo::target_object_address() {
93 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
94 return reinterpret_cast<Object**>(pc_);
95 }
96
97
set_target_object(Object * target)98 void RelocInfo::set_target_object(Object* target) {
99 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
100 *reinterpret_cast<Object**>(pc_) = target;
101 }
102
103
target_reference_address()104 Address* RelocInfo::target_reference_address() {
105 ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
106 return reinterpret_cast<Address*>(pc_);
107 }
108
109
call_address()110 Address RelocInfo::call_address() {
111 ASSERT(IsCallInstruction());
112 return Assembler::target_address_at(pc_ + 1);
113 }
114
115
set_call_address(Address target)116 void RelocInfo::set_call_address(Address target) {
117 ASSERT(IsCallInstruction());
118 Assembler::set_target_address_at(pc_ + 1, target);
119 }
120
121
call_object()122 Object* RelocInfo::call_object() {
123 ASSERT(IsCallInstruction());
124 return *call_object_address();
125 }
126
127
call_object_address()128 Object** RelocInfo::call_object_address() {
129 ASSERT(IsCallInstruction());
130 return reinterpret_cast<Object**>(pc_ + 1);
131 }
132
133
set_call_object(Object * target)134 void RelocInfo::set_call_object(Object* target) {
135 ASSERT(IsCallInstruction());
136 *call_object_address() = target;
137 }
138
139
IsCallInstruction()140 bool RelocInfo::IsCallInstruction() {
141 return *pc_ == 0xE8;
142 }
143
144
Immediate(int x)145 Immediate::Immediate(int x) {
146 x_ = x;
147 rmode_ = RelocInfo::NONE;
148 }
149
150
Immediate(const ExternalReference & ext)151 Immediate::Immediate(const ExternalReference& ext) {
152 x_ = reinterpret_cast<int32_t>(ext.address());
153 rmode_ = RelocInfo::EXTERNAL_REFERENCE;
154 }
155
Immediate(const char * s)156 Immediate::Immediate(const char* s) {
157 x_ = reinterpret_cast<int32_t>(s);
158 rmode_ = RelocInfo::EMBEDDED_STRING;
159 }
160
161
Immediate(Label * internal_offset)162 Immediate::Immediate(Label* internal_offset) {
163 x_ = reinterpret_cast<int32_t>(internal_offset);
164 rmode_ = RelocInfo::INTERNAL_REFERENCE;
165 }
166
167
Immediate(Handle<Object> handle)168 Immediate::Immediate(Handle<Object> handle) {
169 // Verify all Objects referred by code are NOT in new space.
170 Object* obj = *handle;
171 ASSERT(!Heap::InNewSpace(obj));
172 if (obj->IsHeapObject()) {
173 x_ = reinterpret_cast<intptr_t>(handle.location());
174 rmode_ = RelocInfo::EMBEDDED_OBJECT;
175 } else {
176 // no relocation needed
177 x_ = reinterpret_cast<intptr_t>(obj);
178 rmode_ = RelocInfo::NONE;
179 }
180 }
181
182
Immediate(Smi * value)183 Immediate::Immediate(Smi* value) {
184 x_ = reinterpret_cast<intptr_t>(value);
185 rmode_ = RelocInfo::NONE;
186 }
187
188
emit(uint32_t x)189 void Assembler::emit(uint32_t x) {
190 *reinterpret_cast<uint32_t*>(pc_) = x;
191 pc_ += sizeof(uint32_t);
192 }
193
194
emit(Handle<Object> handle)195 void Assembler::emit(Handle<Object> handle) {
196 // Verify all Objects referred by code are NOT in new space.
197 Object* obj = *handle;
198 ASSERT(!Heap::InNewSpace(obj));
199 if (obj->IsHeapObject()) {
200 emit(reinterpret_cast<intptr_t>(handle.location()),
201 RelocInfo::EMBEDDED_OBJECT);
202 } else {
203 // no relocation needed
204 emit(reinterpret_cast<intptr_t>(obj));
205 }
206 }
207
208
emit(uint32_t x,RelocInfo::Mode rmode)209 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {
210 if (rmode != RelocInfo::NONE) RecordRelocInfo(rmode);
211 emit(x);
212 }
213
214
emit(const Immediate & x)215 void Assembler::emit(const Immediate& x) {
216 if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
217 Label* label = reinterpret_cast<Label*>(x.x_);
218 emit_code_relative_offset(label);
219 return;
220 }
221 if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
222 emit(x.x_);
223 }
224
225
emit_code_relative_offset(Label * label)226 void Assembler::emit_code_relative_offset(Label* label) {
227 if (label->is_bound()) {
228 int32_t pos;
229 pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
230 emit(pos);
231 } else {
232 emit_disp(label, Displacement::CODE_RELATIVE);
233 }
234 }
235
236
emit_w(const Immediate & x)237 void Assembler::emit_w(const Immediate& x) {
238 ASSERT(x.rmode_ == RelocInfo::NONE);
239 uint16_t value = static_cast<uint16_t>(x.x_);
240 reinterpret_cast<uint16_t*>(pc_)[0] = value;
241 pc_ += sizeof(uint16_t);
242 }
243
244
target_address_at(Address pc)245 Address Assembler::target_address_at(Address pc) {
246 return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
247 }
248
249
set_target_address_at(Address pc,Address target)250 void Assembler::set_target_address_at(Address pc, Address target) {
251 int32_t* p = reinterpret_cast<int32_t*>(pc);
252 *p = target - (pc + sizeof(int32_t));
253 CPU::FlushICache(p, sizeof(int32_t));
254 }
255
256
disp_at(Label * L)257 Displacement Assembler::disp_at(Label* L) {
258 return Displacement(long_at(L->pos()));
259 }
260
261
disp_at_put(Label * L,Displacement disp)262 void Assembler::disp_at_put(Label* L, Displacement disp) {
263 long_at_put(L->pos(), disp.data());
264 }
265
266
emit_disp(Label * L,Displacement::Type type)267 void Assembler::emit_disp(Label* L, Displacement::Type type) {
268 Displacement disp(L, type);
269 L->link_to(pc_offset());
270 emit(static_cast<int>(disp.data()));
271 }
272
273
set_modrm(int mod,Register rm)274 void Operand::set_modrm(int mod, Register rm) {
275 ASSERT((mod & -4) == 0);
276 buf_[0] = mod << 6 | rm.code();
277 len_ = 1;
278 }
279
280
set_sib(ScaleFactor scale,Register index,Register base)281 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
282 ASSERT(len_ == 1);
283 ASSERT((scale & -4) == 0);
284 // Use SIB with no index register only for base esp.
285 ASSERT(!index.is(esp) || base.is(esp));
286 buf_[1] = scale << 6 | index.code() << 3 | base.code();
287 len_ = 2;
288 }
289
290
set_disp8(int8_t disp)291 void Operand::set_disp8(int8_t disp) {
292 ASSERT(len_ == 1 || len_ == 2);
293 *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
294 }
295
296
set_dispr(int32_t disp,RelocInfo::Mode rmode)297 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
298 ASSERT(len_ == 1 || len_ == 2);
299 int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
300 *p = disp;
301 len_ += sizeof(int32_t);
302 rmode_ = rmode;
303 }
304
Operand(Register reg)305 Operand::Operand(Register reg) {
306 // reg
307 set_modrm(3, reg);
308 }
309
310
Operand(int32_t disp,RelocInfo::Mode rmode)311 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
312 // [disp/r]
313 set_modrm(0, ebp);
314 set_dispr(disp, rmode);
315 }
316
317 } } // namespace v8::internal
318
319 #endif // V8_IA32_ASSEMBLER_IA32_INL_H_
320