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

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

2009-07-17 Gabor Loki <[email protected]>

Reviewed by Gavin Barraclough.

Add YARR support for generic ARM platforms (disabled by default).
https://bugs.webkit.org/show_bug.cgi?id=24986

Add generic ARM port for MacroAssembler. It supports the whole
MacroAssembler functionality except floating point.

The class JmpSrc is extended with a flag which enables to patch
the jump destination offset during execution. This feature is
required for generic ARM port.

Signed off by Zoltan Herczeg <[email protected]>
Signed off by Gabor Loki <[email protected]>

  • JavaScriptCore.pri:
  • assembler/ARMAssembler.cpp: Added. (JSC::ARMAssembler::getLdrImmAddress): (JSC::ARMAssembler::linkBranch): (JSC::ARMAssembler::patchConstantPoolLoad): (JSC::ARMAssembler::getOp2): (JSC::ARMAssembler::genInt): (JSC::ARMAssembler::getImm): (JSC::ARMAssembler::moveImm): (JSC::ARMAssembler::dataTransfer32): (JSC::ARMAssembler::baseIndexTransfer32): (JSC::ARMAssembler::executableCopy):
  • assembler/ARMAssembler.h: Added. (JSC::ARM::): (JSC::ARMAssembler::ARMAssembler): (JSC::ARMAssembler::): (JSC::ARMAssembler::JmpSrc::JmpSrc): (JSC::ARMAssembler::JmpSrc::enableLatePatch): (JSC::ARMAssembler::JmpDst::JmpDst): (JSC::ARMAssembler::JmpDst::isUsed): (JSC::ARMAssembler::JmpDst::used): (JSC::ARMAssembler::emitInst): (JSC::ARMAssembler::and_r): (JSC::ARMAssembler::ands_r): (JSC::ARMAssembler::eor_r): (JSC::ARMAssembler::eors_r): (JSC::ARMAssembler::sub_r): (JSC::ARMAssembler::subs_r): (JSC::ARMAssembler::rsb_r): (JSC::ARMAssembler::rsbs_r): (JSC::ARMAssembler::add_r): (JSC::ARMAssembler::adds_r): (JSC::ARMAssembler::adc_r): (JSC::ARMAssembler::adcs_r): (JSC::ARMAssembler::sbc_r): (JSC::ARMAssembler::sbcs_r): (JSC::ARMAssembler::rsc_r): (JSC::ARMAssembler::rscs_r): (JSC::ARMAssembler::tst_r): (JSC::ARMAssembler::teq_r): (JSC::ARMAssembler::cmp_r): (JSC::ARMAssembler::orr_r): (JSC::ARMAssembler::orrs_r): (JSC::ARMAssembler::mov_r): (JSC::ARMAssembler::movs_r): (JSC::ARMAssembler::bic_r): (JSC::ARMAssembler::bics_r): (JSC::ARMAssembler::mvn_r): (JSC::ARMAssembler::mvns_r): (JSC::ARMAssembler::mul_r): (JSC::ARMAssembler::muls_r): (JSC::ARMAssembler::mull_r): (JSC::ARMAssembler::ldr_imm): (JSC::ARMAssembler::ldr_un_imm): (JSC::ARMAssembler::dtr_u): (JSC::ARMAssembler::dtr_ur): (JSC::ARMAssembler::dtr_d): (JSC::ARMAssembler::dtr_dr): (JSC::ARMAssembler::ldrh_r): (JSC::ARMAssembler::ldrh_d): (JSC::ARMAssembler::ldrh_u): (JSC::ARMAssembler::strh_r): (JSC::ARMAssembler::push_r): (JSC::ARMAssembler::pop_r): (JSC::ARMAssembler::poke_r): (JSC::ARMAssembler::peek_r): (JSC::ARMAssembler::clz_r): (JSC::ARMAssembler::bkpt): (JSC::ARMAssembler::lsl): (JSC::ARMAssembler::lsr): (JSC::ARMAssembler::asr): (JSC::ARMAssembler::lsl_r): (JSC::ARMAssembler::lsr_r): (JSC::ARMAssembler::asr_r): (JSC::ARMAssembler::size): (JSC::ARMAssembler::ensureSpace): (JSC::ARMAssembler::label): (JSC::ARMAssembler::align): (JSC::ARMAssembler::jmp): (JSC::ARMAssembler::patchPointerInternal): (JSC::ARMAssembler::patchConstantPoolLoad): (JSC::ARMAssembler::patchPointer): (JSC::ARMAssembler::repatchInt32): (JSC::ARMAssembler::repatchPointer): (JSC::ARMAssembler::repatchLoadPtrToLEA): (JSC::ARMAssembler::linkJump): (JSC::ARMAssembler::relinkJump): (JSC::ARMAssembler::linkCall): (JSC::ARMAssembler::relinkCall): (JSC::ARMAssembler::getRelocatedAddress): (JSC::ARMAssembler::getDifferenceBetweenLabels): (JSC::ARMAssembler::getCallReturnOffset): (JSC::ARMAssembler::getOp2Byte): (JSC::ARMAssembler::placeConstantPoolBarrier): (JSC::ARMAssembler::RM): (JSC::ARMAssembler::RS): (JSC::ARMAssembler::RD): (JSC::ARMAssembler::RN): (JSC::ARMAssembler::getConditionalField):
  • assembler/ARMv7Assembler.h: (JSC::ARMv7Assembler::JmpSrc::enableLatePatch):
  • assembler/AbstractMacroAssembler.h: (JSC::AbstractMacroAssembler::Call::enableLatePatch): (JSC::AbstractMacroAssembler::Jump::enableLatePatch):
  • assembler/MacroAssembler.h:
  • assembler/MacroAssemblerARM.h: Added. (JSC::MacroAssemblerARM::): (JSC::MacroAssemblerARM::add32): (JSC::MacroAssemblerARM::and32): (JSC::MacroAssemblerARM::lshift32): (JSC::MacroAssemblerARM::mul32): (JSC::MacroAssemblerARM::not32): (JSC::MacroAssemblerARM::or32): (JSC::MacroAssemblerARM::rshift32): (JSC::MacroAssemblerARM::sub32): (JSC::MacroAssemblerARM::xor32): (JSC::MacroAssemblerARM::load32): (JSC::MacroAssemblerARM::load32WithAddressOffsetPatch): (JSC::MacroAssemblerARM::loadPtrWithPatchToLEA): (JSC::MacroAssemblerARM::load16): (JSC::MacroAssemblerARM::store32WithAddressOffsetPatch): (JSC::MacroAssemblerARM::store32): (JSC::MacroAssemblerARM::pop): (JSC::MacroAssemblerARM::push): (JSC::MacroAssemblerARM::move): (JSC::MacroAssemblerARM::swap): (JSC::MacroAssemblerARM::signExtend32ToPtr): (JSC::MacroAssemblerARM::zeroExtend32ToPtr): (JSC::MacroAssemblerARM::branch32): (JSC::MacroAssemblerARM::branch16): (JSC::MacroAssemblerARM::branchTest32): (JSC::MacroAssemblerARM::jump): (JSC::MacroAssemblerARM::branchAdd32): (JSC::MacroAssemblerARM::mull32): (JSC::MacroAssemblerARM::branchMul32): (JSC::MacroAssemblerARM::branchSub32): (JSC::MacroAssemblerARM::breakpoint): (JSC::MacroAssemblerARM::nearCall): (JSC::MacroAssemblerARM::call): (JSC::MacroAssemblerARM::ret): (JSC::MacroAssemblerARM::set32): (JSC::MacroAssemblerARM::setTest32): (JSC::MacroAssemblerARM::tailRecursiveCall): (JSC::MacroAssemblerARM::makeTailRecursiveCall): (JSC::MacroAssemblerARM::moveWithPatch): (JSC::MacroAssemblerARM::branchPtrWithPatch): (JSC::MacroAssemblerARM::storePtrWithPatch): (JSC::MacroAssemblerARM::supportsFloatingPoint): (JSC::MacroAssemblerARM::supportsFloatingPointTruncate): (JSC::MacroAssemblerARM::loadDouble): (JSC::MacroAssemblerARM::storeDouble): (JSC::MacroAssemblerARM::addDouble): (JSC::MacroAssemblerARM::subDouble): (JSC::MacroAssemblerARM::mulDouble): (JSC::MacroAssemblerARM::convertInt32ToDouble): (JSC::MacroAssemblerARM::branchDouble): (JSC::MacroAssemblerARM::branchTruncateDoubleToInt32): (JSC::MacroAssemblerARM::ARMCondition): (JSC::MacroAssemblerARM::prepareCall): (JSC::MacroAssemblerARM::call32):
  • assembler/X86Assembler.h: (JSC::X86Assembler::JmpSrc::enableLatePatch):
  • jit/ExecutableAllocator.h: (JSC::ExecutableAllocator::cacheFlush):
  • wtf/Platform.h:
  • yarr/RegexJIT.cpp: (JSC::Yarr::RegexGenerator::generateEnter): (JSC::Yarr::RegexGenerator::generateReturn):
