source: webkit/trunk/JavaScriptCore/assembler/ARMAssembler.h@ 47186

Last change on this file since 47186 was 47186, checked in by [email protected], 16 years ago

Add optimize call and property access support for ARM JIT.
https://bugs.webkit.org/show_bug.cgi?id=24986

Patch by Gabor Loki <[email protected]> on 2009-08-12
Reviewed by Gavin Barraclough.

For tightly coupled sequences the BEGIN_UNINTERRUPTED_SEQUENCE and
END_UNINTERRUPTED_SEQUENCE macros have been introduced which ensure
space for instructions and constants of the named sequence. This
method is vital for those architecture which are using constant pool.

The 'latePatch' method - which was linked to JmpSrc - is replaced with
a port specific solution (each calls are marked to place their address
on the constant pool).

  • assembler/ARMAssembler.cpp:

(JSC::ARMAssembler::linkBranch):
(JSC::ARMAssembler::executableCopy): Add extra align for constant pool.

  • assembler/ARMAssembler.h:

(JSC::ARMAssembler::JmpSrc::JmpSrc):
(JSC::ARMAssembler::sizeOfConstantPool):
(JSC::ARMAssembler::jmp):
(JSC::ARMAssembler::linkCall):

  • assembler/ARMv7Assembler.h:
  • assembler/AbstractMacroAssembler.h:
  • assembler/AssemblerBufferWithConstantPool.h:

(JSC::AssemblerBufferWithConstantPool::flushIfNoSpaceFor): Fix the
computation of the remaining space.

  • assembler/MacroAssemblerARM.h:

(JSC::MacroAssemblerARM::branch32):
(JSC::MacroAssemblerARM::nearCall):
(JSC::MacroAssemblerARM::call):
(JSC::MacroAssemblerARM::branchPtrWithPatch):
(JSC::MacroAssemblerARM::ensureSpace):
(JSC::MacroAssemblerARM::sizeOfConstantPool):
(JSC::MacroAssemblerARM::prepareCall):

  • assembler/X86Assembler.h:
  • jit/JIT.h:
  • jit/JITCall.cpp:

(JSC::JIT::compileOpCall):

  • jit/JITInlineMethods.h:

(JSC::JIT::beginUninterruptedSequence):
(JSC::JIT::endUninterruptedSequence):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emit_op_method_check):
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::compileGetByIdSlowCase):
(JSC::JIT::emit_op_put_by_id):

