blob: 1c0e5c8d6b45988ea210680eb79163f38e0988a5 [file] [log] [blame]
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00004// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are 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
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000019//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000022// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000033// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +000035// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036
37// A light-weight ARM Assembler
38// Generates user mode instructions for the ARM architecture up to version 5
39
ager@chromium.org5ec48922009-05-05 07:25:34 +000040#ifndef V8_ARM_ASSEMBLER_ARM_H_
41#define V8_ARM_ASSEMBLER_ARM_H_
ager@chromium.org18ad94b2009-09-02 08:22:29 +000042#include <stdio.h>
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043#include "assembler.h"
ager@chromium.org378b34e2011-01-28 08:04:38 +000044#include "constants-arm.h"
ager@chromium.orgc4c92722009-11-18 14:12:51 +000045#include "serialize.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000046
kasperl@chromium.org71affb52009-05-26 05:44:31 +000047namespace v8 {
48namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049
50// CPU Registers.
51//
52// 1) We would prefer to use an enum, but enum values are assignment-
53// compatible with int, which has caused code-generation bugs.
54//
55// 2) We would prefer to use a class instead of a struct but we don't like
56// the register initialization to depend on the particular initialization
57// order (which appears to be different on OS X, Linux, and Windows for the
58// installed versions of C++ we tried). Using a struct permits C-style
59// "initialization". Also, the Register objects cannot be const as this
60// forces initialization stubs in MSVC, making us dependent on initialization
61// order.
62//
63// 3) By not using an enum, we are possibly preventing the compiler from
64// doing certain constant folds, which may significantly reduce the
65// code generated for some assembly instructions (because they boil down
66// to a few constants). If this is a problem, we could change the code
67// such that we use an enum in optimized mode, and the struct in debug
68// mode. This way we get the compile-time error checking in debug mode
69// and best performance in optimized code.
lrn@chromium.org5d00b602011-01-05 09:51:43 +000070
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071// Core register
72struct Register {
kasperl@chromium.orga5551262010-12-07 12:49:48 +000073 static const int kNumRegisters = 16;
74 static const int kNumAllocatableRegisters = 8;
erik.corry@gmail.com3847bd52011-04-27 10:38:56 +000075 static const int kSizeInBytes = 4;
kasperl@chromium.orga5551262010-12-07 12:49:48 +000076
77 static int ToAllocationIndex(Register reg) {
lrn@chromium.org5d00b602011-01-05 09:51:43 +000078 ASSERT(reg.code() < kNumAllocatableRegisters);
kasperl@chromium.orga5551262010-12-07 12:49:48 +000079 return reg.code();
80 }
81
82 static Register FromAllocationIndex(int index) {
83 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
84 return from_code(index);
85 }
86
87 static const char* AllocationIndexToString(int index) {
88 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
89 const char* const names[] = {
90 "r0",
91 "r1",
92 "r2",
93 "r3",
94 "r4",
95 "r5",
96 "r6",
97 "r7",
98 };
99 return names[index];
100 }
101
102 static Register from_code(int code) {
103 Register r = { code };
104 return r;
105 }
106
107 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000108 bool is(Register reg) const { return code_ == reg.code_; }
109 int code() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000110 ASSERT(is_valid());
111 return code_;
112 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000113 int bit() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114 ASSERT(is_valid());
115 return 1 << code_;
116 }
117
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000118 void set_code(int code) {
119 code_ = code;
120 ASSERT(is_valid());
121 }
122
ager@chromium.org5c838252010-02-19 08:53:10 +0000123 // Unfortunately we can't make this private in a struct.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000124 int code_;
125};
126
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000127const Register no_reg = { -1 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000129const Register r0 = { 0 };
130const Register r1 = { 1 };
131const Register r2 = { 2 };
132const Register r3 = { 3 };
133const Register r4 = { 4 };
134const Register r5 = { 5 };
135const Register r6 = { 6 };
136const Register r7 = { 7 };
137const Register r8 = { 8 }; // Used as context register.
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000138const Register r9 = { 9 }; // Used as lithium codegen scratch register.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000139const Register r10 = { 10 }; // Used as roots register.
140const Register fp = { 11 };
141const Register ip = { 12 };
142const Register sp = { 13 };
143const Register lr = { 14 };
144const Register pc = { 15 };
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000145
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000146// Single word VFP register.
147struct SwVfpRegister {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000148 bool is_valid() const { return 0 <= code_ && code_ < 32; }
149 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
150 int code() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000151 ASSERT(is_valid());
152 return code_;
153 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000154 int bit() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000155 ASSERT(is_valid());
156 return 1 << code_;
157 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000158 void split_code(int* vm, int* m) const {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000159 ASSERT(is_valid());
160 *m = code_ & 0x1;
161 *vm = code_ >> 1;
162 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000163
164 int code_;
165};
166
167
168// Double word VFP register.
169struct DwVfpRegister {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000170 // d0 has been excluded from allocation. This is following ia32
171 // where xmm0 is excluded. This should be revisited.
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000172 // Currently d0 is used as a scratch register.
173 // d1 has also been excluded from allocation to be used as a scratch
174 // register as well.
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000175 static const int kNumRegisters = 16;
176 static const int kNumAllocatableRegisters = 15;
177
178 static int ToAllocationIndex(DwVfpRegister reg) {
179 ASSERT(reg.code() != 0);
180 return reg.code() - 1;
181 }
182
183 static DwVfpRegister FromAllocationIndex(int index) {
184 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
185 return from_code(index + 1);
186 }
187
188 static const char* AllocationIndexToString(int index) {
189 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
190 const char* const names[] = {
191 "d1",
192 "d2",
193 "d3",
194 "d4",
195 "d5",
196 "d6",
197 "d7",
198 "d8",
199 "d9",
200 "d10",
201 "d11",
202 "d12",
203 "d13",
204 "d14",
205 "d15"
206 };
207 return names[index];
208 }
209
210 static DwVfpRegister from_code(int code) {
211 DwVfpRegister r = { code };
212 return r;
213 }
214
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000215 // Supporting d0 to d15, can be later extended to d31.
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000216 bool is_valid() const { return 0 <= code_ && code_ < 16; }
217 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
218 SwVfpRegister low() const {
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000219 SwVfpRegister reg;
220 reg.code_ = code_ * 2;
221
222 ASSERT(reg.is_valid());
223 return reg;
224 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000225 SwVfpRegister high() const {
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000226 SwVfpRegister reg;
227 reg.code_ = (code_ * 2) + 1;
228
229 ASSERT(reg.is_valid());
230 return reg;
231 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000232 int code() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000233 ASSERT(is_valid());
234 return code_;
235 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000236 int bit() const {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000237 ASSERT(is_valid());
238 return 1 << code_;
239 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000240 void split_code(int* vm, int* m) const {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000241 ASSERT(is_valid());
242 *m = (code_ & 0x10) >> 4;
243 *vm = code_ & 0x0F;
244 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000245
246 int code_;
247};
248
249
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000250typedef DwVfpRegister DoubleRegister;
251
252
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000253// Support for the VFP registers s0 to s31 (d0 to d15).
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000254// Note that "s(N):s(N+1)" is the same as "d(N/2)".
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000255const SwVfpRegister s0 = { 0 };
256const SwVfpRegister s1 = { 1 };
257const SwVfpRegister s2 = { 2 };
258const SwVfpRegister s3 = { 3 };
259const SwVfpRegister s4 = { 4 };
260const SwVfpRegister s5 = { 5 };
261const SwVfpRegister s6 = { 6 };
262const SwVfpRegister s7 = { 7 };
263const SwVfpRegister s8 = { 8 };
264const SwVfpRegister s9 = { 9 };
265const SwVfpRegister s10 = { 10 };
266const SwVfpRegister s11 = { 11 };
267const SwVfpRegister s12 = { 12 };
268const SwVfpRegister s13 = { 13 };
269const SwVfpRegister s14 = { 14 };
270const SwVfpRegister s15 = { 15 };
271const SwVfpRegister s16 = { 16 };
272const SwVfpRegister s17 = { 17 };
273const SwVfpRegister s18 = { 18 };
274const SwVfpRegister s19 = { 19 };
275const SwVfpRegister s20 = { 20 };
276const SwVfpRegister s21 = { 21 };
277const SwVfpRegister s22 = { 22 };
278const SwVfpRegister s23 = { 23 };
279const SwVfpRegister s24 = { 24 };
280const SwVfpRegister s25 = { 25 };
281const SwVfpRegister s26 = { 26 };
282const SwVfpRegister s27 = { 27 };
283const SwVfpRegister s28 = { 28 };
284const SwVfpRegister s29 = { 29 };
285const SwVfpRegister s30 = { 30 };
286const SwVfpRegister s31 = { 31 };
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000287
ager@chromium.org9ee27ae2011-03-02 13:43:26 +0000288const DwVfpRegister no_dreg = { -1 };
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000289const DwVfpRegister d0 = { 0 };
290const DwVfpRegister d1 = { 1 };
291const DwVfpRegister d2 = { 2 };
292const DwVfpRegister d3 = { 3 };
293const DwVfpRegister d4 = { 4 };
294const DwVfpRegister d5 = { 5 };
295const DwVfpRegister d6 = { 6 };
296const DwVfpRegister d7 = { 7 };
297const DwVfpRegister d8 = { 8 };
298const DwVfpRegister d9 = { 9 };
299const DwVfpRegister d10 = { 10 };
300const DwVfpRegister d11 = { 11 };
301const DwVfpRegister d12 = { 12 };
302const DwVfpRegister d13 = { 13 };
303const DwVfpRegister d14 = { 14 };
304const DwVfpRegister d15 = { 15 };
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000305
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306
307// Coprocessor register
308struct CRegister {
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000309 bool is_valid() const { return 0 <= code_ && code_ < 16; }
310 bool is(CRegister creg) const { return code_ == creg.code_; }
311 int code() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000312 ASSERT(is_valid());
313 return code_;
314 }
whesse@chromium.org4a1fe7d2010-09-27 12:32:04 +0000315 int bit() const {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000316 ASSERT(is_valid());
317 return 1 << code_;
318 }
319
ager@chromium.org5c838252010-02-19 08:53:10 +0000320 // Unfortunately we can't make this private in a struct.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000321 int code_;
322};
323
324
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000325const CRegister no_creg = { -1 };
326
327const CRegister cr0 = { 0 };
328const CRegister cr1 = { 1 };
329const CRegister cr2 = { 2 };
330const CRegister cr3 = { 3 };
331const CRegister cr4 = { 4 };
332const CRegister cr5 = { 5 };
333const CRegister cr6 = { 6 };
334const CRegister cr7 = { 7 };
335const CRegister cr8 = { 8 };
336const CRegister cr9 = { 9 };
337const CRegister cr10 = { 10 };
338const CRegister cr11 = { 11 };
339const CRegister cr12 = { 12 };
340const CRegister cr13 = { 13 };
341const CRegister cr14 = { 14 };
342const CRegister cr15 = { 15 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000343
344
345// Coprocessor number
346enum Coprocessor {
347 p0 = 0,
348 p1 = 1,
349 p2 = 2,
350 p3 = 3,
351 p4 = 4,
352 p5 = 5,
353 p6 = 6,
354 p7 = 7,
355 p8 = 8,
356 p9 = 9,
357 p10 = 10,
358 p11 = 11,
359 p12 = 12,
360 p13 = 13,
361 p14 = 14,
362 p15 = 15
363};
364
365
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000366// -----------------------------------------------------------------------------
367// Machine instruction Operands
368
369// Class Operand represents a shifter operand in data processing instructions
370class Operand BASE_EMBEDDED {
371 public:
372 // immediate
ager@chromium.org236ad962008-09-25 09:45:57 +0000373 INLINE(explicit Operand(int32_t immediate,
374 RelocInfo::Mode rmode = RelocInfo::NONE));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000375 INLINE(explicit Operand(const ExternalReference& f));
376 INLINE(explicit Operand(const char* s));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000377 explicit Operand(Handle<Object> handle);
378 INLINE(explicit Operand(Smi* value));
379
380 // rm
381 INLINE(explicit Operand(Register rm));
382
383 // rm <shift_op> shift_imm
384 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
385
386 // rm <shift_op> rs
387 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
388
mads.s.ager31e71382008-08-13 09:32:07 +0000389 // Return true if this is a register operand.
390 INLINE(bool is_reg() const);
391
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000392 // Return true if this operand fits in one instruction so that no
whesse@chromium.orgb08986c2011-03-14 16:13:42 +0000393 // 2-instruction solution with a load into the ip register is necessary. If
394 // the instruction this operand is used for is a MOV or MVN instruction the
395 // actual instruction to use is required for this calculation. For other
396 // instructions instr is ignored.
397 bool is_single_instruction(Instr instr = 0) const;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +0000398 bool must_use_constant_pool() const;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000399
400 inline int32_t immediate() const {
401 ASSERT(!rm_.is_valid());
402 return imm32_;
403 }
404
mads.s.ager31e71382008-08-13 09:32:07 +0000405 Register rm() const { return rm_; }
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000406 Register rs() const { return rs_; }
407 ShiftOp shift_op() const { return shift_op_; }
mads.s.ager31e71382008-08-13 09:32:07 +0000408
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000409 private:
410 Register rm_;
411 Register rs_;
412 ShiftOp shift_op_;
413 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
414 int32_t imm32_; // valid if rm_ == no_reg
ager@chromium.org236ad962008-09-25 09:45:57 +0000415 RelocInfo::Mode rmode_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416
417 friend class Assembler;
418};
419
420
421// Class MemOperand represents a memory operand in load and store instructions
422class MemOperand BASE_EMBEDDED {
423 public:
424 // [rn +/- offset] Offset/NegOffset
425 // [rn +/- offset]! PreIndex/NegPreIndex
426 // [rn], +/- offset PostIndex/NegPostIndex
427 // offset is any signed 32-bit value; offset is first loaded to register ip if
428 // it does not fit the addressing mode (12-bit unsigned and sign bit)
429 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
430
431 // [rn +/- rm] Offset/NegOffset
432 // [rn +/- rm]! PreIndex/NegPreIndex
433 // [rn], +/- rm PostIndex/NegPostIndex
434 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
435
436 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
437 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
438 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
439 explicit MemOperand(Register rn, Register rm,
440 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
441
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000442 void set_offset(int32_t offset) {
443 ASSERT(rm_.is(no_reg));
444 offset_ = offset;
445 }
446
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000447 uint32_t offset() const {
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000448 ASSERT(rm_.is(no_reg));
449 return offset_;
450 }
451
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +0000452 Register rn() const { return rn_; }
453 Register rm() const { return rm_; }
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000454
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000455 bool OffsetIsUint12Encodable() const {
456 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
457 }
458
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000459 private:
460 Register rn_; // base
461 Register rm_; // register offset
462 int32_t offset_; // valid if rm_ == no_reg
463 ShiftOp shift_op_;
464 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
465 AddrMode am_; // bits P, U, and W
466
467 friend class Assembler;
468};
469
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000470// CpuFeatures keeps track of which features are supported by the target CPU.
471// Supported features must be enabled by a Scope before use.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000472class CpuFeatures : public AllStatic {
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000473 public:
474 // Detect features of the target CPU. Set safe defaults if the serializer
475 // is enabled (snapshots must be portable).
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000476 static void Probe();
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000477
478 // Check whether a feature is supported by the target CPU.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000479 static bool IsSupported(CpuFeature f) {
480 ASSERT(initialized_);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000481 if (f == VFP3 && !FLAG_enable_vfp3) return false;
482 return (supported_ & (1u << f)) != 0;
483 }
484
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000485#ifdef DEBUG
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000486 // Check whether a feature is currently enabled.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000487 static bool IsEnabled(CpuFeature f) {
488 ASSERT(initialized_);
489 Isolate* isolate = Isolate::UncheckedCurrent();
490 if (isolate == NULL) {
491 // When no isolate is available, work as if we're running in
492 // release mode.
493 return IsSupported(f);
494 }
495 unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
496 return (enabled & (1u << f)) != 0;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000497 }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000498#endif
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000499
500 // Enable a specified feature within a scope.
501 class Scope BASE_EMBEDDED {
502#ifdef DEBUG
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000503
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000504 public:
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000505 explicit Scope(CpuFeature f) {
506 unsigned mask = 1u << f;
507 ASSERT(CpuFeatures::IsSupported(f));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000508 ASSERT(!Serializer::enabled() ||
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000509 (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
510 isolate_ = Isolate::UncheckedCurrent();
511 old_enabled_ = 0;
512 if (isolate_ != NULL) {
513 old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
514 isolate_->set_enabled_cpu_features(old_enabled_ | mask);
515 }
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000516 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000517 ~Scope() {
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000518 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
519 if (isolate_ != NULL) {
520 isolate_->set_enabled_cpu_features(old_enabled_);
521 }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000522 }
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000523
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000524 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000525 Isolate* isolate_;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000526 unsigned old_enabled_;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000527#else
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000528
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000529 public:
530 explicit Scope(CpuFeature f) {}
531#endif
532 };
533
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000534 class TryForceFeatureScope BASE_EMBEDDED {
535 public:
536 explicit TryForceFeatureScope(CpuFeature f)
537 : old_supported_(CpuFeatures::supported_) {
538 if (CanForce()) {
539 CpuFeatures::supported_ |= (1u << f);
540 }
541 }
542
543 ~TryForceFeatureScope() {
544 if (CanForce()) {
545 CpuFeatures::supported_ = old_supported_;
546 }
547 }
548
549 private:
550 static bool CanForce() {
551 // It's only safe to temporarily force support of CPU features
552 // when there's only a single isolate, which is guaranteed when
553 // the serializer is enabled.
554 return Serializer::enabled();
555 }
556
557 const unsigned old_supported_;
558 };
559
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000560 private:
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000561#ifdef DEBUG
562 static bool initialized_;
563#endif
564 static unsigned supported_;
565 static unsigned found_by_runtime_probing_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000566
567 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000568};
569
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000570
ager@chromium.org4af710e2009-09-15 12:20:11 +0000571extern const Instr kMovLrPc;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000572extern const Instr kLdrPCMask;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000573extern const Instr kLdrPCPattern;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000574extern const Instr kBlxRegMask;
575extern const Instr kBlxRegPattern;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000576
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000577extern const Instr kMovMvnMask;
578extern const Instr kMovMvnPattern;
579extern const Instr kMovMvnFlip;
580
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000581extern const Instr kMovLeaveCCMask;
582extern const Instr kMovLeaveCCPattern;
583extern const Instr kMovwMask;
584extern const Instr kMovwPattern;
585extern const Instr kMovwLeaveCCFlip;
586
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000587extern const Instr kCmpCmnMask;
588extern const Instr kCmpCmnPattern;
589extern const Instr kCmpCmnFlip;
whesse@chromium.org2c186ca2010-06-16 11:32:39 +0000590extern const Instr kAddSubFlip;
591extern const Instr kAndBicFlip;
ager@chromium.org4af710e2009-09-15 12:20:11 +0000592
ager@chromium.org378b34e2011-01-28 08:04:38 +0000593
594
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000595class Assembler : public AssemblerBase {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000596 public:
597 // Create an assembler. Instructions and relocation information are emitted
598 // into a buffer, with the instructions starting from the beginning and the
599 // relocation information starting from the end of the buffer. See CodeDesc
600 // for a detailed comment on the layout (globals.h).
601 //
602 // If the provided buffer is NULL, the assembler allocates and grows its own
603 // buffer, and buffer_size determines the initial buffer size. The buffer is
604 // owned by the assembler and deallocated upon destruction of the assembler.
605 //
606 // If the provided buffer is not NULL, the assembler uses the provided buffer
607 // for code generation and assumes its size to be buffer_size. If the buffer
608 // is too small, a fatal error occurs. No deallocation of the buffer is done
609 // upon destruction of the assembler.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000610 Assembler(Isolate* isolate, void* buffer, int buffer_size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611 ~Assembler();
612
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000613 // Overrides the default provided by FLAG_debug_code.
614 void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
615
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000616 // GetCode emits any pending (non-emitted) code and fills the descriptor
617 // desc. GetCode() is idempotent; it returns the same result if no other
ager@chromium.org32912102009-01-16 10:38:43 +0000618 // Assembler functions are invoked in between GetCode() calls.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000619 void GetCode(CodeDesc* desc);
620
621 // Label operations & relative jumps (PPUM Appendix D)
622 //
623 // Takes a branch opcode (cc) and a label (L) and generates
624 // either a backward branch or a forward branch and links it
625 // to the label fixup chain. Usage:
626 //
627 // Label L; // unbound label
628 // j(cc, &L); // forward branch to unbound label
629 // bind(&L); // bind label to the current pc
630 // j(cc, &L); // backward branch to bound label
631 // bind(&L); // illegal: a label may be bound only once
632 //
633 // Note: The same Label can be used for forward and backward branches
634 // but it may be bound only once.
635
636 void bind(Label* L); // binds an unbound label L to the current code position
637
638 // Returns the branch offset to the given label from the current code position
639 // Links the label to the current position if it is still unbound
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000640 // Manages the jump elimination optimization if the second parameter is true.
641 int branch_offset(Label* L, bool jump_elimination_allowed);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000642
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000643 // Puts a labels target address at the given position.
644 // The high 8 bits are set to zero.
645 void label_at_put(Label* L, int at_offset);
646
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 // Return the address in the constant pool of the code target address used by
648 // the branch/call instruction at pc.
649 INLINE(static Address target_address_address_at(Address pc));
650
651 // Read/Modify the code target address in the branch/call instruction at pc.
652 INLINE(static Address target_address_at(Address pc));
653 INLINE(static void set_target_address_at(Address pc, Address target));
654
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000655 // This sets the branch destination (which is in the constant pool on ARM).
656 // This is for calls and branches within generated code.
ager@chromium.org3811b432009-10-28 14:53:37 +0000657 inline static void set_target_at(Address constant_pool_entry, Address target);
658
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000659 // This sets the branch destination (which is in the constant pool on ARM).
660 // This is for calls and branches to runtime code.
661 inline static void set_external_target_at(Address constant_pool_entry,
662 Address target) {
663 set_target_at(constant_pool_entry, target);
664 }
665
ager@chromium.org3811b432009-10-28 14:53:37 +0000666 // Here we are patching the address in the constant pool, not the actual call
667 // instruction. The address in the constant pool is the same size as a
668 // pointer.
669 static const int kCallTargetSize = kPointerSize;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000670 static const int kExternalTargetSize = kPointerSize;
ager@chromium.org3811b432009-10-28 14:53:37 +0000671
ager@chromium.org4af710e2009-09-15 12:20:11 +0000672 // Size of an instruction.
673 static const int kInstrSize = sizeof(Instr);
674
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675 // Distance between the instruction referring to the address of the call
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000676 // target and the return address.
677#ifdef USE_BLX
678 // Call sequence is:
679 // ldr ip, [pc, #...] @ call address
680 // blx ip
681 // @ return address
682 static const int kCallTargetAddressOffset = 2 * kInstrSize;
683#else
684 // Call sequence is:
685 // mov lr, pc
686 // ldr pc, [pc, #...] @ call address
687 // @ return address
ager@chromium.org4af710e2009-09-15 12:20:11 +0000688 static const int kCallTargetAddressOffset = kInstrSize;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000689#endif
ager@chromium.org4af710e2009-09-15 12:20:11 +0000690
sgjesse@chromium.org911335c2009-08-19 12:59:44 +0000691 // Distance between start of patched return sequence and the emitted address
692 // to jump to.
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000693#ifdef USE_BLX
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000694 // Patched return sequence is:
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000695 // ldr ip, [pc, #0] @ emited address and start
696 // blx ip
697 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
698#else
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000699 // Patched return sequence is:
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000700 // mov lr, pc @ start of sequence
701 // ldr pc, [pc, #-4] @ emited address
702 static const int kPatchReturnSequenceAddressOffset = kInstrSize;
703#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000704
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000705 // Distance between start of patched debug break slot and the emitted address
706 // to jump to.
707#ifdef USE_BLX
708 // Patched debug break slot code is:
709 // ldr ip, [pc, #0] @ emited address and start
710 // blx ip
711 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
712#else
713 // Patched debug break slot code is:
714 // mov lr, pc @ start of sequence
715 // ldr pc, [pc, #-4] @ emited address
716 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize;
717#endif
718
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000719 // Difference between address of current opcode and value read from pc
720 // register.
721 static const int kPcLoadDelta = 8;
722
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +0000723 static const int kJSReturnSequenceInstructions = 4;
724 static const int kDebugBreakSlotInstructions = 3;
725 static const int kDebugBreakSlotLength =
726 kDebugBreakSlotInstructions * kInstrSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000727
728 // ---------------------------------------------------------------------------
729 // Code generation
730
731 // Insert the smallest number of nop instructions
732 // possible to align the pc offset to a multiple
733 // of m. m must be a power of 2 (>= 4).
734 void Align(int m);
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000735 // Aligns code to something that's optimal for a jump target for the platform.
736 void CodeTargetAlign();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000737
738 // Branch instructions
739 void b(int branch_offset, Condition cond = al);
740 void bl(int branch_offset, Condition cond = al);
741 void blx(int branch_offset); // v5 and above
742 void blx(Register target, Condition cond = al); // v5 and above
743 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
744
745 // Convenience branch instructions using labels
mads.s.ager@gmail.com769cc962008-08-06 10:02:49 +0000746 void b(Label* L, Condition cond = al) {
747 b(branch_offset(L, cond == al), cond);
748 }
749 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
750 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
751 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
752 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000753
754 // Data-processing instructions
ager@chromium.org5c838252010-02-19 08:53:10 +0000755
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000756 void and_(Register dst, Register src1, const Operand& src2,
757 SBit s = LeaveCC, Condition cond = al);
758
759 void eor(Register dst, Register src1, const Operand& src2,
760 SBit s = LeaveCC, Condition cond = al);
761
762 void sub(Register dst, Register src1, const Operand& src2,
763 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000764 void sub(Register dst, Register src1, Register src2,
765 SBit s = LeaveCC, Condition cond = al) {
766 sub(dst, src1, Operand(src2), s, cond);
767 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000768
769 void rsb(Register dst, Register src1, const Operand& src2,
770 SBit s = LeaveCC, Condition cond = al);
771
772 void add(Register dst, Register src1, const Operand& src2,
773 SBit s = LeaveCC, Condition cond = al);
sgjesse@chromium.org82dbbab2010-06-02 08:57:44 +0000774 void add(Register dst, Register src1, Register src2,
775 SBit s = LeaveCC, Condition cond = al) {
776 add(dst, src1, Operand(src2), s, cond);
777 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000778
779 void adc(Register dst, Register src1, const Operand& src2,
780 SBit s = LeaveCC, Condition cond = al);
781
782 void sbc(Register dst, Register src1, const Operand& src2,
783 SBit s = LeaveCC, Condition cond = al);
784
785 void rsc(Register dst, Register src1, const Operand& src2,
786 SBit s = LeaveCC, Condition cond = al);
787
788 void tst(Register src1, const Operand& src2, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000789 void tst(Register src1, Register src2, Condition cond = al) {
790 tst(src1, Operand(src2), cond);
791 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792
793 void teq(Register src1, const Operand& src2, Condition cond = al);
794
795 void cmp(Register src1, const Operand& src2, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000796 void cmp(Register src1, Register src2, Condition cond = al) {
797 cmp(src1, Operand(src2), cond);
798 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +0000799 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000800
801 void cmn(Register src1, const Operand& src2, Condition cond = al);
802
803 void orr(Register dst, Register src1, const Operand& src2,
804 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000805 void orr(Register dst, Register src1, Register src2,
806 SBit s = LeaveCC, Condition cond = al) {
807 orr(dst, src1, Operand(src2), s, cond);
808 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000809
810 void mov(Register dst, const Operand& src,
811 SBit s = LeaveCC, Condition cond = al);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000812 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
813 mov(dst, Operand(src), s, cond);
814 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000815
ricow@chromium.org5ad5ace2010-06-23 09:06:43 +0000816 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
817 // This may actually emit a different mov instruction, but on an ARMv7 it
818 // is guaranteed to only emit one instruction.
819 void movw(Register reg, uint32_t immediate, Condition cond = al);
820 // The constant for movt should be in the range 0-0xffff.
821 void movt(Register reg, uint32_t immediate, Condition cond = al);
822
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000823 void bic(Register dst, Register src1, const Operand& src2,
824 SBit s = LeaveCC, Condition cond = al);
825
826 void mvn(Register dst, const Operand& src,
827 SBit s = LeaveCC, Condition cond = al);
828
829 // Multiply instructions
830
831 void mla(Register dst, Register src1, Register src2, Register srcA,
832 SBit s = LeaveCC, Condition cond = al);
833
834 void mul(Register dst, Register src1, Register src2,
835 SBit s = LeaveCC, Condition cond = al);
836
837 void smlal(Register dstL, Register dstH, Register src1, Register src2,
838 SBit s = LeaveCC, Condition cond = al);
839
840 void smull(Register dstL, Register dstH, Register src1, Register src2,
841 SBit s = LeaveCC, Condition cond = al);
842
843 void umlal(Register dstL, Register dstH, Register src1, Register src2,
844 SBit s = LeaveCC, Condition cond = al);
845
846 void umull(Register dstL, Register dstH, Register src1, Register src2,
847 SBit s = LeaveCC, Condition cond = al);
848
849 // Miscellaneous arithmetic instructions
850
851 void clz(Register dst, Register src, Condition cond = al); // v5 and above
852
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000853 // Saturating instructions. v6 and above.
854
855 // Unsigned saturate.
856 //
857 // Saturate an optionally shifted signed value to an unsigned range.
858 //
859 // usat dst, #satpos, src
860 // usat dst, #satpos, src, lsl #sh
861 // usat dst, #satpos, src, asr #sh
862 //
863 // Register dst will contain:
864 //
865 // 0, if s < 0
866 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
867 // s, otherwise
868 //
869 // where s is the contents of src after shifting (if used.)
870 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
871
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000872 // Bitfield manipulation instructions. v7 and above.
873
874 void ubfx(Register dst, Register src, int lsb, int width,
875 Condition cond = al);
876
877 void sbfx(Register dst, Register src, int lsb, int width,
878 Condition cond = al);
879
880 void bfc(Register dst, int lsb, int width, Condition cond = al);
881
882 void bfi(Register dst, Register src, int lsb, int width,
883 Condition cond = al);
884
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000885 // Status register access instructions
886
887 void mrs(Register dst, SRegister s, Condition cond = al);
888 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
889
890 // Load/Store instructions
891 void ldr(Register dst, const MemOperand& src, Condition cond = al);
892 void str(Register src, const MemOperand& dst, Condition cond = al);
893 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
894 void strb(Register src, const MemOperand& dst, Condition cond = al);
895 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
896 void strh(Register src, const MemOperand& dst, Condition cond = al);
897 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
898 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000899 void ldrd(Register dst1,
900 Register dst2,
901 const MemOperand& src, Condition cond = al);
902 void strd(Register src1,
903 Register src2,
904 const MemOperand& dst, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000905
906 // Load/Store multiple instructions
907 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
908 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
909
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000910 // Exception-generating instructions and debugging support
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000911 void stop(const char* msg,
912 Condition cond = al,
913 int32_t code = kDefaultStopCode);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000914
915 void bkpt(uint32_t imm16); // v5 and above
fschneider@chromium.orge03fb642010-11-01 12:34:09 +0000916 void svc(uint32_t imm24, Condition cond = al);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000917
918 // Coprocessor instructions
919
920 void cdp(Coprocessor coproc, int opcode_1,
921 CRegister crd, CRegister crn, CRegister crm,
922 int opcode_2, Condition cond = al);
923
924 void cdp2(Coprocessor coproc, int opcode_1,
925 CRegister crd, CRegister crn, CRegister crm,
926 int opcode_2); // v5 and above
927
928 void mcr(Coprocessor coproc, int opcode_1,
929 Register rd, CRegister crn, CRegister crm,
930 int opcode_2 = 0, Condition cond = al);
931
932 void mcr2(Coprocessor coproc, int opcode_1,
933 Register rd, CRegister crn, CRegister crm,
934 int opcode_2 = 0); // v5 and above
935
936 void mrc(Coprocessor coproc, int opcode_1,
937 Register rd, CRegister crn, CRegister crm,
938 int opcode_2 = 0, Condition cond = al);
939
940 void mrc2(Coprocessor coproc, int opcode_1,
941 Register rd, CRegister crn, CRegister crm,
942 int opcode_2 = 0); // v5 and above
943
944 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
945 LFlag l = Short, Condition cond = al);
946 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
947 LFlag l = Short, Condition cond = al);
948
949 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
950 LFlag l = Short); // v5 and above
951 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
952 LFlag l = Short); // v5 and above
953
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000954 // Support for VFP.
955 // All these APIs support S0 to S31 and D0 to D15.
956 // Currently these APIs do not support extended D registers, i.e, D16 to D31.
957 // However, some simple modifications can allow
958 // these APIs to support D16 to D31.
959
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000960 void vldr(const DwVfpRegister dst,
961 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000962 int offset,
963 const Condition cond = al);
964 void vldr(const DwVfpRegister dst,
965 const MemOperand& src,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000966 const Condition cond = al);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000967
968 void vldr(const SwVfpRegister dst,
969 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000970 int offset,
971 const Condition cond = al);
972 void vldr(const SwVfpRegister dst,
973 const MemOperand& src,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000974 const Condition cond = al);
975
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000976 void vstr(const DwVfpRegister src,
977 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000978 int offset,
979 const Condition cond = al);
980 void vstr(const DwVfpRegister src,
981 const MemOperand& dst,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000982 const Condition cond = al);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000983
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000984 void vstr(const SwVfpRegister src,
985 const Register base,
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000986 int offset,
987 const Condition cond = al);
988 void vstr(const SwVfpRegister src,
989 const MemOperand& dst,
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000990 const Condition cond = al);
991
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000992 void vldm(BlockAddrMode am,
993 Register base,
994 DwVfpRegister first,
995 DwVfpRegister last,
996 Condition cond = al);
997
998 void vstm(BlockAddrMode am,
999 Register base,
1000 DwVfpRegister first,
1001 DwVfpRegister last,
1002 Condition cond = al);
1003
1004 void vldm(BlockAddrMode am,
1005 Register base,
1006 SwVfpRegister first,
1007 SwVfpRegister last,
1008 Condition cond = al);
1009
1010 void vstm(BlockAddrMode am,
1011 Register base,
1012 SwVfpRegister first,
1013 SwVfpRegister last,
1014 Condition cond = al);
1015
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001016 void vmov(const DwVfpRegister dst,
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +00001017 double imm,
1018 const Condition cond = al);
1019 void vmov(const SwVfpRegister dst,
1020 const SwVfpRegister src,
1021 const Condition cond = al);
1022 void vmov(const DwVfpRegister dst,
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001023 const DwVfpRegister src,
1024 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001025 void vmov(const DwVfpRegister dst,
1026 const Register src1,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001027 const Register src2,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001028 const Condition cond = al);
1029 void vmov(const Register dst1,
1030 const Register dst2,
1031 const DwVfpRegister src,
1032 const Condition cond = al);
1033 void vmov(const SwVfpRegister dst,
1034 const Register src,
1035 const Condition cond = al);
1036 void vmov(const Register dst,
1037 const SwVfpRegister src,
1038 const Condition cond = al);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001039 void vcvt_f64_s32(const DwVfpRegister dst,
1040 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001041 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001042 const Condition cond = al);
1043 void vcvt_f32_s32(const SwVfpRegister dst,
1044 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001045 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001046 const Condition cond = al);
1047 void vcvt_f64_u32(const DwVfpRegister dst,
1048 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001049 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001050 const Condition cond = al);
1051 void vcvt_s32_f64(const SwVfpRegister dst,
1052 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001053 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001054 const Condition cond = al);
1055 void vcvt_u32_f64(const SwVfpRegister dst,
1056 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001057 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001058 const Condition cond = al);
1059 void vcvt_f64_f32(const DwVfpRegister dst,
1060 const SwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001061 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001062 const Condition cond = al);
1063 void vcvt_f32_f64(const SwVfpRegister dst,
1064 const DwVfpRegister src,
ricow@chromium.org83aa5492011-02-07 12:42:56 +00001065 VFPConversionMode mode = kDefaultRoundToZero,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +00001066 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001067
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001068 void vneg(const DwVfpRegister dst,
1069 const DwVfpRegister src,
1070 const Condition cond = al);
whesse@chromium.org7a392b32011-01-31 11:30:36 +00001071 void vabs(const DwVfpRegister dst,
1072 const DwVfpRegister src,
1073 const Condition cond = al);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +00001074 void vadd(const DwVfpRegister dst,
1075 const DwVfpRegister src1,
1076 const DwVfpRegister src2,
1077 const Condition cond = al);
1078 void vsub(const DwVfpRegister dst,
1079 const DwVfpRegister src1,
1080 const DwVfpRegister src2,
1081 const Condition cond = al);
1082 void vmul(const DwVfpRegister dst,
1083 const DwVfpRegister src1,
1084 const DwVfpRegister src2,
1085 const Condition cond = al);
1086 void vdiv(const DwVfpRegister dst,
1087 const DwVfpRegister src1,
1088 const DwVfpRegister src2,
1089 const Condition cond = al);
1090 void vcmp(const DwVfpRegister src1,
1091 const DwVfpRegister src2,
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001092 const Condition cond = al);
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001093 void vcmp(const DwVfpRegister src1,
1094 const double src2,
ager@chromium.orgea4f62e2010-08-16 16:28:43 +00001095 const Condition cond = al);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001096 void vmrs(const Register dst,
1097 const Condition cond = al);
ager@chromium.org01fe7df2010-11-10 11:59:11 +00001098 void vmsr(const Register dst,
1099 const Condition cond = al);
lrn@chromium.org32d961d2010-06-30 09:09:34 +00001100 void vsqrt(const DwVfpRegister dst,
1101 const DwVfpRegister src,
1102 const Condition cond = al);
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001103
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001104 // Pseudo instructions
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001105
1106 // Different nop operations are used by the code generator to detect certain
1107 // states of the generated code.
1108 enum NopMarkerTypes {
1109 NON_MARKING_NOP = 0,
1110 DEBUG_BREAK_NOP,
1111 // IC markers.
1112 PROPERTY_ACCESS_INLINED,
1113 PROPERTY_ACCESS_INLINED_CONTEXT,
1114 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1115 // Helper values.
1116 LAST_CODE_MARKER,
1117 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1118 };
1119
1120 void nop(int type = 0); // 0 is the default non-marking type.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001121
kasperl@chromium.orgb3284ad2009-05-18 06:12:45 +00001122 void push(Register src, Condition cond = al) {
1123 str(src, MemOperand(sp, 4, NegPreIndex), cond);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001124 }
1125
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +00001126 void pop(Register dst, Condition cond = al) {
1127 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
mads.s.ager31e71382008-08-13 09:32:07 +00001128 }
1129
1130 void pop() {
1131 add(sp, sp, Operand(kPointerSize));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001132 }
1133
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001134 // Jump unconditionally to given label.
1135 void jmp(Label* L) { b(L, al); }
1136
ager@chromium.org4af710e2009-09-15 12:20:11 +00001137 // Check the code size generated from label to here.
1138 int InstructionsGeneratedSince(Label* l) {
1139 return (pc_offset() - l->pos()) / kInstrSize;
1140 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001141
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001142 // Check whether an immediate fits an addressing mode 1 instruction.
1143 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1144
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001145 // Class for scoping postponing the constant pool generation.
1146 class BlockConstPoolScope {
1147 public:
1148 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1149 assem_->StartBlockConstPool();
1150 }
1151 ~BlockConstPoolScope() {
1152 assem_->EndBlockConstPool();
1153 }
1154
1155 private:
1156 Assembler* assem_;
1157
1158 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1159 };
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001160
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001161 // Postpone the generation of the constant pool for the specified number of
1162 // instructions.
1163 void BlockConstPoolFor(int instructions);
1164
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001165 // Debugging
1166
ager@chromium.org4af710e2009-09-15 12:20:11 +00001167 // Mark address of the ExitJSFrame code.
1168 void RecordJSReturn();
1169
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001170 // Mark address of a debug break slot.
1171 void RecordDebugBreakSlot();
1172
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001173 // Record the AST id of the CallIC being compiled, so that it can be placed
1174 // in the relocation information.
1175 void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; }
1176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001177 // Record a comment relocation entry that can be used by a disassembler.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001178 // Use --code-comments to enable.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001179 void RecordComment(const char* msg);
1180
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001181 // Writes a single byte or word of data in the code stream. Used
1182 // for inline tables, e.g., jump-tables. The constant pool should be
1183 // emitted before any use of db and dd to ensure that constant pools
1184 // are not emitted as part of the tables generated.
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001185 void db(uint8_t data);
1186 void dd(uint32_t data);
1187
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001188 int pc_offset() const { return pc_ - buffer_; }
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001189
1190 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001191
1192 // Read/patch instructions
1193 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1194 static void instr_at_put(byte* pc, Instr instr) {
1195 *reinterpret_cast<Instr*>(pc) = instr;
1196 }
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001197 static Condition GetCondition(Instr instr);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001198 static bool IsBranch(Instr instr);
1199 static int GetBranchOffset(Instr instr);
1200 static bool IsLdrRegisterImmediate(Instr instr);
1201 static int GetLdrRegisterImmediateOffset(Instr instr);
1202 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
whesse@chromium.orgba5a61b2010-07-26 11:44:40 +00001203 static bool IsStrRegisterImmediate(Instr instr);
1204 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1205 static bool IsAddRegisterImmediate(Instr instr);
1206 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001207 static Register GetRd(Instr instr);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001208 static Register GetRn(Instr instr);
1209 static Register GetRm(Instr instr);
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +00001210 static bool IsPush(Instr instr);
1211 static bool IsPop(Instr instr);
1212 static bool IsStrRegFpOffset(Instr instr);
1213 static bool IsLdrRegFpOffset(Instr instr);
1214 static bool IsStrRegFpNegOffset(Instr instr);
1215 static bool IsLdrRegFpNegOffset(Instr instr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001216 static bool IsLdrPcImmediateOffset(Instr instr);
sgjesse@chromium.org496c03a2011-02-14 12:05:43 +00001217 static bool IsTstImmediate(Instr instr);
1218 static bool IsCmpRegister(Instr instr);
1219 static bool IsCmpImmediate(Instr instr);
1220 static Register GetCmpImmediateRegister(Instr instr);
1221 static int GetCmpImmediateRawImmediate(Instr instr);
ager@chromium.orgbeb25712010-11-29 08:02:25 +00001222 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001223
danno@chromium.org40cb8782011-05-25 07:58:50 +00001224 // Buffer size and constant pool distance are checked together at regular
1225 // intervals of kBufferCheckInterval emitted bytes
1226 static const int kBufferCheckInterval = 1*KB/2;
1227 // Constants in pools are accessed via pc relative addressing, which can
1228 // reach +/-4KB thereby defining a maximum distance between the instruction
1229 // and the accessed constant. We satisfy this constraint by limiting the
1230 // distance between pools.
1231 static const int kMaxDistBetweenPools = 4*KB - 2*kBufferCheckInterval;
1232 static const int kMaxNumPRInfo = kMaxDistBetweenPools/kInstrSize;
1233
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001234 // Check if is time to emit a constant pool for pending reloc info entries
1235 void CheckConstPool(bool force_emit, bool require_jump);
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001236
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001237 protected:
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +00001238 // Relocation for a type-recording IC has the AST id added to it. This
1239 // member variable is a way to pass the information from the call site to
1240 // the relocation info.
1241 unsigned ast_id_for_reloc_info_;
1242
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001243 bool emit_debug_code() const { return emit_debug_code_; }
1244
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001245 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1246
1247 // Read/patch instructions
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001248 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1249 void instr_at_put(int pos, Instr instr) {
1250 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1251 }
1252
1253 // Decode branch instruction at pos and return branch target pos
1254 int target_at(int pos);
1255
1256 // Patch branch instruction at pos to branch to given branch target pos
1257 void target_at_put(int pos, int target_pos);
1258
ager@chromium.org8bb60582008-12-11 12:02:20 +00001259 // Block the emission of the constant pool before pc_offset
1260 void BlockConstPoolBefore(int pc_offset) {
1261 if (no_const_pool_before_ < pc_offset) no_const_pool_before_ = pc_offset;
1262 }
1263
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001264 void StartBlockConstPool() {
1265 const_pool_blocked_nesting_++;
1266 }
1267 void EndBlockConstPool() {
1268 const_pool_blocked_nesting_--;
1269 }
fschneider@chromium.org40b9da32010-06-28 11:29:21 +00001270 bool is_const_pool_blocked() const { return const_pool_blocked_nesting_ > 0; }
lrn@chromium.orgc34f5802010-04-28 12:53:43 +00001271
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001272 private:
1273 // Code buffer:
1274 // The buffer into which code and relocation info are generated.
1275 byte* buffer_;
1276 int buffer_size_;
1277 // True if the assembler owns the buffer, false if buffer is external.
1278 bool own_buffer_;
1279
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001280 int next_buffer_check_; // pc offset of next buffer check
1281
1282 // Code generation
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001283 // The relocation writer's position is at least kGap bytes below the end of
1284 // the generated instructions. This is so that multi-instruction sequences do
1285 // not have to check for overflow. The same is true for writes of large
1286 // relocation info entries.
1287 static const int kGap = 32;
1288 byte* pc_; // the program counter; moves forward
1289
1290 // Constant pool generation
1291 // Pools are emitted in the instruction stream, preferably after unconditional
1292 // jumps or after returns from functions (in dead code locations).
1293 // If a long code sequence does not contain unconditional jumps, it is
1294 // necessary to emit the constant pool before the pool gets too far from the
1295 // location it is accessed from. In this case, we emit a jump over the emitted
1296 // constant pool.
1297 // Constants in the pool may be addresses of functions that gets relocated;
1298 // if so, a relocation info entry is associated to the constant pool entry.
1299
1300 // Repeated checking whether the constant pool should be emitted is rather
1301 // expensive. By default we only check again once a number of instructions
1302 // has been generated. That also means that the sizing of the buffers is not
1303 // an exact science, and that we rely on some slop to not overrun buffers.
1304 static const int kCheckConstIntervalInst = 32;
1305 static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
1306
1307
1308 // Pools are emitted after function return and in dead code at (more or less)
1309 // regular intervals of kDistBetweenPools bytes
1310 static const int kDistBetweenPools = 1*KB;
1311
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001312 // Emission of the constant pool may be blocked in some code sequences.
1313 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1314 int no_const_pool_before_; // Block emission before this pc offset.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001315
1316 // Keep track of the last emitted pool to guarantee a maximal distance
1317 int last_const_pool_end_; // pc offset following the last constant pool
1318
1319 // Relocation info generation
1320 // Each relocation is encoded as a variable size value
1321 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1322 RelocInfoWriter reloc_info_writer;
1323 // Relocation info records are also used during code generation as temporary
1324 // containers for constants and code target addresses until they are emitted
1325 // to the constant pool. These pending relocation info records are temporarily
1326 // stored in a separate buffer until a constant pool is emitted.
1327 // If every instruction in a long sequence is accessing the pool, we need one
1328 // pending relocation entry per instruction.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329 RelocInfo prinfo_[kMaxNumPRInfo]; // the buffer of pending relocation info
1330 int num_prinfo_; // number of pending reloc info entries in the buffer
1331
kasperl@chromium.org41044eb2008-10-06 08:24:46 +00001332 // The bound position, before this we cannot do instruction elimination.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001333 int last_bound_pos_;
1334
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001335 // Code emission
1336 inline void CheckBuffer();
1337 void GrowBuffer();
1338 inline void emit(Instr x);
1339
1340 // Instruction generation
1341 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1342 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1343 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1344 void addrmod4(Instr instr, Register rn, RegList rl);
1345 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1346
1347 // Labels
1348 void print(Label* L);
1349 void bind_to(Label* L, int pos);
1350 void link_to(Label* L, Label* appendix);
1351 void next(Label* L);
1352
1353 // Record reloc info for current pc_
ager@chromium.org236ad962008-09-25 09:45:57 +00001354 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
ager@chromium.org18ad94b2009-09-02 08:22:29 +00001355
1356 friend class RegExpMacroAssemblerARM;
ager@chromium.org4af710e2009-09-15 12:20:11 +00001357 friend class RelocInfo;
1358 friend class CodePatcher;
fschneider@chromium.org013f3e12010-04-26 13:27:52 +00001359 friend class BlockConstPoolScope;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001360
1361 PositionsRecorder positions_recorder_;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001362 bool emit_debug_code_;
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001363 friend class PositionsRecorder;
1364 friend class EnsureSpace;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001365};
1366
whesse@chromium.orgf0ac72d2010-11-08 12:47:26 +00001367
1368class EnsureSpace BASE_EMBEDDED {
1369 public:
1370 explicit EnsureSpace(Assembler* assembler) {
1371 assembler->CheckBuffer();
1372 }
1373};
1374
1375
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001376} } // namespace v8::internal
1377
ager@chromium.org5ec48922009-05-05 07:25:34 +00001378#endif // V8_ARM_ASSEMBLER_ARM_H_