File size: 20.5 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 fp0 //FIXME
67 } FPRegisterID;
68} // namespace ARM
69
70 class ARMAssembler {
71 public:
72 typedef ARM::RegisterID RegisterID;
73 typedef ARM::FPRegisterID FPRegisterID;
74 typedef AssemblerBufferWithConstantPool<2048, 4, 4, ARMAssembler> ARMBuffer;
75 typedef WTF::SegmentedVector<int, 64> Jumps;
76
77 ARMAssembler() { }
78
79 // ARM conditional constants
80 typedef enum {
81 EQ = 0x00000000, // Zero
82 NE = 0x10000000, // Non-zero
83 CS = 0x20000000,
84 CC = 0x30000000,
85 MI = 0x40000000,
86 PL = 0x50000000,
87 VS = 0x60000000,
88 VC = 0x70000000,
89 HI = 0x80000000,
90 LS = 0x90000000,
91 GE = 0xa0000000,
92 LT = 0xb0000000,
93 GT = 0xc0000000,
94 LE = 0xd0000000,
95 AL = 0xe0000000
96 } Condition;
97
98 // ARM instruction constants
99 enum {
100 AND = (0x0 << 21),
101 EOR = (0x1 << 21),
102 SUB = (0x2 << 21),
103 RSB = (0x3 << 21),
104 ADD = (0x4 << 21),
105 ADC = (0x5 << 21),
106 SBC = (0x6 << 21),
107 RSC = (0x7 << 21),
108 TST = (0x8 << 21),
109 TEQ = (0x9 << 21),
110 CMP = (0xa << 21),
111 CMN = (0xb << 21),
112 ORR = (0xc << 21),
113 MOV = (0xd << 21),
114 BIC = (0xe << 21),
115 MVN = (0xf << 21),
116 MUL = 0x00000090,
117 MULL = 0x00c00090,
118 DTR = 0x05000000,
119 LDRH = 0x00100090,
120 STRH = 0x00000090,
121 STMDB = 0x09200000,
122 LDMIA = 0x08b00000,
123 B = 0x0a000000,
124 BL = 0x0b000000,
125#if ARM_ARCH_VERSION >= 5
126 CLZ = 0x016f0f10,
127 BKPT = 0xe120070,
128#endif
129 };
130
131 enum {
132 OP2_IMM = (1 << 25),
133 OP2_IMMh = (1 << 22),
134 OP2_INV_IMM = (1 << 26),
135 SET_CC = (1 << 20),
136 OP2_OFSREG = (1 << 25),
137 DT_UP = (1 << 23),
138 DT_WB = (1 << 21),
139 // This flag is inlcuded in LDR and STR
140 DT_PRE = (1 << 24),
141 HDT_UH = (1 << 5),
142 DT_LOAD = (1 << 20),
143 };
144
145 // Masks of ARM instructions
146 enum {
147 BRANCH_MASK = 0x00ffffff,
148 NONARM = 0xf0000000,
149 SDT_MASK = 0x0c000000,
150 SDT_OFFSET_MASK = 0xfff,
151 };
152
153 enum {
154 BOFFSET_MIN = -0x00800000,
155 BOFFSET_MAX = 0x007fffff,
156 SDT = 0x04000000,
157 };
158
159 enum {
160 padForAlign8 = 0x00,
161 padForAlign16 = 0x0000,
162 padForAlign32 = 0xee120070,
163 };
164
165 class JmpSrc {
166 friend class ARMAssembler;
167 public:
168 JmpSrc()
169 : m_offset(-1)
170 , m_latePatch(false)
171 {
172 }
173
174 void enableLatePatch() { m_latePatch = true; }
175 private:
176 JmpSrc(int offset)
177 : m_offset(offset)
178 , m_latePatch(false)
179 {
180 }
181
182 int m_offset : 31;
183 int m_latePatch : 1;
184 };
185
186 class JmpDst {
187 friend class ARMAssembler;
188 public:
189 JmpDst()
190 : m_offset(-1)
191 , m_used(false)
192 {
193 }
194
195 bool isUsed() const { return m_used; }
196 void used() { m_used = true; }
197 private:
198 JmpDst(int offset)
199 : m_offset(offset)
200 , m_used(false)
201 {
202 ASSERT(m_offset == offset);
203 }
204
205 int m_offset : 31;
206 int m_used : 1;
207 };
208
209 // Instruction formating
210
211 void emitInst(ARMWord op, int rd, int rn, ARMWord op2)
212 {
213 ASSERT ( ((op2 & ~OP2_IMM) <= 0xfff) || (((op2 & ~OP2_IMMh) <= 0xfff)) );
214 m_buffer.putInt(op | RN(rn) | RD(rd) | op2);
215 }
216
217 void and_r(int rd, int rn, ARMWord op2, Condition cc = AL)
218 {
219 emitInst(static_cast<ARMWord>(cc) | AND, rd, rn, op2);
220 }
221
222 void ands_r(int rd, int rn, ARMWord op2, Condition cc = AL)
223 {
224 emitInst(static_cast<ARMWord>(cc) | AND | SET_CC, rd, rn, op2);
225 }
226
227 void eor_r(int rd, int rn, ARMWord op2, Condition cc = AL)
228 {
229 emitInst(static_cast<ARMWord>(cc) | EOR, rd, rn, op2);
230 }
231
232 void eors_r(int rd, int rn, ARMWord op2, Condition cc = AL)
233 {
234 emitInst(static_cast<ARMWord>(cc) | EOR | SET_CC, rd, rn, op2);
235 }
236
237 void sub_r(int rd, int rn, ARMWord op2, Condition cc = AL)
238 {
239 emitInst(static_cast<ARMWord>(cc) | SUB, rd, rn, op2);
240 }
241
242 void subs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
243 {
244 emitInst(static_cast<ARMWord>(cc) | SUB | SET_CC, rd, rn, op2);
245 }
246
247 void rsb_r(int rd, int rn, ARMWord op2, Condition cc = AL)
248 {
249 emitInst(static_cast<ARMWord>(cc) | RSB, rd, rn, op2);
250 }
251
252 void rsbs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
253 {
254 emitInst(static_cast<ARMWord>(cc) | RSB | SET_CC, rd, rn, op2);
255 }
256
257 void add_r(int rd, int rn, ARMWord op2, Condition cc = AL)
258 {
259 emitInst(static_cast<ARMWord>(cc) | ADD, rd, rn, op2);
260 }
261
262 void adds_r(int rd, int rn, ARMWord op2, Condition cc = AL)
263 {
264 emitInst(static_cast<ARMWord>(cc) | ADD | SET_CC, rd, rn, op2);
265 }
266
267 void adc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
268 {
269 emitInst(static_cast<ARMWord>(cc) | ADC, rd, rn, op2);
270 }
271
272 void adcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
273 {
274 emitInst(static_cast<ARMWord>(cc) | ADC | SET_CC, rd, rn, op2);
275 }
276
277 void sbc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
278 {
279 emitInst(static_cast<ARMWord>(cc) | SBC, rd, rn, op2);
280 }
281
282 void sbcs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
283 {
284 emitInst(static_cast<ARMWord>(cc) | SBC | SET_CC, rd, rn, op2);
285 }
286
287 void rsc_r(int rd, int rn, ARMWord op2, Condition cc = AL)
288 {
289 emitInst(static_cast<ARMWord>(cc) | RSC, rd, rn, op2);
290 }
291
292 void rscs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
293 {
294 emitInst(static_cast<ARMWord>(cc) | RSC | SET_CC, rd, rn, op2);
295 }
296
297 void tst_r(int rn, ARMWord op2, Condition cc = AL)
298 {
299 emitInst(static_cast<ARMWord>(cc) | TST | SET_CC, 0, rn, op2);
300 }
301
302 void teq_r(int rn, ARMWord op2, Condition cc = AL)
303 {
304 emitInst(static_cast<ARMWord>(cc) | TEQ | SET_CC, 0, rn, op2);
305 }
306
307 void cmp_r(int rn, ARMWord op2, Condition cc = AL)
308 {
309 emitInst(static_cast<ARMWord>(cc) | CMP | SET_CC, 0, rn, op2);
310 }
311
312 void orr_r(int rd, int rn, ARMWord op2, Condition cc = AL)
313 {
314 emitInst(static_cast<ARMWord>(cc) | ORR, rd, rn, op2);
315 }
316
317 void orrs_r(int rd, int rn, ARMWord op2, Condition cc = AL)
318 {
319 emitInst(static_cast<ARMWord>(cc) | ORR | SET_CC, rd, rn, op2);
320 }
321
322 void mov_r(int rd, ARMWord op2, Condition cc = AL)
323 {
324 emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARM::r0, op2);
325 }
326
327 void movs_r(int rd, ARMWord op2, Condition cc = AL)
328 {
329 emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARM::r0, op2);
330 }
331
332 void bic_r(int rd, int rn, ARMWord op2, Condition cc = AL)
333 {
334 emitInst(static_cast<ARMWord>(cc) | BIC, rd, rn, op2);
335 }
336
337 void bics_r(int rd, int rn, ARMWord op2, Condition cc = AL)
338 {
339 emitInst(static_cast<ARMWord>(cc) | BIC | SET_CC, rd, rn, op2);
340 }
341
342 void mvn_r(int rd, ARMWord op2, Condition cc = AL)
343 {
344 emitInst(static_cast<ARMWord>(cc) | MVN, rd, ARM::r0, op2);
345 }
346
347 void mvns_r(int rd, ARMWord op2, Condition cc = AL)
348 {
349 emitInst(static_cast<ARMWord>(cc) | MVN | SET_CC, rd, ARM::r0, op2);
350 }
351
352 void mul_r(int rd, int rn, int rm, Condition cc = AL)
353 {
354 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | RN(rd) | RS(rn) | RM(rm));
355 }
356
357 void muls_r(int rd, int rn, int rm, Condition cc = AL)
358 {
359 m_buffer.putInt(static_cast<ARMWord>(cc) | MUL | SET_CC | RN(rd) | RS(rn) | RM(rm));
360 }
361
362 void mull_r(int rdhi, int rdlo, int rn, int rm, Condition cc = AL)
363 {
364 m_buffer.putInt(static_cast<ARMWord>(cc) | MULL | RN(rdhi) | RD(rdlo) | RS(rn) | RM(rm));
365 }
366
367 void ldr_imm(int rd, ARMWord imm, Condition cc = AL)
368 {
369 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARM::pc) | RD(rd), imm, true);
370 }
371
372 void ldr_un_imm(int rd, ARMWord imm, Condition cc = AL)
373 {
374 m_buffer.putIntWithConstantInt(static_cast<ARMWord>(cc) | DTR | DT_LOAD | DT_UP | RN(ARM::pc) | RD(rd), imm);
375 }
376
377 void dtr_u(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
378 {
379 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP, rd, rb, op2);
380 }
381
382 void dtr_ur(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
383 {
384 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | DT_UP | OP2_OFSREG, rd, rb, rm);
385 }
386
387 void dtr_d(bool isLoad, int rd, int rb, ARMWord op2, Condition cc = AL)
388 {
389 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0), rd, rb, op2);
390 }
391
392 void dtr_dr(bool isLoad, int rd, int rb, int rm, Condition cc = AL)
393 {
394 emitInst(static_cast<ARMWord>(cc) | DTR | (isLoad ? DT_LOAD : 0) | OP2_OFSREG, rd, rb, rm);
395 }
396
397 void ldrh_r(int rd, int rn, int rm, Condition cc = AL)
398 {
399 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
400 }
401
402 void ldrh_d(int rd, int rb, ARMWord op2, Condition cc = AL)
403 {
404 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_PRE, rd, rb, op2);
405 }
406
407 void ldrh_u(int rd, int rb, ARMWord op2, Condition cc = AL)
408 {
409 emitInst(static_cast<ARMWord>(cc) | LDRH | HDT_UH | DT_UP | DT_PRE, rd, rb, op2);
410 }
411
412 void strh_r(int rn, int rm, int rd, Condition cc = AL)
413 {
414 emitInst(static_cast<ARMWord>(cc) | STRH | HDT_UH | DT_UP | DT_PRE, rd, rn, rm);
415 }
416
417 void push_r(int reg, Condition cc = AL)
418 {
419 ASSERT(ARMWord(reg) <= 0xf);
420 m_buffer.putInt(cc | DTR | DT_WB | RN(ARM::sp) | RD(reg) | 0x4);
421 }
422
423 void pop_r(int reg, Condition cc = AL)
424 {
425 ASSERT(ARMWord(reg) <= 0xf);
426 m_buffer.putInt(cc | (DTR ^ DT_PRE) | DT_LOAD | DT_UP | RN(ARM::sp) | RD(reg) | 0x4);
427 }
428
429 inline void poke_r(int reg, Condition cc = AL)
430 {
431 dtr_d(false, ARM::sp, 0, reg, cc);
432 }
433
434 inline void peek_r(int reg, Condition cc = AL)
435 {
436 dtr_u(true, reg, ARM::sp, 0, cc);
437 }
438
439#if ARM_ARCH_VERSION >= 5
440 void clz_r(int rd, int rm, Condition cc = AL)
441 {
442 m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm));
443 }
444#endif
445
446 void bkpt(ARMWord value)
447 {
448#if ARM_ARCH_VERSION >= 5
449 m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf));
450#else
451 // Cannot access to Zero memory address
452 dtr_dr(true, ARM::S0, ARM::S0, ARM::S0);
453#endif
454 }
455
456 static ARMWord lsl(int reg, ARMWord value)
457 {
458 ASSERT(reg <= ARM::pc);
459 ASSERT(value <= 0x1f);
460 return reg | (value << 7) | 0x00;
461 }
462
463 static ARMWord lsr(int reg, ARMWord value)
464 {
465 ASSERT(reg <= ARM::pc);
466 ASSERT(value <= 0x1f);
467 return reg | (value << 7) | 0x20;
468 }
469
470 static ARMWord asr(int reg, ARMWord value)
471 {
472 ASSERT(reg <= ARM::pc);
473 ASSERT(value <= 0x1f);
474 return reg | (value << 7) | 0x40;
475 }
476
477 static ARMWord lsl_r(int reg, int shiftReg)
478 {
479 ASSERT(reg <= ARM::pc);
480 ASSERT(shiftReg <= ARM::pc);
481 return reg | (shiftReg << 8) | 0x10;
482 }
483
484 static ARMWord lsr_r(int reg, int shiftReg)
485 {
486 ASSERT(reg <= ARM::pc);
487 ASSERT(shiftReg <= ARM::pc);
488 return reg | (shiftReg << 8) | 0x30;
489 }
490
491 static ARMWord asr_r(int reg, int shiftReg)
492 {
493 ASSERT(reg <= ARM::pc);
494 ASSERT(shiftReg <= ARM::pc);
495 return reg | (shiftReg << 8) | 0x50;
496 }
497
498 // General helpers
499
500 int size()
501 {
502 return m_buffer.size();
503 }
504
505 void ensureSpace(int insnSpace, int constSpace)
506 {
507 m_buffer.ensureSpace(insnSpace, constSpace);
508 }
509
510 JmpDst label()
511 {
512 return JmpDst(m_buffer.size());
513 }
514
515 JmpDst align(int alignment)
516 {
517 while (!m_buffer.isAligned(alignment))
518 mov_r(ARM::r0, ARM::r0);
519
520 return label();
521 }
522
523 JmpSrc jmp(Condition cc = AL)
524 {
525 int s = size();
526 ldr_un_imm(ARM::pc, 0xffffffff, cc);
527 m_jumps.append(s);
528 return JmpSrc(s);
529 }
530
531 void* executableCopy(ExecutablePool* allocator);
532
533 // Patching helpers
534
535 static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0);
536 static void linkBranch(void* code, JmpSrc from, void* to);
537
538 static void patchPointerInternal(intptr_t from, void* to)
539 {
540 ARMWord* insn = reinterpret_cast<ARMWord*>(from);
541 ARMWord* addr = getLdrImmAddress(insn);
542 ExecutableAllocator::MakeWritable unprotect(addr, sizeof(ARMWord));
543 *addr = reinterpret_cast<ARMWord>(to);
544 }
545
546 static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value)
547 {
548 value = (value << 1) + 1;
549 ASSERT(!(value & ~0xfff));
550 return (load & ~0xfff) | value;
551 }
552
553 static void patchConstantPoolLoad(void* loadAddr, void* constPoolAddr);
554
555 // Patch pointers
556
557 static void patchPointer(void* code, JmpDst from, void* to)
558 {
559 patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to);
560 }
561
562 static void repatchInt32(void* from, int32_t to)
563 {
564 patchPointerInternal(reinterpret_cast<intptr_t>(from), reinterpret_cast<void*>(to));
565 }
566
567 static void repatchPointer(void* from, void* to)
568 {
569 patchPointerInternal(reinterpret_cast<intptr_t>(from), to);
570 }
571
572 static void repatchLoadPtrToLEA(void* from)
573 {
574 // On arm, this is a patch from LDR to ADD. It is restricted conversion,
575 // from special case to special case, altough enough for its purpose
576 ARMWord* insn = reinterpret_cast<ARMWord*>(from);
577 ASSERT((*insn & 0x0ff00f00) == 0x05900000);
578
579 ExecutableAllocator::MakeWritable unprotect(insn, sizeof(ARMWord));
580 *insn = (*insn & 0xf00ff0ff) | 0x02800000;
581 }
582
583 // Linkers
584
585 void linkJump(JmpSrc from, JmpDst to)
586 {
587 ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord));
588 *getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset);
589 }
590
591 static void linkJump(void* code, JmpSrc from, void* to)
592 {
593 linkBranch(code, from, to);
594 }
595
596 static void relinkJump(void* from, void* to)
597 {
598 patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to);
599 }
600
601 static void linkCall(void* code, JmpSrc from, void* to)
602 {
603 linkBranch(code, from, to);
604 }
605
606 static void relinkCall(void* from, void* to)
607 {
608 relinkJump(from, to);
609 }
610
611 // Address operations
612
613 static void* getRelocatedAddress(void* code, JmpSrc jump)
614 {
615 return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + jump.m_offset / sizeof(ARMWord) + 1);
616 }
617
618 static void* getRelocatedAddress(void* code, JmpDst label)
619 {
620 return reinterpret_cast<void*>(reinterpret_cast<ARMWord*>(code) + label.m_offset / sizeof(ARMWord));
621 }
622
623 // Address differences
624
625 static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
626 {
627 return (to.m_offset + sizeof(ARMWord)) - from.m_offset;
628 }
629
630 static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
631 {
632 return to.m_offset - from.m_offset;
633 }
634
635 static unsigned getCallReturnOffset(JmpSrc call)
636 {
637 return call.m_offset + sizeof(ARMWord);
638 }
639
640 // Handle immediates
641
642 static ARMWord getOp2Byte(ARMWord imm)
643 {
644 ASSERT(imm <= 0xff);
645 return OP2_IMMh | (imm & 0x0f) | ((imm & 0xf0) << 4) ;
646 }
647
648 static ARMWord getOp2(ARMWord imm);
649 ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false);
650 void moveImm(ARMWord imm, int dest);
651
652 // Memory load/store helpers
653
654 void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset);
655 void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset);
656
657 // Constant pool hnadlers
658
659 static ARMWord placeConstantPoolBarrier(int offset)
660 {
661 offset = (offset - sizeof(ARMWord)) >> 2;
662 ASSERT((offset <= BOFFSET_MAX && offset >= BOFFSET_MIN));
663 return AL | B | (offset & BRANCH_MASK);
664 }
665
666 private:
667 ARMWord RM(int reg)
668 {
669 ASSERT(reg <= ARM::pc);
670 return reg;
671 }
672
673 ARMWord RS(int reg)
674 {
675 ASSERT(reg <= ARM::pc);
676 return reg << 8;
677 }
678
679 ARMWord RD(int reg)
680 {
681 ASSERT(reg <= ARM::pc);
682 return reg << 12;
683 }
684
685 ARMWord RN(int reg)
686 {
687 ASSERT(reg <= ARM::pc);
688 return reg << 16;
689 }
690
691 static ARMWord getConditionalField(ARMWord i)
692 {
693 return i & 0xf0000000;
694 }
695
696 int genInt(int reg, ARMWord imm, bool positive);
697
698 ARMBuffer m_buffer;
699 Jumps m_jumps;
700 };
701
702} // namespace JSC
703
704#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM)
705
706#endif // ARMAssembler_h
Note: See TracBrowser for help on using the repository browser.