File size: 22.4 KB
Line 
1/*
2 * Copyright (C) 2009 University of Szeged
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifndef ARMAssembler_h
28#define ARMAssembler_h
29
30#include <wtf/Platform.h>
31
32#if ENABLE(ASSEMBLER) && PLATFORM(ARM)
33
34#include "AssemblerBufferWithConstantPool.h"
35#include <wtf/Assertions.h>
36namespace JSC {
37
38typedef uint32_t ARMWord;
39
40namespace ARM {
41 typedef enum {
42 r0 = 0,
43 r1,
44 r2,
45 r3,
46 S0 = r3,
47 r4,
48 r5,
49 r6,
50 r7,
51 r8,
52 S1 = r8,
53 r9,
54 r10,
55 r11,
56 r12,
57 r13,
58 sp = r13,
59 r14,
60 lr = r14,
61 r15,
62 pc = r15
63 } RegisterID;
64
65 typedef enum {
66 d0,
67 d1,
68 d2,
69 d3,
70 SD0 = d3
71 } FPRegisterID;
72
73} // namespace ARM
74
75 class ARMAssembler {
76 public:
77 typedef ARM::RegisterID RegisterID;
78 typedef ARM::FPRegisterID FPRegisterID;
79 typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
80 typedef WTF::SegmentedVector<int, 64> Jumps;
81
82 ARMAssembler() { }
83
84 // ARM conditional constants
85 typedef enum {
86 EQ = 0x00000000, // Zero
87 NE = 0x10000000, // Non-zero
88 CS = 0x20000000,
89 CC = 0x30000000,
90 MI = 0x40000000,
91 PL = 0x50000000,
92 VS = 0x60000000,
93 VC = 0x70000000,
94 HI = 0x80000000,
95 LS = 0x90000000,
96 GE = 0xa0000000,
97 LT = 0xb0000000,
98 GT = 0xc0000000,
99 LE = 0xd0000000,
100 AL = 0xe0000000
101 } Condition;
102
103 // ARM instruction constants
104 enum {
105 AND = (0x0 << 21),
106 EOR = (0x1 << 21),
107 SUB = (0x2 << 21),
108 RSB = (0x3 << 21),
109 ADD = (0x4 << 21),
110 ADC = (0x5 << 21),
111 SBC = (0x6 << 21),
112 RSC = (0x7 << 21),
113 TST = (0x8 << 21),
114 TEQ = (0x9 << 21),
115 CMP = (0xa << 21),
116 CMN = (0xb << 21),
117 ORR = (0xc << 21),
118 MOV = (0xd << 21),
119 BIC = (0xe << 21),
120 MVN = (0xf << 21),
121 MUL = 0x00000090,
122 MULL = 0x00c00090,
123 FADDD = 0x0e300b00,
124 FSUBD = 0x0e300b40,
125 FMULD = 0x0e200b00,
126 FCMPD = 0x0eb40b40,
127 DTR = 0x05000000,
128 LDRH = 0x00100090,
129 STRH = 0x00000090,
130 STMDB = 0x09200000,
131 LDMIA = 0x08b00000,
132 FDTR = 0x0d000b00,
133 B = 0x0a000000,
134 BL = 0x0b000000,
135 FMSR = 0x0e000a10,
136 FSITOD = 0x0eb80bc0,
137 FMSTAT = 0x0ef1fa10,
138#if ARM_ARCH_VERSION >= 5
139 CLZ = 0x016f0f10,
140 BKPT = 0xe120070,
141#endif
142 };
143
144 enum {
145 OP2_IMM = (1 << 25),
146 OP2_IMMh = (1 << 22),
147 OP2_INV_IMM = (1 << 26),
148 SET_CC = (1 << 20),
149 OP2_OFSREG = (1 << 25),
150 DT_UP = (1 << 23),
151 DT_WB = (1 << 21),
152 // This flag is inlcuded in LDR and STR
153 DT_PRE = (1 << 24),
154 HDT_UH = (1 << 5),
155 DT_LOAD = (1 << 20),
156 };
157
158 // Masks of ARM instructions
159 enum {
160 BRANCH_MASK = 0x00ffffff,
161 NONARM = 0xf0000000,
162 SDT_MASK = 0x0c000000,
163 SDT_OFFSET_MASK = 0xfff,
164 };
165
166 enum {
167 BOFFSET_MIN = -0x00800000,
168 BOFFSET_MAX = 0x007fffff,
169 SDT = 0x04000000,
170 };
171
172 enum {
173 padForAlign8 = 0x00,
174 padForAlign16 = 0x0000,
175 padForAlign32 = 0xee120070,
176 };
177
178 class JmpSrc {
179 friend class ARMAssembler;
180 public:
181 JmpSrc()
182 : m_offset(-1)
183 {
184 }
185
186 private:
187 JmpSrc(int offset)
188 : m_offset(offset)
189 {
190 }
191
192 int m_offset;
193 };
194
195 class JmpDst {
196 friend class ARMAssembler;
197 public:
198 JmpDst()
199 : m_offset(-1)
200 , m_used(false)
201 {
202 }
203
204 bool isUsed() const { return m_used; }
205 void used() { m_used = true; }
206 private:
207 JmpDst(int offset)
208 : m_offset(offset)
209 , m_used(false)
210 {
211 ASSERT(m_offset == offset);
212 }
213
214 int m_offset : 31;
215 int m_used : 1;
216 };
217
218 // Instruction formating
219
220 void emitInst(ARMWord op, int rd, int rn, ARMWord op2)
221 {
222 ASSERT ( ((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)) );
223 m_buffer.putInt(op | RN(rn) | RD(rd) | op2);
224 }
225
226 void and_r(int rd, int rn, ARMWord op2, Condition cc = AL)
227 {
228 emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2);
229 }
230
231 void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL)
232 {
233 emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2);
234 }
235
236 void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL)
237 {
238 emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2);
239 }
240
241 void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL)
242 {
243 emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2);
244 }
245
246 void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL)
247 {
248 emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2);
249 }
250
251 void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
252 {
253 emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2);
254 }
255
256 void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL)
257 {
258 emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2);
259 }
260
261 void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
262 {
263 emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2);
264 }
265
266 void add_r(int rd, int rn, ARMWord op2, Condition cc = AL)
267 {
268 emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2);
269 }
270
271 void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL)
272 {
273 emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2);
274 }
275
276 void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
277 {
278 emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2);
279 }
280
281 void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
282 {
283 emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2);
284 }
285
286 void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
287 {
288 emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2);
289 }
290
291 void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
292 {
293 emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2);
294 }
295
296 void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
297 {
298 emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2);
299 }
300
301 void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
302 {
303 emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2);
304 }
305
306 void tst_r(int rn, ARMWord op2, Condition cc = AL)
307 {
308 emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2);
309 }
310
311 void teq_r(int rn, ARMWord op2, Condition cc = AL)
312 {
313 emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2);
314 }
315
316 void cmp_r(int rn, ARMWord op2, Condition cc = AL)
317 {
318 emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
319 }
320
321 void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
322 {
323 emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
324 }
325
326 void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
327 {
328 emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2);
329 }
330
331 void mov_r(int rd, ARMWord op2, Condition cc = AL)
332 {
333 emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARM::r0, op2);
334 }
335
336 void movs_r(int rd, ARMWord op2, Condition cc = AL)
337 {
338 emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARM::r0, op2);
339 }
340
341 void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL)
342 {
343 emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2);
344 }
345
346 void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL)
347 {
348 emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2);
349 }
350
351 void mvn_r(int rd, ARMWord op2, Condition cc = AL)
352 {
353 emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARM::r0, op2);
354 }
355
356 void mvns_r(int rd, ARMWord op2, Condition cc = AL)
357 {
358 emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARM::r0, op2);
359 }
360
361 void mul_r(int rd, int rn, int rm, Condition cc = AL)
362 {
363 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm));
364 }
365
366 void muls_r(int rd, int rn, int rm, Condition cc = AL)
367 {
368 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm));
369 }
370
371 void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL)
372 {
373 m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm));
374 }
375
376 void faddd_r(int dd, int dn, int dm, Condition cc = AL)
377 {
378 emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm);
379 }
380
381 void fsubd_r(int dd, int dn, int dm, Condition cc = AL)
382 {
383 emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm);
384 }
385
386 void fmuld_r(int dd, int dn, int dm, Condition cc = AL)
387 {
388 emitInst(static_cast<ARMWord>(cc) | FMULD, dd, dn, dm);
389 }
390
391 void fcmpd_r(int dd, int dm, Condition cc = AL)
392 {
393 emitInst(static_cast<ARMWord>(cc) | FCMPD, dd, 0, dm);
394 }
395
396 void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
397 {
398 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARM::pc) | RD(rd), imm, true);
399 }
400
401 void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL)
402 {
403 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARM::pc) | RD(rd), imm);
404 }
405
406 void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
407 {
408 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2);
409 }
410
411 void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
412 {
413 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm);
414 }
415
416 void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
417 {
418 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
419 }
420
421 void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
422 {
423 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm);
424 }
425
426 void ldrh_r(int rd, int rn, int rm, Condition cc = AL)
427 {
428 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
429 }
430
431 void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL)
432 {
433 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2);
434 }
435
436 void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL)
437 {
438 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2);
439 }
440
441 void strh_r(int rn, int rm, int rd, Condition cc = AL)
442 {
443 emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
444 }
445
446 void fdtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
447 {
448 ASSERT(op2 <= 0xff);
449 emitInst(static_cast<ARMWord>(cc) | FDTR | DT_UP | (isLoad ? DT_LOAD : 0), rd, rb, op2);
450 }
451
452 void fdtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
453 {
454 ASSERT(op2 <= 0xff);
455 emitInst(static_cast<ARMWord>(cc) | FDTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
456 }
457
458 void push_r(int reg, Condition cc = AL)
459 {
460 ASSERT(ARMWord(reg) <= 0xf);
461 m_buffer.putInt(cc | DTR | DT_WB | RN(ARM::sp) | RD(reg) | 0x4);
462 }
463
464 void pop_r(int reg, Condition cc = AL)
465 {
466 ASSERT(ARMWord(reg) <= 0xf);
467 m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARM::sp) | RD(reg) | 0x4);
468 }
469
470 inline void poke_r(int reg, Condition cc = AL)
471 {
472 dtr_d(false, ARM::sp, 0, reg, cc);
473 }
474
475 inline void peek_r(int reg, Condition cc = AL)
476 {
477 dtr_u(true, reg, ARM::sp, 0, cc);
478 }
479
480 void fmsr_r(int dd, int rn, Condition cc = AL)
481 {
482 emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0);
483 }
484
485 void fsitod_r(int dd, int dm, Condition cc = AL)
486 {
487 emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm);
488 }
489
490 void fmstat(Condition cc = AL)
491 {
492 m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT);
493 }
494
495#if ARM_ARCH_VERSION >= 5
496 void clz_r(int rd, int rm, Condition cc = AL)
497 {
498 m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm));
499 }
500#endif
501
502 void bkpt(ARMWord value)
503 {
504#if ARM_ARCH_VERSION >= 5
505 m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf));
506#else
507 // Cannot access to Zero memory address
508 dtr_dr(true, ARM::S0, ARM::S0, ARM::S0);
509#endif
510 }
511
512 static ARMWord lsl(int reg, ARMWord value)
513 {
514 ASSERT(reg <= ARM::pc);
515 ASSERT(value <= 0x1f);
516 return reg | (value << 7) | 0x00;
517 }
518
519 static ARMWord lsr(int reg, ARMWord value)
520 {
521 ASSERT(reg <= ARM::pc);
522 ASSERT(value <= 0x1f);
523 return reg | (value << 7) | 0x20;
524 }
525
526 static ARMWord asr(int reg, ARMWord value)
527 {
528 ASSERT(reg <= ARM::pc);
529 ASSERT(value <= 0x1f);
530 return reg | (value << 7) | 0x40;
531 }
532
533 static ARMWord lsl_r(int reg, int shiftReg)
534 {
535 ASSERT(reg <= ARM::pc);
536 ASSERT(shiftReg <= ARM::pc);
537 return reg | (shiftReg << 8) | 0x10;
538 }
539
540 static ARMWord lsr_r(int reg, int shiftReg)
541 {
542 ASSERT(reg <= ARM::pc);
543 ASSERT(shiftReg <= ARM::pc);
544 return reg | (shiftReg << 8) | 0x30;
545 }
546
547 static ARMWord asr_r(int reg, int shiftReg)
548 {
549 ASSERT(reg <= ARM::pc);
550 ASSERT(shiftReg <= ARM::pc);
551 return reg | (shiftReg << 8) | 0x50;
552 }
553
554 // General helpers
555
556 int size()
557 {
558 return m_buffer.size();
559 }
560
561 void ensureSpace(int insnSpace, int constSpace)
562 {
563 m_buffer.ensureSpace(insnSpace, constSpace);
564 }
565
566 int sizeOfConstantPool()
567 {
568 return m_buffer.sizeOfConstantPool();
569 }
570
571 JmpDst label()
572 {
573 return JmpDst(m_buffer.size());
574 }
575
576 JmpDst align(int alignment)
577 {
578 while (!m_buffer.isAligned(alignment))
579 mov_r(ARM::r0, ARM::r0);
580
581 return label();
582 }
583
584 JmpSrc jmp(Condition cc = AL, int useConstantPool = 0)
585 {
586 ensureSpace(sizeof(ARMWord), sizeof(ARMWord));
587 int s = m_buffer.uncheckedSize();
588 ldr_un_imm(ARM::pc, 0xffffffff, cc);
589 m_jumps.append(s | (useConstantPool & 0x1));
590 return JmpSrc(s);
591 }
592
593 void* executableCopy(ExecutablePool* allocator);
594
595 // Patching helpers
596
597 static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0);
598 static void linkBranch(void* code, JmpSrc from, void* to, int useConstantPool = 0);
599
600 static void patchPointerInternal(intptr_t from, void* to)
601 {
602 ARMWord* insn = reinterpret_cast<ARMWord*>(from);
603 ARMWord* addr = getLdrImmAddress(insn);
604 *addr = reinterpret_cast<ARMWord>(to);
605 ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord));
606 }
607
608 static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
609 {
610 value = (value << 1) + 1;
611 ASSERT(!(value & ~0xfff));
612 return (load & ~0xfff) | value;
613 }
614
615 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
616
617 // Patch pointers
618
619 static void linkPointer(void* code, JmpDst from, void* to)
620 {
621 patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
622 }
623
624 static void repatchInt32(void* from, int32_t to)
625 {
626 patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to));
627 }
628
629 static void repatchPointer(void* from, void* to)
630 {
631 patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
632 }
633
634 static void repatchLoadPtrToLEA(void* from)
635 {
636 // On arm, this is a patch from LDR to ADD. It is restricted conversion,
637 // from special case to special case, altough enough for its purpose
638 ARMWord* insn = reinterpret_cast<ARMWord*>(from);
639 ASSERT((*insn & 0x0ff00f00) == 0x05900000);
640
641 *insn = (*insn & 0xf00ff0ff) | 0x02800000;
642 ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord));
643 }
644
645 // Linkers
646
647 void linkJump(JmpSrc from, JmpDst to)
648 {
649 ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
650 *getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset);
651 }
652
653 static void linkJump(void* code, JmpSrc from, void* to)
654 {
655 linkBranch(code, from, to);
656 }
657
658 static void relinkJump(void* from, void* to)
659 {
660 patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
661 }
662
663 static void linkCall(void* code, JmpSrc from, void* to)
664 {
665 linkBranch(code, from, to, true);
666 }
667
668 static void relinkCall(void* from, void* to)
669 {
670 relinkJump(from, to);
671 }
672
673 // Address operations
674
675 static void* getRelocatedAddress(void* code, JmpSrc jump)
676 {
677 return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord) + 1);
678 }
679
680 static void* getRelocatedAddress(void* code, JmpDst label)
681 {
682 return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + label.m_offset / sizeof(ARMWord));
683 }
684
685 // Address differences
686
687 static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
688 {
689 return (to.m_offset + sizeof(ARMWord)) - from.m_offset;
690 }
691
692 static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
693 {
694 return to.m_offset - from.m_offset;
695 }
696
697 static unsigned getCallReturnOffset(JmpSrc call)
698 {
699 return call.m_offset + sizeof(ARMWord);
700 }
701
702 // Handle immediates
703
704 static ARMWord getOp2Byte(ARMWord imm)
705 {
706 ASSERT(imm <= 0xff);
707 return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ;
708 }
709
710 static ARMWord getOp2(ARMWord imm);
711 ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false);
712 void moveImm(ARMWord imm, int dest);
713
714 // Memory load/store helpers
715
716 void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset);
717 void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset);
718 void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset);
719
720 // Constant pool hnadlers
721
722 static ARMWord placeConstantPoolBarrier(int offset)
723 {
724 offset = (offset - sizeof(ARMWord)) >> 2;
725 ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN));
726 return AL | B | (offset & BRANCH_MASK);
727 }
728
729 private:
730 ARMWord RM(int reg)
731 {
732 ASSERT(reg <= ARM::pc);
733 return reg;
734 }
735
736 ARMWord RS(int reg)
737 {
738 ASSERT(reg <= ARM::pc);
739 return reg << 8;
740 }
741
742 ARMWord RD(int reg)
743 {
744 ASSERT(reg <= ARM::pc);
745 return reg << 12;
746 }
747
748 ARMWord RN(int reg)
749 {
750 ASSERT(reg <= ARM::pc);
751 return reg << 16;
752 }
753
754 static ARMWord getConditionalField(ARMWord i)
755 {
756 return i & 0xf0000000;
757 }
758
759 int genInt(int reg, ARMWord imm, bool positive);
760
761 ARMBuffer m_buffer;
762 Jumps m_jumps;
763 };
764
765} // namespace JSC
766
767#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM)
768
769#endif // ARMAssembler_h
Note: See TracBrowser for help on using the repository browser.