blob: e2d5f598b78422bb69852cf86a42672ccac62f8f [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +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
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.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// 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
Leon Clarked91b9f72010-01-27 17:25:45 +000033// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
Ben Murdoch692be652012-01-10 18:47:50 +000035// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +000036
37// A light-weight ARM Assembler
38// Generates user mode instructions for the ARM architecture up to version 5
39
40#ifndef V8_ARM_ASSEMBLER_ARM_H_
41#define V8_ARM_ASSEMBLER_ARM_H_
42#include <stdio.h>
43#include "assembler.h"
Steve Block1e0659c2011-05-24 12:43:12 +010044#include "constants-arm.h"
Steve Blockd0582a62009-12-15 09:54:21 +000045#include "serialize.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000046
47namespace v8 {
48namespace internal {
49
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.
Steve Block9fac8402011-05-12 15:51:54 +010070
Steve Blocka7e24c12009-10-30 11:49:00 +000071// Core register
72struct Register {
Ben Murdochb0fe1622011-05-05 13:52:32 +010073 static const int kNumRegisters = 16;
74 static const int kNumAllocatableRegisters = 8;
Ben Murdoch257744e2011-11-30 15:57:28 +000075 static const int kSizeInBytes = 4;
Ben Murdochb0fe1622011-05-05 13:52:32 +010076
77 static int ToAllocationIndex(Register reg) {
Steve Block9fac8402011-05-12 15:51:54 +010078 ASSERT(reg.code() < kNumAllocatableRegisters);
Ben Murdochb0fe1622011-05-05 13:52:32 +010079 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; }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100108 bool is(Register reg) const { return code_ == reg.code_; }
109 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000110 ASSERT(is_valid());
111 return code_;
112 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100113 int bit() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000114 ASSERT(is_valid());
115 return 1 << code_;
116 }
117
Leon Clarkef7060e22010-06-03 12:02:55 +0100118 void set_code(int code) {
119 code_ = code;
120 ASSERT(is_valid());
121 }
122
Andrei Popescu31002712010-02-23 13:46:05 +0000123 // Unfortunately we can't make this private in a struct.
Steve Blocka7e24c12009-10-30 11:49:00 +0000124 int code_;
125};
126
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100127// These constants are used in several locations, including static initializers
128const int kRegister_no_reg_Code = -1;
129const int kRegister_r0_Code = 0;
130const int kRegister_r1_Code = 1;
131const int kRegister_r2_Code = 2;
132const int kRegister_r3_Code = 3;
133const int kRegister_r4_Code = 4;
134const int kRegister_r5_Code = 5;
135const int kRegister_r6_Code = 6;
136const int kRegister_r7_Code = 7;
137const int kRegister_r8_Code = 8;
138const int kRegister_r9_Code = 9;
139const int kRegister_r10_Code = 10;
140const int kRegister_fp_Code = 11;
141const int kRegister_ip_Code = 12;
142const int kRegister_sp_Code = 13;
143const int kRegister_lr_Code = 14;
144const int kRegister_pc_Code = 15;
Steve Blocka7e24c12009-10-30 11:49:00 +0000145
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100146const Register no_reg = { kRegister_no_reg_Code };
147
148const Register r0 = { kRegister_r0_Code };
149const Register r1 = { kRegister_r1_Code };
150const Register r2 = { kRegister_r2_Code };
151const Register r3 = { kRegister_r3_Code };
152const Register r4 = { kRegister_r4_Code };
153const Register r5 = { kRegister_r5_Code };
154const Register r6 = { kRegister_r6_Code };
155const Register r7 = { kRegister_r7_Code };
156// Used as context register.
157const Register r8 = { kRegister_r8_Code };
158// Used as lithium codegen scratch register.
159const Register r9 = { kRegister_r9_Code };
160// Used as roots register.
161const Register r10 = { kRegister_r10_Code };
162const Register fp = { kRegister_fp_Code };
163const Register ip = { kRegister_ip_Code };
164const Register sp = { kRegister_sp_Code };
165const Register lr = { kRegister_lr_Code };
166const Register pc = { kRegister_pc_Code };
167
Steve Blockd0582a62009-12-15 09:54:21 +0000168
Leon Clarkee46be812010-01-19 14:06:41 +0000169// Single word VFP register.
170struct SwVfpRegister {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100171 bool is_valid() const { return 0 <= code_ && code_ < 32; }
172 bool is(SwVfpRegister reg) const { return code_ == reg.code_; }
173 int code() const {
Leon Clarkee46be812010-01-19 14:06:41 +0000174 ASSERT(is_valid());
175 return code_;
176 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100177 int bit() const {
Leon Clarkee46be812010-01-19 14:06:41 +0000178 ASSERT(is_valid());
179 return 1 << code_;
180 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100181 void split_code(int* vm, int* m) const {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100182 ASSERT(is_valid());
183 *m = code_ & 0x1;
184 *vm = code_ >> 1;
185 }
Leon Clarkee46be812010-01-19 14:06:41 +0000186
187 int code_;
188};
189
190
191// Double word VFP register.
192struct DwVfpRegister {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100193 static const int kNumRegisters = 16;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000194 // A few double registers are reserved: one as a scratch register and one to
195 // hold 0.0, that does not fit in the immediate field of vmov instructions.
196 // d14: 0.0
197 // d15: scratch register.
198 static const int kNumReservedRegisters = 2;
199 static const int kNumAllocatableRegisters = kNumRegisters -
200 kNumReservedRegisters;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100201
Ben Murdoch692be652012-01-10 18:47:50 +0000202 inline static int ToAllocationIndex(DwVfpRegister reg);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100203
204 static DwVfpRegister FromAllocationIndex(int index) {
205 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
Ben Murdoch692be652012-01-10 18:47:50 +0000206 return from_code(index);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100207 }
208
209 static const char* AllocationIndexToString(int index) {
210 ASSERT(index >= 0 && index < kNumAllocatableRegisters);
211 const char* const names[] = {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000212 "d0",
Ben Murdochb0fe1622011-05-05 13:52:32 +0100213 "d1",
214 "d2",
215 "d3",
216 "d4",
217 "d5",
218 "d6",
219 "d7",
220 "d8",
221 "d9",
222 "d10",
223 "d11",
224 "d12",
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000225 "d13"
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226 };
227 return names[index];
228 }
229
230 static DwVfpRegister from_code(int code) {
231 DwVfpRegister r = { code };
232 return r;
233 }
234
Leon Clarkee46be812010-01-19 14:06:41 +0000235 // Supporting d0 to d15, can be later extended to d31.
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100236 bool is_valid() const { return 0 <= code_ && code_ < 16; }
237 bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
238 SwVfpRegister low() const {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100239 SwVfpRegister reg;
240 reg.code_ = code_ * 2;
241
242 ASSERT(reg.is_valid());
243 return reg;
244 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100245 SwVfpRegister high() const {
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100246 SwVfpRegister reg;
247 reg.code_ = (code_ * 2) + 1;
248
249 ASSERT(reg.is_valid());
250 return reg;
251 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100252 int code() const {
Leon Clarkee46be812010-01-19 14:06:41 +0000253 ASSERT(is_valid());
254 return code_;
255 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100256 int bit() const {
Leon Clarkee46be812010-01-19 14:06:41 +0000257 ASSERT(is_valid());
258 return 1 << code_;
259 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100260 void split_code(int* vm, int* m) const {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100261 ASSERT(is_valid());
262 *m = (code_ & 0x10) >> 4;
263 *vm = code_ & 0x0F;
264 }
Leon Clarkee46be812010-01-19 14:06:41 +0000265
266 int code_;
267};
268
269
Ben Murdochb0fe1622011-05-05 13:52:32 +0100270typedef DwVfpRegister DoubleRegister;
271
272
Steve Block6ded16b2010-05-10 14:33:55 +0100273// Support for the VFP registers s0 to s31 (d0 to d15).
Leon Clarkee46be812010-01-19 14:06:41 +0000274// Note that "s(N):s(N+1)" is the same as "d(N/2)".
Steve Block6ded16b2010-05-10 14:33:55 +0100275const SwVfpRegister s0 = { 0 };
276const SwVfpRegister s1 = { 1 };
277const SwVfpRegister s2 = { 2 };
278const SwVfpRegister s3 = { 3 };
279const SwVfpRegister s4 = { 4 };
280const SwVfpRegister s5 = { 5 };
281const SwVfpRegister s6 = { 6 };
282const SwVfpRegister s7 = { 7 };
283const SwVfpRegister s8 = { 8 };
284const SwVfpRegister s9 = { 9 };
285const SwVfpRegister s10 = { 10 };
286const SwVfpRegister s11 = { 11 };
287const SwVfpRegister s12 = { 12 };
288const SwVfpRegister s13 = { 13 };
289const SwVfpRegister s14 = { 14 };
290const SwVfpRegister s15 = { 15 };
291const SwVfpRegister s16 = { 16 };
292const SwVfpRegister s17 = { 17 };
293const SwVfpRegister s18 = { 18 };
294const SwVfpRegister s19 = { 19 };
295const SwVfpRegister s20 = { 20 };
296const SwVfpRegister s21 = { 21 };
297const SwVfpRegister s22 = { 22 };
298const SwVfpRegister s23 = { 23 };
299const SwVfpRegister s24 = { 24 };
300const SwVfpRegister s25 = { 25 };
301const SwVfpRegister s26 = { 26 };
302const SwVfpRegister s27 = { 27 };
303const SwVfpRegister s28 = { 28 };
304const SwVfpRegister s29 = { 29 };
305const SwVfpRegister s30 = { 30 };
306const SwVfpRegister s31 = { 31 };
Leon Clarkee46be812010-01-19 14:06:41 +0000307
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100308const DwVfpRegister no_dreg = { -1 };
Steve Block6ded16b2010-05-10 14:33:55 +0100309const DwVfpRegister d0 = { 0 };
310const DwVfpRegister d1 = { 1 };
311const DwVfpRegister d2 = { 2 };
312const DwVfpRegister d3 = { 3 };
313const DwVfpRegister d4 = { 4 };
314const DwVfpRegister d5 = { 5 };
315const DwVfpRegister d6 = { 6 };
316const DwVfpRegister d7 = { 7 };
317const DwVfpRegister d8 = { 8 };
318const DwVfpRegister d9 = { 9 };
319const DwVfpRegister d10 = { 10 };
320const DwVfpRegister d11 = { 11 };
321const DwVfpRegister d12 = { 12 };
322const DwVfpRegister d13 = { 13 };
323const DwVfpRegister d14 = { 14 };
324const DwVfpRegister d15 = { 15 };
Leon Clarkee46be812010-01-19 14:06:41 +0000325
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100326// Aliases for double registers. Defined using #define instead of
327// "static const DwVfpRegister&" because Clang complains otherwise when a
328// compilation unit that includes this header doesn't use the variables.
329#define kFirstCalleeSavedDoubleReg d8
330#define kLastCalleeSavedDoubleReg d15
331#define kDoubleRegZero d14
332#define kScratchDoubleReg d15
Ben Murdoch7d3e7fc2011-07-12 16:37:06 +0100333
Steve Blocka7e24c12009-10-30 11:49:00 +0000334
335// Coprocessor register
336struct CRegister {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100337 bool is_valid() const { return 0 <= code_ && code_ < 16; }
338 bool is(CRegister creg) const { return code_ == creg.code_; }
339 int code() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000340 ASSERT(is_valid());
341 return code_;
342 }
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100343 int bit() const {
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 ASSERT(is_valid());
345 return 1 << code_;
346 }
347
Andrei Popescu31002712010-02-23 13:46:05 +0000348 // Unfortunately we can't make this private in a struct.
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 int code_;
350};
351
352
Steve Block6ded16b2010-05-10 14:33:55 +0100353const CRegister no_creg = { -1 };
354
355const CRegister cr0 = { 0 };
356const CRegister cr1 = { 1 };
357const CRegister cr2 = { 2 };
358const CRegister cr3 = { 3 };
359const CRegister cr4 = { 4 };
360const CRegister cr5 = { 5 };
361const CRegister cr6 = { 6 };
362const CRegister cr7 = { 7 };
363const CRegister cr8 = { 8 };
364const CRegister cr9 = { 9 };
365const CRegister cr10 = { 10 };
366const CRegister cr11 = { 11 };
367const CRegister cr12 = { 12 };
368const CRegister cr13 = { 13 };
369const CRegister cr14 = { 14 };
370const CRegister cr15 = { 15 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000371
372
373// Coprocessor number
374enum Coprocessor {
375 p0 = 0,
376 p1 = 1,
377 p2 = 2,
378 p3 = 3,
379 p4 = 4,
380 p5 = 5,
381 p6 = 6,
382 p7 = 7,
383 p8 = 8,
384 p9 = 9,
385 p10 = 10,
386 p11 = 11,
387 p12 = 12,
388 p13 = 13,
389 p14 = 14,
390 p15 = 15
391};
392
393
Steve Blocka7e24c12009-10-30 11:49:00 +0000394// -----------------------------------------------------------------------------
395// Machine instruction Operands
396
397// Class Operand represents a shifter operand in data processing instructions
398class Operand BASE_EMBEDDED {
399 public:
400 // immediate
401 INLINE(explicit Operand(int32_t immediate,
402 RelocInfo::Mode rmode = RelocInfo::NONE));
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000403 INLINE(static Operand Zero()) {
404 return Operand(static_cast<int32_t>(0));
405 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000406 INLINE(explicit Operand(const ExternalReference& f));
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 explicit Operand(Handle<Object> handle);
408 INLINE(explicit Operand(Smi* value));
409
410 // rm
411 INLINE(explicit Operand(Register rm));
412
413 // rm <shift_op> shift_imm
414 explicit Operand(Register rm, ShiftOp shift_op, int shift_imm);
415
416 // rm <shift_op> rs
417 explicit Operand(Register rm, ShiftOp shift_op, Register rs);
418
419 // Return true if this is a register operand.
420 INLINE(bool is_reg() const);
421
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100422 // Return true if this operand fits in one instruction so that no
Steve Block44f0eee2011-05-26 01:26:41 +0100423 // 2-instruction solution with a load into the ip register is necessary. If
424 // the instruction this operand is used for is a MOV or MVN instruction the
425 // actual instruction to use is required for this calculation. For other
426 // instructions instr is ignored.
427 bool is_single_instruction(Instr instr = 0) const;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800428 bool must_use_constant_pool() const;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100429
430 inline int32_t immediate() const {
431 ASSERT(!rm_.is_valid());
432 return imm32_;
433 }
434
Steve Blocka7e24c12009-10-30 11:49:00 +0000435 Register rm() const { return rm_; }
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100436 Register rs() const { return rs_; }
437 ShiftOp shift_op() const { return shift_op_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000438
439 private:
440 Register rm_;
441 Register rs_;
442 ShiftOp shift_op_;
443 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
444 int32_t imm32_; // valid if rm_ == no_reg
445 RelocInfo::Mode rmode_;
446
447 friend class Assembler;
448};
449
450
451// Class MemOperand represents a memory operand in load and store instructions
452class MemOperand BASE_EMBEDDED {
453 public:
454 // [rn +/- offset] Offset/NegOffset
455 // [rn +/- offset]! PreIndex/NegPreIndex
456 // [rn], +/- offset PostIndex/NegPostIndex
457 // offset is any signed 32-bit value; offset is first loaded to register ip if
458 // it does not fit the addressing mode (12-bit unsigned and sign bit)
459 explicit MemOperand(Register rn, int32_t offset = 0, AddrMode am = Offset);
460
461 // [rn +/- rm] Offset/NegOffset
462 // [rn +/- rm]! PreIndex/NegPreIndex
463 // [rn], +/- rm PostIndex/NegPostIndex
464 explicit MemOperand(Register rn, Register rm, AddrMode am = Offset);
465
466 // [rn +/- rm <shift_op> shift_imm] Offset/NegOffset
467 // [rn +/- rm <shift_op> shift_imm]! PreIndex/NegPreIndex
468 // [rn], +/- rm <shift_op> shift_imm PostIndex/NegPostIndex
469 explicit MemOperand(Register rn, Register rm,
470 ShiftOp shift_op, int shift_imm, AddrMode am = Offset);
471
Kristian Monsen25f61362010-05-21 11:50:48 +0100472 void set_offset(int32_t offset) {
473 ASSERT(rm_.is(no_reg));
474 offset_ = offset;
475 }
476
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100477 uint32_t offset() const {
Kristian Monsen25f61362010-05-21 11:50:48 +0100478 ASSERT(rm_.is(no_reg));
479 return offset_;
480 }
481
Leon Clarkef7060e22010-06-03 12:02:55 +0100482 Register rn() const { return rn_; }
483 Register rm() const { return rm_; }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000484 AddrMode am() const { return am_; }
Kristian Monsen25f61362010-05-21 11:50:48 +0100485
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100486 bool OffsetIsUint12Encodable() const {
487 return offset_ >= 0 ? is_uint12(offset_) : is_uint12(-offset_);
488 }
489
Steve Blocka7e24c12009-10-30 11:49:00 +0000490 private:
491 Register rn_; // base
492 Register rm_; // register offset
493 int32_t offset_; // valid if rm_ == no_reg
494 ShiftOp shift_op_;
495 int shift_imm_; // valid if rm_ != no_reg && rs_ == no_reg
496 AddrMode am_; // bits P, U, and W
497
498 friend class Assembler;
499};
500
Steve Blockd0582a62009-12-15 09:54:21 +0000501// CpuFeatures keeps track of which features are supported by the target CPU.
502// Supported features must be enabled by a Scope before use.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100503class CpuFeatures : public AllStatic {
Steve Blockd0582a62009-12-15 09:54:21 +0000504 public:
505 // Detect features of the target CPU. Set safe defaults if the serializer
506 // is enabled (snapshots must be portable).
Ben Murdoch8b112d22011-06-08 16:22:53 +0100507 static void Probe();
Steve Blockd0582a62009-12-15 09:54:21 +0000508
509 // Check whether a feature is supported by the target CPU.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100510 static bool IsSupported(CpuFeature f) {
511 ASSERT(initialized_);
Steve Blockd0582a62009-12-15 09:54:21 +0000512 if (f == VFP3 && !FLAG_enable_vfp3) return false;
513 return (supported_ & (1u << f)) != 0;
514 }
515
Ben Murdoch8b112d22011-06-08 16:22:53 +0100516#ifdef DEBUG
Steve Blockd0582a62009-12-15 09:54:21 +0000517 // Check whether a feature is currently enabled.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100518 static bool IsEnabled(CpuFeature f) {
519 ASSERT(initialized_);
520 Isolate* isolate = Isolate::UncheckedCurrent();
521 if (isolate == NULL) {
522 // When no isolate is available, work as if we're running in
523 // release mode.
524 return IsSupported(f);
525 }
526 unsigned enabled = static_cast<unsigned>(isolate->enabled_cpu_features());
527 return (enabled & (1u << f)) != 0;
Steve Blockd0582a62009-12-15 09:54:21 +0000528 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100529#endif
Steve Blockd0582a62009-12-15 09:54:21 +0000530
531 // Enable a specified feature within a scope.
532 class Scope BASE_EMBEDDED {
533#ifdef DEBUG
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000534
Steve Blockd0582a62009-12-15 09:54:21 +0000535 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100536 explicit Scope(CpuFeature f) {
537 unsigned mask = 1u << f;
538 ASSERT(CpuFeatures::IsSupported(f));
Steve Blockd0582a62009-12-15 09:54:21 +0000539 ASSERT(!Serializer::enabled() ||
Ben Murdoch8b112d22011-06-08 16:22:53 +0100540 (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
541 isolate_ = Isolate::UncheckedCurrent();
542 old_enabled_ = 0;
543 if (isolate_ != NULL) {
544 old_enabled_ = static_cast<unsigned>(isolate_->enabled_cpu_features());
545 isolate_->set_enabled_cpu_features(old_enabled_ | mask);
546 }
Steve Blockd0582a62009-12-15 09:54:21 +0000547 }
Steve Block44f0eee2011-05-26 01:26:41 +0100548 ~Scope() {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100549 ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
550 if (isolate_ != NULL) {
551 isolate_->set_enabled_cpu_features(old_enabled_);
552 }
Steve Block44f0eee2011-05-26 01:26:41 +0100553 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000554
Steve Blockd0582a62009-12-15 09:54:21 +0000555 private:
Steve Block44f0eee2011-05-26 01:26:41 +0100556 Isolate* isolate_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100557 unsigned old_enabled_;
Steve Blockd0582a62009-12-15 09:54:21 +0000558#else
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000559
Steve Blockd0582a62009-12-15 09:54:21 +0000560 public:
561 explicit Scope(CpuFeature f) {}
562#endif
563 };
564
Ben Murdoch8b112d22011-06-08 16:22:53 +0100565 class TryForceFeatureScope BASE_EMBEDDED {
566 public:
567 explicit TryForceFeatureScope(CpuFeature f)
568 : old_supported_(CpuFeatures::supported_) {
569 if (CanForce()) {
570 CpuFeatures::supported_ |= (1u << f);
571 }
572 }
573
574 ~TryForceFeatureScope() {
575 if (CanForce()) {
576 CpuFeatures::supported_ = old_supported_;
577 }
578 }
579
580 private:
581 static bool CanForce() {
582 // It's only safe to temporarily force support of CPU features
583 // when there's only a single isolate, which is guaranteed when
584 // the serializer is enabled.
585 return Serializer::enabled();
586 }
587
588 const unsigned old_supported_;
589 };
590
Steve Blockd0582a62009-12-15 09:54:21 +0000591 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100592#ifdef DEBUG
593 static bool initialized_;
594#endif
595 static unsigned supported_;
596 static unsigned found_by_runtime_probing_;
Steve Block44f0eee2011-05-26 01:26:41 +0100597
598 DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
Steve Blockd0582a62009-12-15 09:54:21 +0000599};
600
Steve Blocka7e24c12009-10-30 11:49:00 +0000601
Steve Blocka7e24c12009-10-30 11:49:00 +0000602extern const Instr kMovLrPc;
Steve Block6ded16b2010-05-10 14:33:55 +0100603extern const Instr kLdrPCMask;
Steve Blocka7e24c12009-10-30 11:49:00 +0000604extern const Instr kLdrPCPattern;
Steve Block6ded16b2010-05-10 14:33:55 +0100605extern const Instr kBlxRegMask;
606extern const Instr kBlxRegPattern;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100607extern const Instr kBlxIp;
Steve Blocka7e24c12009-10-30 11:49:00 +0000608
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100609extern const Instr kMovMvnMask;
610extern const Instr kMovMvnPattern;
611extern const Instr kMovMvnFlip;
612
613extern const Instr kMovLeaveCCMask;
614extern const Instr kMovLeaveCCPattern;
615extern const Instr kMovwMask;
616extern const Instr kMovwPattern;
617extern const Instr kMovwLeaveCCFlip;
618
619extern const Instr kCmpCmnMask;
620extern const Instr kCmpCmnPattern;
621extern const Instr kCmpCmnFlip;
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100622extern const Instr kAddSubFlip;
623extern const Instr kAndBicFlip;
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
Steve Block1e0659c2011-05-24 12:43:12 +0100625
626
Steve Block44f0eee2011-05-26 01:26:41 +0100627class Assembler : public AssemblerBase {
Steve Blocka7e24c12009-10-30 11:49:00 +0000628 public:
629 // Create an assembler. Instructions and relocation information are emitted
630 // into a buffer, with the instructions starting from the beginning and the
631 // relocation information starting from the end of the buffer. See CodeDesc
632 // for a detailed comment on the layout (globals.h).
633 //
634 // If the provided buffer is NULL, the assembler allocates and grows its own
635 // buffer, and buffer_size determines the initial buffer size. The buffer is
636 // owned by the assembler and deallocated upon destruction of the assembler.
637 //
638 // If the provided buffer is not NULL, the assembler uses the provided buffer
639 // for code generation and assumes its size to be buffer_size. If the buffer
640 // is too small, a fatal error occurs. No deallocation of the buffer is done
641 // upon destruction of the assembler.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100642 Assembler(Isolate* isolate, void* buffer, int buffer_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643 ~Assembler();
644
Steve Block44f0eee2011-05-26 01:26:41 +0100645 // Overrides the default provided by FLAG_debug_code.
646 void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
647
Steve Blocka7e24c12009-10-30 11:49:00 +0000648 // GetCode emits any pending (non-emitted) code and fills the descriptor
649 // desc. GetCode() is idempotent; it returns the same result if no other
650 // Assembler functions are invoked in between GetCode() calls.
651 void GetCode(CodeDesc* desc);
652
653 // Label operations & relative jumps (PPUM Appendix D)
654 //
655 // Takes a branch opcode (cc) and a label (L) and generates
656 // either a backward branch or a forward branch and links it
657 // to the label fixup chain. Usage:
658 //
659 // Label L; // unbound label
660 // j(cc, &L); // forward branch to unbound label
661 // bind(&L); // bind label to the current pc
662 // j(cc, &L); // backward branch to bound label
663 // bind(&L); // illegal: a label may be bound only once
664 //
665 // Note: The same Label can be used for forward and backward branches
666 // but it may be bound only once.
667
668 void bind(Label* L); // binds an unbound label L to the current code position
669
670 // Returns the branch offset to the given label from the current code position
671 // Links the label to the current position if it is still unbound
672 // Manages the jump elimination optimization if the second parameter is true.
673 int branch_offset(Label* L, bool jump_elimination_allowed);
674
675 // Puts a labels target address at the given position.
676 // The high 8 bits are set to zero.
677 void label_at_put(Label* L, int at_offset);
678
679 // Return the address in the constant pool of the code target address used by
680 // the branch/call instruction at pc.
681 INLINE(static Address target_address_address_at(Address pc));
682
683 // Read/Modify the code target address in the branch/call instruction at pc.
684 INLINE(static Address target_address_at(Address pc));
685 INLINE(static void set_target_address_at(Address pc, Address target));
686
Steve Blockd0582a62009-12-15 09:54:21 +0000687 // This sets the branch destination (which is in the constant pool on ARM).
688 // This is for calls and branches within generated code.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100689 inline static void deserialization_set_special_target_at(
690 Address constant_pool_entry, Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000691
692 // This sets the branch destination (which is in the constant pool on ARM).
693 // This is for calls and branches to runtime code.
694 inline static void set_external_target_at(Address constant_pool_entry,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100695 Address target);
Steve Blockd0582a62009-12-15 09:54:21 +0000696
697 // Here we are patching the address in the constant pool, not the actual call
698 // instruction. The address in the constant pool is the same size as a
699 // pointer.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100700 static const int kSpecialTargetSize = kPointerSize;
Steve Blockd0582a62009-12-15 09:54:21 +0000701
Steve Blocka7e24c12009-10-30 11:49:00 +0000702 // Size of an instruction.
703 static const int kInstrSize = sizeof(Instr);
704
705 // Distance between the instruction referring to the address of the call
Steve Block6ded16b2010-05-10 14:33:55 +0100706 // target and the return address.
707#ifdef USE_BLX
708 // Call sequence is:
709 // ldr ip, [pc, #...] @ call address
710 // blx ip
711 // @ return address
712 static const int kCallTargetAddressOffset = 2 * kInstrSize;
713#else
714 // Call sequence is:
715 // mov lr, pc
716 // ldr pc, [pc, #...] @ call address
717 // @ return address
Steve Blocka7e24c12009-10-30 11:49:00 +0000718 static const int kCallTargetAddressOffset = kInstrSize;
Steve Block6ded16b2010-05-10 14:33:55 +0100719#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000720
721 // Distance between start of patched return sequence and the emitted address
722 // to jump to.
Steve Block6ded16b2010-05-10 14:33:55 +0100723#ifdef USE_BLX
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100724 // Patched return sequence is:
Steve Block6ded16b2010-05-10 14:33:55 +0100725 // ldr ip, [pc, #0] @ emited address and start
726 // blx ip
727 static const int kPatchReturnSequenceAddressOffset = 0 * kInstrSize;
728#else
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100729 // Patched return sequence is:
Steve Block6ded16b2010-05-10 14:33:55 +0100730 // mov lr, pc @ start of sequence
731 // ldr pc, [pc, #-4] @ emited address
732 static const int kPatchReturnSequenceAddressOffset = kInstrSize;
733#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000734
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100735 // Distance between start of patched debug break slot and the emitted address
736 // to jump to.
737#ifdef USE_BLX
738 // Patched debug break slot code is:
739 // ldr ip, [pc, #0] @ emited address and start
740 // blx ip
741 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
742#else
743 // Patched debug break slot code is:
744 // mov lr, pc @ start of sequence
745 // ldr pc, [pc, #-4] @ emited address
746 static const int kPatchDebugBreakSlotAddressOffset = kInstrSize;
747#endif
748
Steve Blocka7e24c12009-10-30 11:49:00 +0000749 // Difference between address of current opcode and value read from pc
750 // register.
751 static const int kPcLoadDelta = 8;
752
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100753 static const int kJSReturnSequenceInstructions = 4;
754 static const int kDebugBreakSlotInstructions = 3;
755 static const int kDebugBreakSlotLength =
756 kDebugBreakSlotInstructions * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000757
758 // ---------------------------------------------------------------------------
759 // Code generation
760
761 // Insert the smallest number of nop instructions
762 // possible to align the pc offset to a multiple
763 // of m. m must be a power of 2 (>= 4).
764 void Align(int m);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100765 // Aligns code to something that's optimal for a jump target for the platform.
766 void CodeTargetAlign();
Steve Blocka7e24c12009-10-30 11:49:00 +0000767
768 // Branch instructions
769 void b(int branch_offset, Condition cond = al);
770 void bl(int branch_offset, Condition cond = al);
771 void blx(int branch_offset); // v5 and above
772 void blx(Register target, Condition cond = al); // v5 and above
773 void bx(Register target, Condition cond = al); // v5 and above, plus v4t
774
775 // Convenience branch instructions using labels
776 void b(Label* L, Condition cond = al) {
777 b(branch_offset(L, cond == al), cond);
778 }
779 void b(Condition cond, Label* L) { b(branch_offset(L, cond == al), cond); }
780 void bl(Label* L, Condition cond = al) { bl(branch_offset(L, false), cond); }
781 void bl(Condition cond, Label* L) { bl(branch_offset(L, false), cond); }
782 void blx(Label* L) { blx(branch_offset(L, false)); } // v5 and above
783
784 // Data-processing instructions
Andrei Popescu31002712010-02-23 13:46:05 +0000785
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 void and_(Register dst, Register src1, const Operand& src2,
787 SBit s = LeaveCC, Condition cond = al);
788
789 void eor(Register dst, Register src1, const Operand& src2,
790 SBit s = LeaveCC, Condition cond = al);
791
792 void sub(Register dst, Register src1, const Operand& src2,
793 SBit s = LeaveCC, Condition cond = al);
794 void sub(Register dst, Register src1, Register src2,
795 SBit s = LeaveCC, Condition cond = al) {
796 sub(dst, src1, Operand(src2), s, cond);
797 }
798
799 void rsb(Register dst, Register src1, const Operand& src2,
800 SBit s = LeaveCC, Condition cond = al);
801
802 void add(Register dst, Register src1, const Operand& src2,
803 SBit s = LeaveCC, Condition cond = al);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100804 void add(Register dst, Register src1, Register src2,
805 SBit s = LeaveCC, Condition cond = al) {
806 add(dst, src1, Operand(src2), s, cond);
807 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000808
809 void adc(Register dst, Register src1, const Operand& src2,
810 SBit s = LeaveCC, Condition cond = al);
811
812 void sbc(Register dst, Register src1, const Operand& src2,
813 SBit s = LeaveCC, Condition cond = al);
814
815 void rsc(Register dst, Register src1, const Operand& src2,
816 SBit s = LeaveCC, Condition cond = al);
817
818 void tst(Register src1, const Operand& src2, Condition cond = al);
819 void tst(Register src1, Register src2, Condition cond = al) {
820 tst(src1, Operand(src2), cond);
821 }
822
823 void teq(Register src1, const Operand& src2, Condition cond = al);
824
825 void cmp(Register src1, const Operand& src2, Condition cond = al);
826 void cmp(Register src1, Register src2, Condition cond = al) {
827 cmp(src1, Operand(src2), cond);
828 }
Steve Block1e0659c2011-05-24 12:43:12 +0100829 void cmp_raw_immediate(Register src1, int raw_immediate, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000830
831 void cmn(Register src1, const Operand& src2, Condition cond = al);
832
833 void orr(Register dst, Register src1, const Operand& src2,
834 SBit s = LeaveCC, Condition cond = al);
835 void orr(Register dst, Register src1, Register src2,
836 SBit s = LeaveCC, Condition cond = al) {
837 orr(dst, src1, Operand(src2), s, cond);
838 }
839
840 void mov(Register dst, const Operand& src,
841 SBit s = LeaveCC, Condition cond = al);
842 void mov(Register dst, Register src, SBit s = LeaveCC, Condition cond = al) {
843 mov(dst, Operand(src), s, cond);
844 }
845
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100846 // ARMv7 instructions for loading a 32 bit immediate in two instructions.
847 // This may actually emit a different mov instruction, but on an ARMv7 it
848 // is guaranteed to only emit one instruction.
849 void movw(Register reg, uint32_t immediate, Condition cond = al);
850 // The constant for movt should be in the range 0-0xffff.
851 void movt(Register reg, uint32_t immediate, Condition cond = al);
852
Steve Blocka7e24c12009-10-30 11:49:00 +0000853 void bic(Register dst, Register src1, const Operand& src2,
854 SBit s = LeaveCC, Condition cond = al);
855
856 void mvn(Register dst, const Operand& src,
857 SBit s = LeaveCC, Condition cond = al);
858
859 // Multiply instructions
860
861 void mla(Register dst, Register src1, Register src2, Register srcA,
862 SBit s = LeaveCC, Condition cond = al);
863
864 void mul(Register dst, Register src1, Register src2,
865 SBit s = LeaveCC, Condition cond = al);
866
867 void smlal(Register dstL, Register dstH, Register src1, Register src2,
868 SBit s = LeaveCC, Condition cond = al);
869
870 void smull(Register dstL, Register dstH, Register src1, Register src2,
871 SBit s = LeaveCC, Condition cond = al);
872
873 void umlal(Register dstL, Register dstH, Register src1, Register src2,
874 SBit s = LeaveCC, Condition cond = al);
875
876 void umull(Register dstL, Register dstH, Register src1, Register src2,
877 SBit s = LeaveCC, Condition cond = al);
878
879 // Miscellaneous arithmetic instructions
880
881 void clz(Register dst, Register src, Condition cond = al); // v5 and above
882
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100883 // Saturating instructions. v6 and above.
884
885 // Unsigned saturate.
886 //
887 // Saturate an optionally shifted signed value to an unsigned range.
888 //
889 // usat dst, #satpos, src
890 // usat dst, #satpos, src, lsl #sh
891 // usat dst, #satpos, src, asr #sh
892 //
893 // Register dst will contain:
894 //
895 // 0, if s < 0
896 // (1 << satpos) - 1, if s > ((1 << satpos) - 1)
897 // s, otherwise
898 //
899 // where s is the contents of src after shifting (if used.)
900 void usat(Register dst, int satpos, const Operand& src, Condition cond = al);
901
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100902 // Bitfield manipulation instructions. v7 and above.
903
904 void ubfx(Register dst, Register src, int lsb, int width,
905 Condition cond = al);
906
907 void sbfx(Register dst, Register src, int lsb, int width,
908 Condition cond = al);
909
910 void bfc(Register dst, int lsb, int width, Condition cond = al);
911
912 void bfi(Register dst, Register src, int lsb, int width,
913 Condition cond = al);
914
Steve Blocka7e24c12009-10-30 11:49:00 +0000915 // Status register access instructions
916
917 void mrs(Register dst, SRegister s, Condition cond = al);
918 void msr(SRegisterFieldMask fields, const Operand& src, Condition cond = al);
919
920 // Load/Store instructions
921 void ldr(Register dst, const MemOperand& src, Condition cond = al);
922 void str(Register src, const MemOperand& dst, Condition cond = al);
923 void ldrb(Register dst, const MemOperand& src, Condition cond = al);
924 void strb(Register src, const MemOperand& dst, Condition cond = al);
925 void ldrh(Register dst, const MemOperand& src, Condition cond = al);
926 void strh(Register src, const MemOperand& dst, Condition cond = al);
927 void ldrsb(Register dst, const MemOperand& src, Condition cond = al);
928 void ldrsh(Register dst, const MemOperand& src, Condition cond = al);
Leon Clarkef7060e22010-06-03 12:02:55 +0100929 void ldrd(Register dst1,
930 Register dst2,
931 const MemOperand& src, Condition cond = al);
932 void strd(Register src1,
933 Register src2,
934 const MemOperand& dst, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000935
936 // Load/Store multiple instructions
937 void ldm(BlockAddrMode am, Register base, RegList dst, Condition cond = al);
938 void stm(BlockAddrMode am, Register base, RegList src, Condition cond = al);
939
Steve Blocka7e24c12009-10-30 11:49:00 +0000940 // Exception-generating instructions and debugging support
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800941 void stop(const char* msg,
942 Condition cond = al,
943 int32_t code = kDefaultStopCode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000944
945 void bkpt(uint32_t imm16); // v5 and above
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -0800946 void svc(uint32_t imm24, Condition cond = al);
Steve Blocka7e24c12009-10-30 11:49:00 +0000947
948 // Coprocessor instructions
949
950 void cdp(Coprocessor coproc, int opcode_1,
951 CRegister crd, CRegister crn, CRegister crm,
952 int opcode_2, Condition cond = al);
953
954 void cdp2(Coprocessor coproc, int opcode_1,
955 CRegister crd, CRegister crn, CRegister crm,
956 int opcode_2); // v5 and above
957
958 void mcr(Coprocessor coproc, int opcode_1,
959 Register rd, CRegister crn, CRegister crm,
960 int opcode_2 = 0, Condition cond = al);
961
962 void mcr2(Coprocessor coproc, int opcode_1,
963 Register rd, CRegister crn, CRegister crm,
964 int opcode_2 = 0); // v5 and above
965
966 void mrc(Coprocessor coproc, int opcode_1,
967 Register rd, CRegister crn, CRegister crm,
968 int opcode_2 = 0, Condition cond = al);
969
970 void mrc2(Coprocessor coproc, int opcode_1,
971 Register rd, CRegister crn, CRegister crm,
972 int opcode_2 = 0); // v5 and above
973
974 void ldc(Coprocessor coproc, CRegister crd, const MemOperand& src,
975 LFlag l = Short, Condition cond = al);
976 void ldc(Coprocessor coproc, CRegister crd, Register base, int option,
977 LFlag l = Short, Condition cond = al);
978
979 void ldc2(Coprocessor coproc, CRegister crd, const MemOperand& src,
980 LFlag l = Short); // v5 and above
981 void ldc2(Coprocessor coproc, CRegister crd, Register base, int option,
982 LFlag l = Short); // v5 and above
983
Steve Blockd0582a62009-12-15 09:54:21 +0000984 // Support for VFP.
985 // All these APIs support S0 to S31 and D0 to D15.
986 // Currently these APIs do not support extended D registers, i.e, D16 to D31.
987 // However, some simple modifications can allow
988 // these APIs to support D16 to D31.
989
Leon Clarked91b9f72010-01-27 17:25:45 +0000990 void vldr(const DwVfpRegister dst,
991 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100992 int offset,
993 const Condition cond = al);
994 void vldr(const DwVfpRegister dst,
995 const MemOperand& src,
Leon Clarked91b9f72010-01-27 17:25:45 +0000996 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +0100997
998 void vldr(const SwVfpRegister dst,
999 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001000 int offset,
1001 const Condition cond = al);
1002 void vldr(const SwVfpRegister dst,
1003 const MemOperand& src,
Steve Block6ded16b2010-05-10 14:33:55 +01001004 const Condition cond = al);
1005
Leon Clarked91b9f72010-01-27 17:25:45 +00001006 void vstr(const DwVfpRegister src,
1007 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001008 int offset,
1009 const Condition cond = al);
1010 void vstr(const DwVfpRegister src,
1011 const MemOperand& dst,
Leon Clarked91b9f72010-01-27 17:25:45 +00001012 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001013
Iain Merrick75681382010-08-19 15:07:18 +01001014 void vstr(const SwVfpRegister src,
1015 const Register base,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001016 int offset,
1017 const Condition cond = al);
1018 void vstr(const SwVfpRegister src,
1019 const MemOperand& dst,
Iain Merrick75681382010-08-19 15:07:18 +01001020 const Condition cond = al);
1021
Ben Murdoch8b112d22011-06-08 16:22:53 +01001022 void vldm(BlockAddrMode am,
1023 Register base,
1024 DwVfpRegister first,
1025 DwVfpRegister last,
1026 Condition cond = al);
1027
1028 void vstm(BlockAddrMode am,
1029 Register base,
1030 DwVfpRegister first,
1031 DwVfpRegister last,
1032 Condition cond = al);
1033
1034 void vldm(BlockAddrMode am,
1035 Register base,
1036 SwVfpRegister first,
1037 SwVfpRegister last,
1038 Condition cond = al);
1039
1040 void vstm(BlockAddrMode am,
1041 Register base,
1042 SwVfpRegister first,
1043 SwVfpRegister last,
1044 Condition cond = al);
1045
Steve Block8defd9f2010-07-08 12:39:36 +01001046 void vmov(const DwVfpRegister dst,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001047 double imm,
1048 const Condition cond = al);
1049 void vmov(const SwVfpRegister dst,
1050 const SwVfpRegister src,
1051 const Condition cond = al);
1052 void vmov(const DwVfpRegister dst,
Steve Block8defd9f2010-07-08 12:39:36 +01001053 const DwVfpRegister src,
1054 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001055 void vmov(const DwVfpRegister dst,
1056 const Register src1,
Steve Blockd0582a62009-12-15 09:54:21 +00001057 const Register src2,
Leon Clarkee46be812010-01-19 14:06:41 +00001058 const Condition cond = al);
1059 void vmov(const Register dst1,
1060 const Register dst2,
1061 const DwVfpRegister src,
1062 const Condition cond = al);
1063 void vmov(const SwVfpRegister dst,
1064 const Register src,
1065 const Condition cond = al);
1066 void vmov(const Register dst,
1067 const SwVfpRegister src,
1068 const Condition cond = al);
Steve Block6ded16b2010-05-10 14:33:55 +01001069 void vcvt_f64_s32(const DwVfpRegister dst,
1070 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001071 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001072 const Condition cond = al);
1073 void vcvt_f32_s32(const SwVfpRegister dst,
1074 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001075 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001076 const Condition cond = al);
1077 void vcvt_f64_u32(const DwVfpRegister dst,
1078 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001079 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001080 const Condition cond = al);
1081 void vcvt_s32_f64(const SwVfpRegister dst,
1082 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001083 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001084 const Condition cond = al);
1085 void vcvt_u32_f64(const SwVfpRegister dst,
1086 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001087 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001088 const Condition cond = al);
1089 void vcvt_f64_f32(const DwVfpRegister dst,
1090 const SwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001091 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001092 const Condition cond = al);
1093 void vcvt_f32_f64(const SwVfpRegister dst,
1094 const DwVfpRegister src,
Steve Block1e0659c2011-05-24 12:43:12 +01001095 VFPConversionMode mode = kDefaultRoundToZero,
Steve Block6ded16b2010-05-10 14:33:55 +01001096 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001097
Steve Block44f0eee2011-05-26 01:26:41 +01001098 void vneg(const DwVfpRegister dst,
1099 const DwVfpRegister src,
1100 const Condition cond = al);
Steve Block1e0659c2011-05-24 12:43:12 +01001101 void vabs(const DwVfpRegister dst,
1102 const DwVfpRegister src,
1103 const Condition cond = al);
Leon Clarkee46be812010-01-19 14:06:41 +00001104 void vadd(const DwVfpRegister dst,
1105 const DwVfpRegister src1,
1106 const DwVfpRegister src2,
1107 const Condition cond = al);
1108 void vsub(const DwVfpRegister dst,
1109 const DwVfpRegister src1,
1110 const DwVfpRegister src2,
1111 const Condition cond = al);
1112 void vmul(const DwVfpRegister dst,
1113 const DwVfpRegister src1,
1114 const DwVfpRegister src2,
1115 const Condition cond = al);
1116 void vdiv(const DwVfpRegister dst,
1117 const DwVfpRegister src1,
1118 const DwVfpRegister src2,
1119 const Condition cond = al);
1120 void vcmp(const DwVfpRegister src1,
1121 const DwVfpRegister src2,
Steve Blockd0582a62009-12-15 09:54:21 +00001122 const Condition cond = al);
Iain Merrick75681382010-08-19 15:07:18 +01001123 void vcmp(const DwVfpRegister src1,
1124 const double src2,
Iain Merrick75681382010-08-19 15:07:18 +01001125 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001126 void vmrs(const Register dst,
1127 const Condition cond = al);
Russell Brenner90bac252010-11-18 13:33:46 -08001128 void vmsr(const Register dst,
1129 const Condition cond = al);
Steve Block8defd9f2010-07-08 12:39:36 +01001130 void vsqrt(const DwVfpRegister dst,
1131 const DwVfpRegister src,
1132 const Condition cond = al);
Steve Blockd0582a62009-12-15 09:54:21 +00001133
Steve Blocka7e24c12009-10-30 11:49:00 +00001134 // Pseudo instructions
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001135
1136 // Different nop operations are used by the code generator to detect certain
1137 // states of the generated code.
1138 enum NopMarkerTypes {
1139 NON_MARKING_NOP = 0,
1140 DEBUG_BREAK_NOP,
1141 // IC markers.
1142 PROPERTY_ACCESS_INLINED,
1143 PROPERTY_ACCESS_INLINED_CONTEXT,
1144 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1145 // Helper values.
1146 LAST_CODE_MARKER,
1147 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1148 };
1149
1150 void nop(int type = 0); // 0 is the default non-marking type.
Steve Blocka7e24c12009-10-30 11:49:00 +00001151
1152 void push(Register src, Condition cond = al) {
1153 str(src, MemOperand(sp, 4, NegPreIndex), cond);
1154 }
1155
1156 void pop(Register dst, Condition cond = al) {
1157 ldr(dst, MemOperand(sp, 4, PostIndex), cond);
1158 }
1159
1160 void pop() {
1161 add(sp, sp, Operand(kPointerSize));
1162 }
1163
Steve Blocka7e24c12009-10-30 11:49:00 +00001164 // Jump unconditionally to given label.
1165 void jmp(Label* L) { b(L, al); }
1166
1167 // Check the code size generated from label to here.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001168 int SizeOfCodeGeneratedSince(Label* label) {
1169 return pc_offset() - label->pos();
1170 }
1171
1172 // Check the number of instructions generated from label to here.
1173 int InstructionsGeneratedSince(Label* label) {
1174 return SizeOfCodeGeneratedSince(label) / kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001175 }
1176
Steve Blockd0582a62009-12-15 09:54:21 +00001177 // Check whether an immediate fits an addressing mode 1 instruction.
1178 bool ImmediateFitsAddrMode1Instruction(int32_t imm32);
1179
Steve Block6ded16b2010-05-10 14:33:55 +01001180 // Class for scoping postponing the constant pool generation.
1181 class BlockConstPoolScope {
1182 public:
1183 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1184 assem_->StartBlockConstPool();
1185 }
1186 ~BlockConstPoolScope() {
1187 assem_->EndBlockConstPool();
1188 }
1189
1190 private:
1191 Assembler* assem_;
1192
1193 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1194 };
1195
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 // Debugging
1197
1198 // Mark address of the ExitJSFrame code.
1199 void RecordJSReturn();
1200
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001201 // Mark address of a debug break slot.
1202 void RecordDebugBreakSlot();
1203
Ben Murdoch257744e2011-11-30 15:57:28 +00001204 // Record the AST id of the CallIC being compiled, so that it can be placed
1205 // in the relocation information.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001206 void SetRecordedAstId(unsigned ast_id) {
1207 ASSERT(recorded_ast_id_ == kNoASTId);
1208 recorded_ast_id_ = ast_id;
1209 }
1210
1211 unsigned RecordedAstId() {
1212 ASSERT(recorded_ast_id_ != kNoASTId);
1213 return recorded_ast_id_;
1214 }
1215
1216 void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
Ben Murdoch257744e2011-11-30 15:57:28 +00001217
Steve Blocka7e24c12009-10-30 11:49:00 +00001218 // Record a comment relocation entry that can be used by a disassembler.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001219 // Use --code-comments to enable.
Steve Blocka7e24c12009-10-30 11:49:00 +00001220 void RecordComment(const char* msg);
1221
Ben Murdochb8e0da22011-05-16 14:20:40 +01001222 // Writes a single byte or word of data in the code stream. Used
1223 // for inline tables, e.g., jump-tables. The constant pool should be
1224 // emitted before any use of db and dd to ensure that constant pools
1225 // are not emitted as part of the tables generated.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001226 void db(uint8_t data);
1227 void dd(uint32_t data);
1228
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 int pc_offset() const { return pc_ - buffer_; }
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001230
1231 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
Steve Block6ded16b2010-05-10 14:33:55 +01001232
1233 // Read/patch instructions
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001234 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1235 void instr_at_put(int pos, Instr instr) {
1236 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1237 }
Steve Block6ded16b2010-05-10 14:33:55 +01001238 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1239 static void instr_at_put(byte* pc, Instr instr) {
1240 *reinterpret_cast<Instr*>(pc) = instr;
1241 }
Steve Block1e0659c2011-05-24 12:43:12 +01001242 static Condition GetCondition(Instr instr);
Steve Block6ded16b2010-05-10 14:33:55 +01001243 static bool IsBranch(Instr instr);
1244 static int GetBranchOffset(Instr instr);
1245 static bool IsLdrRegisterImmediate(Instr instr);
1246 static int GetLdrRegisterImmediateOffset(Instr instr);
1247 static Instr SetLdrRegisterImmediateOffset(Instr instr, int offset);
Kristian Monsen50ef84f2010-07-29 15:18:00 +01001248 static bool IsStrRegisterImmediate(Instr instr);
1249 static Instr SetStrRegisterImmediateOffset(Instr instr, int offset);
1250 static bool IsAddRegisterImmediate(Instr instr);
1251 static Instr SetAddRegisterImmediateOffset(Instr instr, int offset);
Leon Clarkef7060e22010-06-03 12:02:55 +01001252 static Register GetRd(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001253 static Register GetRn(Instr instr);
1254 static Register GetRm(Instr instr);
Leon Clarkef7060e22010-06-03 12:02:55 +01001255 static bool IsPush(Instr instr);
1256 static bool IsPop(Instr instr);
1257 static bool IsStrRegFpOffset(Instr instr);
1258 static bool IsLdrRegFpOffset(Instr instr);
1259 static bool IsStrRegFpNegOffset(Instr instr);
1260 static bool IsLdrRegFpNegOffset(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001261 static bool IsLdrPcImmediateOffset(Instr instr);
Steve Block1e0659c2011-05-24 12:43:12 +01001262 static bool IsTstImmediate(Instr instr);
1263 static bool IsCmpRegister(Instr instr);
1264 static bool IsCmpImmediate(Instr instr);
1265 static Register GetCmpImmediateRegister(Instr instr);
1266 static int GetCmpImmediateRawImmediate(Instr instr);
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08001267 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
Steve Block6ded16b2010-05-10 14:33:55 +01001268
Ben Murdoch257744e2011-11-30 15:57:28 +00001269 // Constants in pools are accessed via pc relative addressing, which can
1270 // reach +/-4KB thereby defining a maximum distance between the instruction
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001271 // and the accessed constant.
1272 static const int kMaxDistToPool = 4*KB;
1273 static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize;
Ben Murdoch257744e2011-11-30 15:57:28 +00001274
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001275 // Postpone the generation of the constant pool for the specified number of
1276 // instructions.
1277 void BlockConstPoolFor(int instructions);
1278
1279 // Check if is time to emit a constant pool.
Ben Murdochb0fe1622011-05-05 13:52:32 +01001280 void CheckConstPool(bool force_emit, bool require_jump);
Steve Blocka7e24c12009-10-30 11:49:00 +00001281
1282 protected:
Ben Murdoch257744e2011-11-30 15:57:28 +00001283 // Relocation for a type-recording IC has the AST id added to it. This
1284 // member variable is a way to pass the information from the call site to
1285 // the relocation info.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001286 unsigned recorded_ast_id_;
Ben Murdoch257744e2011-11-30 15:57:28 +00001287
Steve Block44f0eee2011-05-26 01:26:41 +01001288 bool emit_debug_code() const { return emit_debug_code_; }
1289
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1291
Steve Blocka7e24c12009-10-30 11:49:00 +00001292 // Decode branch instruction at pos and return branch target pos
1293 int target_at(int pos);
1294
1295 // Patch branch instruction at pos to branch to given branch target pos
1296 void target_at_put(int pos, int target_pos);
1297
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001298 // Prevent contant pool emission until EndBlockConstPool is called.
1299 // Call to this function can be nested but must be followed by an equal
1300 // number of call to EndBlockConstpool.
1301 void StartBlockConstPool() {
1302 if (const_pool_blocked_nesting_++ == 0) {
1303 // Prevent constant pool checks happening by setting the next check to
1304 // the biggest possible offset.
1305 next_buffer_check_ = kMaxInt;
1306 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001307 }
1308
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001309 // Resume constant pool emission. Need to be called as many time as
1310 // StartBlockConstPool to have an effect.
Steve Block6ded16b2010-05-10 14:33:55 +01001311 void EndBlockConstPool() {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001312 if (--const_pool_blocked_nesting_ == 0) {
1313 // Check the constant pool hasn't been blocked for too long.
1314 ASSERT((num_pending_reloc_info_ == 0) ||
1315 (pc_offset() < (first_const_pool_use_ + kMaxDistToPool)));
1316 // Two cases:
1317 // * no_const_pool_before_ >= next_buffer_check_ and the emission is
1318 // still blocked
1319 // * no_const_pool_before_ < next_buffer_check_ and the next emit will
1320 // trigger a check.
1321 next_buffer_check_ = no_const_pool_before_;
1322 }
Steve Block6ded16b2010-05-10 14:33:55 +01001323 }
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001324
1325 bool is_const_pool_blocked() const {
1326 return (const_pool_blocked_nesting_ > 0) ||
1327 (pc_offset() < no_const_pool_before_);
1328 }
Steve Block6ded16b2010-05-10 14:33:55 +01001329
Steve Blocka7e24c12009-10-30 11:49:00 +00001330 private:
1331 // Code buffer:
1332 // The buffer into which code and relocation info are generated.
1333 byte* buffer_;
1334 int buffer_size_;
1335 // True if the assembler owns the buffer, false if buffer is external.
1336 bool own_buffer_;
1337
Steve Blocka7e24c12009-10-30 11:49:00 +00001338 int next_buffer_check_; // pc offset of next buffer check
1339
1340 // Code generation
1341 // The relocation writer's position is at least kGap bytes below the end of
1342 // the generated instructions. This is so that multi-instruction sequences do
1343 // not have to check for overflow. The same is true for writes of large
1344 // relocation info entries.
1345 static const int kGap = 32;
1346 byte* pc_; // the program counter; moves forward
1347
1348 // Constant pool generation
1349 // Pools are emitted in the instruction stream, preferably after unconditional
1350 // jumps or after returns from functions (in dead code locations).
1351 // If a long code sequence does not contain unconditional jumps, it is
1352 // necessary to emit the constant pool before the pool gets too far from the
1353 // location it is accessed from. In this case, we emit a jump over the emitted
1354 // constant pool.
1355 // Constants in the pool may be addresses of functions that gets relocated;
1356 // if so, a relocation info entry is associated to the constant pool entry.
1357
1358 // Repeated checking whether the constant pool should be emitted is rather
1359 // expensive. By default we only check again once a number of instructions
1360 // has been generated. That also means that the sizing of the buffers is not
1361 // an exact science, and that we rely on some slop to not overrun buffers.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001362 static const int kCheckPoolIntervalInst = 32;
1363 static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
Steve Blocka7e24c12009-10-30 11:49:00 +00001364
1365
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001366 // Average distance beetween a constant pool and the first instruction
1367 // accessing the constant pool. Longer distance should result in less I-cache
1368 // pollution.
1369 // In practice the distance will be smaller since constant pool emission is
1370 // forced after function return and sometimes after unconditional branches.
1371 static const int kAvgDistToPool = kMaxDistToPool - kCheckPoolInterval;
Steve Blocka7e24c12009-10-30 11:49:00 +00001372
Steve Block6ded16b2010-05-10 14:33:55 +01001373 // Emission of the constant pool may be blocked in some code sequences.
1374 int const_pool_blocked_nesting_; // Block emission if this is not zero.
1375 int no_const_pool_before_; // Block emission before this pc offset.
Steve Blocka7e24c12009-10-30 11:49:00 +00001376
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001377 // Keep track of the first instruction requiring a constant pool entry
1378 // since the previous constant pool was emitted.
1379 int first_const_pool_use_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001380
1381 // Relocation info generation
1382 // Each relocation is encoded as a variable size value
1383 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1384 RelocInfoWriter reloc_info_writer;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001385
Steve Blocka7e24c12009-10-30 11:49:00 +00001386 // Relocation info records are also used during code generation as temporary
1387 // containers for constants and code target addresses until they are emitted
1388 // to the constant pool. These pending relocation info records are temporarily
1389 // stored in a separate buffer until a constant pool is emitted.
1390 // If every instruction in a long sequence is accessing the pool, we need one
1391 // pending relocation entry per instruction.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001392
1393 // the buffer of pending relocation info
1394 RelocInfo pending_reloc_info_[kMaxNumPendingRelocInfo];
1395 // number of pending reloc info entries in the buffer
1396 int num_pending_reloc_info_;
Steve Blocka7e24c12009-10-30 11:49:00 +00001397
1398 // The bound position, before this we cannot do instruction elimination.
1399 int last_bound_pos_;
1400
Steve Blocka7e24c12009-10-30 11:49:00 +00001401 // Code emission
1402 inline void CheckBuffer();
1403 void GrowBuffer();
1404 inline void emit(Instr x);
1405
1406 // Instruction generation
1407 void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
1408 void addrmod2(Instr instr, Register rd, const MemOperand& x);
1409 void addrmod3(Instr instr, Register rd, const MemOperand& x);
1410 void addrmod4(Instr instr, Register rn, RegList rl);
1411 void addrmod5(Instr instr, CRegister crd, const MemOperand& x);
1412
1413 // Labels
1414 void print(Label* L);
1415 void bind_to(Label* L, int pos);
1416 void link_to(Label* L, Label* appendix);
1417 void next(Label* L);
1418
1419 // Record reloc info for current pc_
1420 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1421
1422 friend class RegExpMacroAssemblerARM;
1423 friend class RelocInfo;
1424 friend class CodePatcher;
Steve Block6ded16b2010-05-10 14:33:55 +01001425 friend class BlockConstPoolScope;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001426
1427 PositionsRecorder positions_recorder_;
Steve Block44f0eee2011-05-26 01:26:41 +01001428 bool emit_debug_code_;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001429 friend class PositionsRecorder;
1430 friend class EnsureSpace;
Steve Blocka7e24c12009-10-30 11:49:00 +00001431};
1432
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001433
1434class EnsureSpace BASE_EMBEDDED {
1435 public:
1436 explicit EnsureSpace(Assembler* assembler) {
1437 assembler->CheckBuffer();
1438 }
1439};
1440
1441
Steve Blocka7e24c12009-10-30 11:49:00 +00001442} } // namespace v8::internal
1443
1444#endif // V8_ARM_ASSEMBLER_ARM_H_