• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 && IsPatchedReturnSequence()) {
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 Memory::Object_at(pc_);
89 }
90 
91 
target_object_handle(Assembler * origin)92 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
93   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
94   return Memory::Object_Handle_at(pc_);
95 }
96 
97 
target_object_address()98 Object** RelocInfo::target_object_address() {
99   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
100   return &Memory::Object_at(pc_);
101 }
102 
103 
set_target_object(Object * target)104 void RelocInfo::set_target_object(Object* target) {
105   ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
106   Memory::Object_at(pc_) = target;
107 }
108 
109 
target_reference_address()110 Address* RelocInfo::target_reference_address() {
111   ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
112   return reinterpret_cast<Address*>(pc_);
113 }
114 
115 
call_address()116 Address RelocInfo::call_address() {
117   ASSERT(IsPatchedReturnSequence());
118   return Assembler::target_address_at(pc_ + 1);
119 }
120 
121 
set_call_address(Address target)122 void RelocInfo::set_call_address(Address target) {
123   ASSERT(IsPatchedReturnSequence());
124   Assembler::set_target_address_at(pc_ + 1, target);
125 }
126 
127 
call_object()128 Object* RelocInfo::call_object() {
129   ASSERT(IsPatchedReturnSequence());
130   return *call_object_address();
131 }
132 
133 
call_object_address()134 Object** RelocInfo::call_object_address() {
135   ASSERT(IsPatchedReturnSequence());
136   return reinterpret_cast<Object**>(pc_ + 1);
137 }
138 
139 
set_call_object(Object * target)140 void RelocInfo::set_call_object(Object* target) {
141   ASSERT(IsPatchedReturnSequence());
142   *call_object_address() = target;
143 }
144 
145 
IsPatchedReturnSequence()146 bool RelocInfo::IsPatchedReturnSequence() {
147   return *pc_ == 0xE8;
148 }
149 
150 
Immediate(int x)151 Immediate::Immediate(int x)  {
152   x_ = x;
153   rmode_ = RelocInfo::NONE;
154 }
155 
156 
Immediate(const ExternalReference & ext)157 Immediate::Immediate(const ExternalReference& ext) {
158   x_ = reinterpret_cast<int32_t>(ext.address());
159   rmode_ = RelocInfo::EXTERNAL_REFERENCE;
160 }
161 
Immediate(const char * s)162 Immediate::Immediate(const char* s) {
163   x_ = reinterpret_cast<int32_t>(s);
164   rmode_ = RelocInfo::EMBEDDED_STRING;
165 }
166 
167 
Immediate(Label * internal_offset)168 Immediate::Immediate(Label* internal_offset) {
169   x_ = reinterpret_cast<int32_t>(internal_offset);
170   rmode_ = RelocInfo::INTERNAL_REFERENCE;
171 }
172 
173 
Immediate(Handle<Object> handle)174 Immediate::Immediate(Handle<Object> handle) {
175   // Verify all Objects referred by code are NOT in new space.
176   Object* obj = *handle;
177   ASSERT(!Heap::InNewSpace(obj));
178   if (obj->IsHeapObject()) {
179     x_ = reinterpret_cast<intptr_t>(handle.location());
180     rmode_ = RelocInfo::EMBEDDED_OBJECT;
181   } else {
182     // no relocation needed
183     x_ =  reinterpret_cast<intptr_t>(obj);
184     rmode_ = RelocInfo::NONE;
185   }
186 }
187 
188 
Immediate(Smi * value)189 Immediate::Immediate(Smi* value) {
190   x_ = reinterpret_cast<intptr_t>(value);
191   rmode_ = RelocInfo::NONE;
192 }
193 
194 
emit(uint32_t x)195 void Assembler::emit(uint32_t x) {
196   *reinterpret_cast<uint32_t*>(pc_) = x;
197   pc_ += sizeof(uint32_t);
198 }
199 
200 
emit(Handle<Object> handle)201 void Assembler::emit(Handle<Object> handle) {
202   // Verify all Objects referred by code are NOT in new space.
203   Object* obj = *handle;
204   ASSERT(!Heap::InNewSpace(obj));
205   if (obj->IsHeapObject()) {
206     emit(reinterpret_cast<intptr_t>(handle.location()),
207          RelocInfo::EMBEDDED_OBJECT);
208   } else {
209     // no relocation needed
210     emit(reinterpret_cast<intptr_t>(obj));
211   }
212 }
213 
214 
emit(uint32_t x,RelocInfo::Mode rmode)215 void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {
216   if (rmode != RelocInfo::NONE) RecordRelocInfo(rmode);
217   emit(x);
218 }
219 
220 
emit(const Immediate & x)221 void Assembler::emit(const Immediate& x) {
222   if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
223     Label* label = reinterpret_cast<Label*>(x.x_);
224     emit_code_relative_offset(label);
225     return;
226   }
227   if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
228   emit(x.x_);
229 }
230 
231 
emit_code_relative_offset(Label * label)232 void Assembler::emit_code_relative_offset(Label* label) {
233   if (label->is_bound()) {
234     int32_t pos;
235     pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
236     emit(pos);
237   } else {
238     emit_disp(label, Displacement::CODE_RELATIVE);
239   }
240 }
241 
242 
emit_w(const Immediate & x)243 void Assembler::emit_w(const Immediate& x) {
244   ASSERT(x.rmode_ == RelocInfo::NONE);
245   uint16_t value = static_cast<uint16_t>(x.x_);
246   reinterpret_cast<uint16_t*>(pc_)[0] = value;
247   pc_ += sizeof(uint16_t);
248 }
249 
250 
target_address_at(Address pc)251 Address Assembler::target_address_at(Address pc) {
252   return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
253 }
254 
255 
set_target_address_at(Address pc,Address target)256 void Assembler::set_target_address_at(Address pc, Address target) {
257   int32_t* p = reinterpret_cast<int32_t*>(pc);
258   *p = target - (pc + sizeof(int32_t));
259   CPU::FlushICache(p, sizeof(int32_t));
260 }
261 
262 
disp_at(Label * L)263 Displacement Assembler::disp_at(Label* L) {
264   return Displacement(long_at(L->pos()));
265 }
266 
267 
disp_at_put(Label * L,Displacement disp)268 void Assembler::disp_at_put(Label* L, Displacement disp) {
269   long_at_put(L->pos(), disp.data());
270 }
271 
272 
emit_disp(Label * L,Displacement::Type type)273 void Assembler::emit_disp(Label* L, Displacement::Type type) {
274   Displacement disp(L, type);
275   L->link_to(pc_offset());
276   emit(static_cast<int>(disp.data()));
277 }
278 
279 
set_modrm(int mod,Register rm)280 void Operand::set_modrm(int mod, Register rm) {
281   ASSERT((mod & -4) == 0);
282   buf_[0] = mod << 6 | rm.code();
283   len_ = 1;
284 }
285 
286 
set_sib(ScaleFactor scale,Register index,Register base)287 void Operand::set_sib(ScaleFactor scale, Register index, Register base) {
288   ASSERT(len_ == 1);
289   ASSERT((scale & -4) == 0);
290   // Use SIB with no index register only for base esp.
291   ASSERT(!index.is(esp) || base.is(esp));
292   buf_[1] = scale << 6 | index.code() << 3 | base.code();
293   len_ = 2;
294 }
295 
296 
set_disp8(int8_t disp)297 void Operand::set_disp8(int8_t disp) {
298   ASSERT(len_ == 1 || len_ == 2);
299   *reinterpret_cast<int8_t*>(&buf_[len_++]) = disp;
300 }
301 
302 
set_dispr(int32_t disp,RelocInfo::Mode rmode)303 void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
304   ASSERT(len_ == 1 || len_ == 2);
305   int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
306   *p = disp;
307   len_ += sizeof(int32_t);
308   rmode_ = rmode;
309 }
310 
Operand(Register reg)311 Operand::Operand(Register reg) {
312   // reg
313   set_modrm(3, reg);
314 }
315 
316 
Operand(int32_t disp,RelocInfo::Mode rmode)317 Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
318   // [disp/r]
319   set_modrm(0, ebp);
320   set_dispr(disp, rmode);
321 }
322 
323 } }  // namespace v8::internal
324 
325 #endif  // V8_IA32_ASSEMBLER_IA32_INL_H_
326