blob: a3d24b276b2299898c6bf4aaad9bc0065c7a743f [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// 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.
ager@chromium.org9258b6b2008-09-11 09:11:10 +000033// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000034
35// A light-weight IA32 Assembler.
36
ager@chromium.org5ec48922009-05-05 07:25:34 +000037#ifndef V8_IA32_ASSEMBLER_IA32_INL_H_
38#define V8_IA32_ASSEMBLER_IA32_INL_H_
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000039
40#include "cpu.h"
41
42namespace v8 { namespace internal {
43
44Condition NegateCondition(Condition cc) {
45 return static_cast<Condition>(cc ^ 1);
46}
47
48
49// The modes possibly affected by apply must be in kApplyMask.
50void RelocInfo::apply(int delta) {
ager@chromium.org236ad962008-09-25 09:45:57 +000051 if (rmode_ == RUNTIME_ENTRY || IsCodeTarget(rmode_)) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052 int32_t* p = reinterpret_cast<int32_t*>(pc_);
53 *p -= delta; // relocate entry
iposva@chromium.org245aa852009-02-10 00:49:54 +000054 } else if (rmode_ == JS_RETURN && IsCallInstruction()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055 // Special handling of js_return when a break point is set (call
56 // instruction has been inserted).
57 int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
58 *p -= delta; // relocate entry
ager@chromium.org236ad962008-09-25 09:45:57 +000059 } else if (IsInternalReference(rmode_)) {
60 // absolute code pointer inside code object moves with the code object.
61 int32_t* p = reinterpret_cast<int32_t*>(pc_);
62 *p += delta; // relocate entry
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000063 }
64}
65
66
67Address RelocInfo::target_address() {
ager@chromium.org236ad962008-09-25 09:45:57 +000068 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000069 return Assembler::target_address_at(pc_);
70}
71
72
ager@chromium.org32912102009-01-16 10:38:43 +000073Address RelocInfo::target_address_address() {
74 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
75 return reinterpret_cast<Address>(pc_);
76}
77
78
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000079void RelocInfo::set_target_address(Address target) {
ager@chromium.org236ad962008-09-25 09:45:57 +000080 ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000081 Assembler::set_target_address_at(pc_, target);
82}
83
84
85Object* RelocInfo::target_object() {
ager@chromium.org236ad962008-09-25 09:45:57 +000086 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000087 return *reinterpret_cast<Object**>(pc_);
88}
89
90
91Object** RelocInfo::target_object_address() {
ager@chromium.org236ad962008-09-25 09:45:57 +000092 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000093 return reinterpret_cast<Object**>(pc_);
94}
95
96
97void RelocInfo::set_target_object(Object* target) {
ager@chromium.org236ad962008-09-25 09:45:57 +000098 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099 *reinterpret_cast<Object**>(pc_) = target;
100}
101
102
103Address* RelocInfo::target_reference_address() {
ager@chromium.org236ad962008-09-25 09:45:57 +0000104 ASSERT(rmode_ == RelocInfo::EXTERNAL_REFERENCE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000105 return reinterpret_cast<Address*>(pc_);
106}
107
108
109Address RelocInfo::call_address() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000110 ASSERT(IsCallInstruction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000111 return Assembler::target_address_at(pc_ + 1);
112}
113
114
115void RelocInfo::set_call_address(Address target) {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000116 ASSERT(IsCallInstruction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000117 Assembler::set_target_address_at(pc_ + 1, target);
118}
119
120
121Object* RelocInfo::call_object() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000122 ASSERT(IsCallInstruction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123 return *call_object_address();
124}
125
126
127Object** RelocInfo::call_object_address() {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000128 ASSERT(IsCallInstruction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000129 return reinterpret_cast<Object**>(pc_ + 1);
130}
131
132
133void RelocInfo::set_call_object(Object* target) {
iposva@chromium.org245aa852009-02-10 00:49:54 +0000134 ASSERT(IsCallInstruction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135 *call_object_address() = target;
136}
137
138
iposva@chromium.org245aa852009-02-10 00:49:54 +0000139bool RelocInfo::IsCallInstruction() {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140 return *pc_ == 0xE8;
141}
142
143
144Immediate::Immediate(int x) {
145 x_ = x;
ager@chromium.org236ad962008-09-25 09:45:57 +0000146 rmode_ = RelocInfo::NONE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147}
148
149
150Immediate::Immediate(const ExternalReference& ext) {
151 x_ = reinterpret_cast<int32_t>(ext.address());
ager@chromium.org236ad962008-09-25 09:45:57 +0000152 rmode_ = RelocInfo::EXTERNAL_REFERENCE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000153}
154
155Immediate::Immediate(const char* s) {
156 x_ = reinterpret_cast<int32_t>(s);
ager@chromium.org236ad962008-09-25 09:45:57 +0000157 rmode_ = RelocInfo::EMBEDDED_STRING;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000158}
159
160
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000161Immediate::Immediate(Label *internal_offset) {
162 x_ = reinterpret_cast<int32_t>(internal_offset);
163 rmode_ = RelocInfo::INTERNAL_REFERENCE;
164}
165
166
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000167Immediate::Immediate(Handle<Object> handle) {
168 // Verify all Objects referred by code are NOT in new space.
169 Object* obj = *handle;
170 ASSERT(!Heap::InNewSpace(obj));
171 if (obj->IsHeapObject()) {
172 x_ = reinterpret_cast<intptr_t>(handle.location());
ager@chromium.org236ad962008-09-25 09:45:57 +0000173 rmode_ = RelocInfo::EMBEDDED_OBJECT;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000174 } else {
175 // no relocation needed
176 x_ = reinterpret_cast<intptr_t>(obj);
ager@chromium.org236ad962008-09-25 09:45:57 +0000177 rmode_ = RelocInfo::NONE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000178 }
179}
180
181
182Immediate::Immediate(Smi* value) {
183 x_ = reinterpret_cast<intptr_t>(value);
ager@chromium.org236ad962008-09-25 09:45:57 +0000184 rmode_ = RelocInfo::NONE;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185}
186
187
188void Assembler::emit(uint32_t x) {
189 *reinterpret_cast<uint32_t*>(pc_) = x;
190 pc_ += sizeof(uint32_t);
191}
192
193
194void Assembler::emit(Handle<Object> handle) {
195 // Verify all Objects referred by code are NOT in new space.
196 Object* obj = *handle;
197 ASSERT(!Heap::InNewSpace(obj));
198 if (obj->IsHeapObject()) {
ager@chromium.org236ad962008-09-25 09:45:57 +0000199 emit(reinterpret_cast<intptr_t>(handle.location()),
200 RelocInfo::EMBEDDED_OBJECT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000201 } else {
202 // no relocation needed
203 emit(reinterpret_cast<intptr_t>(obj));
204 }
205}
206
207
ager@chromium.org236ad962008-09-25 09:45:57 +0000208void Assembler::emit(uint32_t x, RelocInfo::Mode rmode) {
209 if (rmode != RelocInfo::NONE) RecordRelocInfo(rmode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 emit(x);
211}
212
213
214void Assembler::emit(const Immediate& x) {
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000215 if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
216 Label* label = reinterpret_cast<Label*>(x.x_);
217 emit_code_relative_offset(label);
218 return;
219 }
ager@chromium.org236ad962008-09-25 09:45:57 +0000220 if (x.rmode_ != RelocInfo::NONE) RecordRelocInfo(x.rmode_);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000221 emit(x.x_);
222}
223
224
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000225void Assembler::emit_code_relative_offset(Label* label) {
226 if (label->is_bound()) {
227 int32_t pos;
228 pos = label->pos() + Code::kHeaderSize - kHeapObjectTag;
229 emit(pos);
230 } else {
231 emit_disp(label, Displacement::CODE_RELATIVE);
232 }
233}
234
235
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000236void Assembler::emit_w(const Immediate& x) {
237 ASSERT(x.rmode_ == RelocInfo::NONE);
238 uint16_t value = static_cast<uint16_t>(x.x_);
239 reinterpret_cast<uint16_t*>(pc_)[0] = value;
240 pc_ += sizeof(uint16_t);
241}
242
243
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244Address Assembler::target_address_at(Address pc) {
245 return pc + sizeof(int32_t) + *reinterpret_cast<int32_t*>(pc);
246}
247
kasper.lund7276f142008-07-30 08:49:36 +0000248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249void Assembler::set_target_address_at(Address pc, Address target) {
250 int32_t* p = reinterpret_cast<int32_t*>(pc);
251 *p = target - (pc + sizeof(int32_t));
252 CPU::FlushICache(p, sizeof(int32_t));
253}
254
kasper.lund7276f142008-07-30 08:49:36 +0000255
256Displacement Assembler::disp_at(Label* L) {
257 return Displacement(long_at(L->pos()));
258}
259
260
261void Assembler::disp_at_put(Label* L, Displacement disp) {
262 long_at_put(L->pos(), disp.data());
263}
264
265
266void Assembler::emit_disp(Label* L, Displacement::Type type) {
267 Displacement disp(L, type);
268 L->link_to(pc_offset());
269 emit(static_cast<int>(disp.data()));
270}
271
272
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000273void Operand::set_modrm(int mod, Register rm) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000274 ASSERT((mod & -4) == 0);
275 buf_[0] = mod << 6 | rm.code();
276 len_ = 1;
277}
278
279
ager@chromium.org236ad962008-09-25 09:45:57 +0000280void Operand::set_dispr(int32_t disp, RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000281 ASSERT(len_ == 1 || len_ == 2);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000282 int32_t* p = reinterpret_cast<int32_t*>(&buf_[len_]);
283 *p = disp;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000284 len_ += sizeof(int32_t);
285 rmode_ = rmode;
286}
287
288Operand::Operand(Register reg) {
289 // reg
290 set_modrm(3, reg);
291}
292
293
ager@chromium.org236ad962008-09-25 09:45:57 +0000294Operand::Operand(int32_t disp, RelocInfo::Mode rmode) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000295 // [disp/r]
296 set_modrm(0, ebp);
297 set_dispr(disp, rmode);
298}
299
300} } // namespace v8::internal
301
ager@chromium.org5ec48922009-05-05 07:25:34 +0000302#endif // V8_IA32_ASSEMBLER_IA32_INL_H_