blob: 3fcfec8db2caa9c830a62e68042298623d20d744 [file] [log] [blame]
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001/*
2 * Copyright (C) 2008 Apple Inc.
eric@webkit.org6a210e72010-04-22 13:24:56 +00003 * Copyright (C) 2009, 2010 University of Szeged
barraclough@apple.com5ea68952009-07-17 21:56:28 +00004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef MacroAssemblerARM_h
29#define MacroAssemblerARM_h
30
mjs@apple.comcc668212010-01-04 11:38:56 +000031#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
barraclough@apple.com5ea68952009-07-17 21:56:28 +000032
33#include "ARMAssembler.h"
34#include "AbstractMacroAssembler.h"
35
36namespace JSC {
37
38class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> {
ossy@webkit.orgcb981302009-11-06 07:28:56 +000039 static const int DoubleConditionMask = 0x0f;
40 static const int DoubleConditionBitSpecial = 0x10;
41 COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes);
barraclough@apple.com5ea68952009-07-17 21:56:28 +000042public:
barraclough@apple.comcdab3602010-07-01 22:56:58 +000043 typedef ARMRegisters::FPRegisterID FPRegisterID;
44
barraclough@apple.com5ea68952009-07-17 21:56:28 +000045 enum Condition {
46 Equal = ARMAssembler::EQ,
47 NotEqual = ARMAssembler::NE,
48 Above = ARMAssembler::HI,
49 AboveOrEqual = ARMAssembler::CS,
50 Below = ARMAssembler::CC,
51 BelowOrEqual = ARMAssembler::LS,
52 GreaterThan = ARMAssembler::GT,
53 GreaterThanOrEqual = ARMAssembler::GE,
54 LessThan = ARMAssembler::LT,
55 LessThanOrEqual = ARMAssembler::LE,
56 Overflow = ARMAssembler::VS,
57 Signed = ARMAssembler::MI,
58 Zero = ARMAssembler::EQ,
59 NonZero = ARMAssembler::NE
60 };
61
62 enum DoubleCondition {
ossy@webkit.orgcb981302009-11-06 07:28:56 +000063 // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
64 DoubleEqual = ARMAssembler::EQ,
65 DoubleNotEqual = ARMAssembler::NE | DoubleConditionBitSpecial,
barraclough@apple.com9ef61d52009-08-06 05:33:27 +000066 DoubleGreaterThan = ARMAssembler::GT,
67 DoubleGreaterThanOrEqual = ARMAssembler::GE,
ossy@webkit.orgcb981302009-11-06 07:28:56 +000068 DoubleLessThan = ARMAssembler::CC,
69 DoubleLessThanOrEqual = ARMAssembler::LS,
70 // If either operand is NaN, these conditions always evaluate to true.
71 DoubleEqualOrUnordered = ARMAssembler::EQ | DoubleConditionBitSpecial,
72 DoubleNotEqualOrUnordered = ARMAssembler::NE,
73 DoubleGreaterThanOrUnordered = ARMAssembler::HI,
74 DoubleGreaterThanOrEqualOrUnordered = ARMAssembler::CS,
barraclough@apple.com2ffca6f2009-11-04 23:59:14 +000075 DoubleLessThanOrUnordered = ARMAssembler::LT,
76 DoubleLessThanOrEqualOrUnordered = ARMAssembler::LE,
barraclough@apple.com5ea68952009-07-17 21:56:28 +000077 };
78
eric@webkit.org734dd062009-08-20 00:02:24 +000079 static const RegisterID stackPointerRegister = ARMRegisters::sp;
eric@webkit.org6fe95ae2009-10-26 22:49:23 +000080 static const RegisterID linkRegister = ARMRegisters::lr;
barraclough@apple.com5ea68952009-07-17 21:56:28 +000081
82 static const Scale ScalePtr = TimesFour;
83
84 void add32(RegisterID src, RegisterID dest)
85 {
86 m_assembler.adds_r(dest, dest, src);
87 }
88
89 void add32(Imm32 imm, Address address)
90 {
eric@webkit.org734dd062009-08-20 00:02:24 +000091 load32(address, ARMRegisters::S1);
92 add32(imm, ARMRegisters::S1);
93 store32(ARMRegisters::S1, address);
barraclough@apple.com5ea68952009-07-17 21:56:28 +000094 }
95
96 void add32(Imm32 imm, RegisterID dest)
97 {
eric@webkit.org734dd062009-08-20 00:02:24 +000098 m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +000099 }
100
101 void add32(Address src, RegisterID dest)
102 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000103 load32(src, ARMRegisters::S1);
104 add32(ARMRegisters::S1, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000105 }
106
107 void and32(RegisterID src, RegisterID dest)
108 {
109 m_assembler.ands_r(dest, dest, src);
110 }
111
112 void and32(Imm32 imm, RegisterID dest)
113 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000114 ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000115 if (w & ARMAssembler::OP2_INV_IMM)
116 m_assembler.bics_r(dest, dest, w & ~ARMAssembler::OP2_INV_IMM);
117 else
118 m_assembler.ands_r(dest, dest, w);
119 }
120
barraclough@apple.comc4a3fa82009-11-06 09:35:03 +0000121 void lshift32(RegisterID shift_amount, RegisterID dest)
122 {
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000123 ARMWord w = ARMAssembler::getOp2(0x1f);
124 ASSERT(w != ARMAssembler::INVALID_IMM);
125 m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
barraclough@apple.comc4a3fa82009-11-06 09:35:03 +0000126
127 m_assembler.movs_r(dest, m_assembler.lsl_r(dest, ARMRegisters::S0));
128 }
129
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000130 void lshift32(Imm32 imm, RegisterID dest)
131 {
132 m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
133 }
134
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000135 void mul32(RegisterID src, RegisterID dest)
136 {
137 if (src == dest) {
eric@webkit.org734dd062009-08-20 00:02:24 +0000138 move(src, ARMRegisters::S0);
139 src = ARMRegisters::S0;
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000140 }
141 m_assembler.muls_r(dest, dest, src);
142 }
143
144 void mul32(Imm32 imm, RegisterID src, RegisterID dest)
145 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000146 move(imm, ARMRegisters::S0);
147 m_assembler.muls_r(dest, src, ARMRegisters::S0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000148 }
149
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000150 void neg32(RegisterID srcDest)
151 {
152 m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2(0));
153 }
154
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000155 void not32(RegisterID dest)
156 {
157 m_assembler.mvns_r(dest, dest);
158 }
159
160 void or32(RegisterID src, RegisterID dest)
161 {
162 m_assembler.orrs_r(dest, dest, src);
163 }
164
165 void or32(Imm32 imm, RegisterID dest)
166 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000167 m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000168 }
169
170 void rshift32(RegisterID shift_amount, RegisterID dest)
171 {
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000172 ARMWord w = ARMAssembler::getOp2(0x1f);
173 ASSERT(w != ARMAssembler::INVALID_IMM);
174 m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
barraclough@apple.comc4a3fa82009-11-06 09:35:03 +0000175
176 m_assembler.movs_r(dest, m_assembler.asr_r(dest, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000177 }
178
179 void rshift32(Imm32 imm, RegisterID dest)
180 {
181 m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
182 }
oliver@apple.com429ede02010-04-30 07:56:38 +0000183
184 void urshift32(RegisterID shift_amount, RegisterID dest)
185 {
186 ARMWord w = ARMAssembler::getOp2(0x1f);
187 ASSERT(w != ARMAssembler::INVALID_IMM);
188 m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
189
190 m_assembler.movs_r(dest, m_assembler.lsr_r(dest, ARMRegisters::S0));
191 }
192
193 void urshift32(Imm32 imm, RegisterID dest)
194 {
195 m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
196 }
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000197
198 void sub32(RegisterID src, RegisterID dest)
199 {
200 m_assembler.subs_r(dest, dest, src);
201 }
202
203 void sub32(Imm32 imm, RegisterID dest)
204 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000205 m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000206 }
207
208 void sub32(Imm32 imm, Address address)
209 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000210 load32(address, ARMRegisters::S1);
211 sub32(imm, ARMRegisters::S1);
212 store32(ARMRegisters::S1, address);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000213 }
214
215 void sub32(Address src, RegisterID dest)
216 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000217 load32(src, ARMRegisters::S1);
218 sub32(ARMRegisters::S1, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000219 }
220
221 void xor32(RegisterID src, RegisterID dest)
222 {
223 m_assembler.eors_r(dest, dest, src);
224 }
225
226 void xor32(Imm32 imm, RegisterID dest)
227 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000228 m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000229 }
230
loki@webkit.org0f28f9b2010-11-20 22:02:36 +0000231 void countLeadingZeros32(RegisterID src, RegisterID dest)
232 {
233#if WTF_ARM_ARCH_AT_LEAST(5)
234 m_assembler.clz_r(dest, src);
235#else
236 UNUSED_PARAM(src);
237 UNUSED_PARAM(dest);
238 ASSERT_NOT_REACHED();
239#endif
240 }
241
loki@webkit.org2acccd02010-03-09 09:36:06 +0000242 void load8(ImplicitAddress address, RegisterID dest)
243 {
244 m_assembler.dataTransfer32(true, dest, address.base, address.offset, true);
245 }
246
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000247 void load32(ImplicitAddress address, RegisterID dest)
248 {
249 m_assembler.dataTransfer32(true, dest, address.base, address.offset);
250 }
251
252 void load32(BaseIndex address, RegisterID dest)
253 {
254 m_assembler.baseIndexTransfer32(true, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
255 }
256
mjs@apple.comcc668212010-01-04 11:38:56 +0000257#if CPU(ARMV5_OR_LOWER)
eric@webkit.org16d65d12009-09-26 02:27:02 +0000258 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest);
259#else
260 void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
261 {
262 load32(address, dest);
263 }
264#endif
265
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000266 DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
267 {
268 DataLabel32 dataLabel(this);
eric@webkit.org734dd062009-08-20 00:02:24 +0000269 m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
270 m_assembler.dtr_ur(true, dest, address.base, ARMRegisters::S0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000271 return dataLabel;
272 }
273
274 Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
275 {
276 Label label(this);
277 load32(address, dest);
278 return label;
279 }
280
281 void load16(BaseIndex address, RegisterID dest)
282 {
eric@webkit.org25809632010-05-08 20:03:31 +0000283 m_assembler.add_r(ARMRegisters::S1, address.base, m_assembler.lsl(address.index, address.scale));
284 load16(Address(ARMRegisters::S1, address.offset), dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000285 }
oliver@apple.com771ce2d2010-05-06 20:04:28 +0000286
287 void load16(ImplicitAddress address, RegisterID dest)
288 {
289 if (address.offset >= 0)
eric@webkit.org25809632010-05-08 20:03:31 +0000290 m_assembler.ldrh_u(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(address.offset, ARMRegisters::S0));
oliver@apple.com771ce2d2010-05-06 20:04:28 +0000291 else
eric@webkit.org25809632010-05-08 20:03:31 +0000292 m_assembler.ldrh_d(dest, address.base, m_assembler.getOffsetForHalfwordDataTransfer(-address.offset, ARMRegisters::S0));
oliver@apple.com771ce2d2010-05-06 20:04:28 +0000293 }
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000294
295 DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
296 {
297 DataLabel32 dataLabel(this);
eric@webkit.org734dd062009-08-20 00:02:24 +0000298 m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
299 m_assembler.dtr_ur(false, src, address.base, ARMRegisters::S0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000300 return dataLabel;
301 }
302
303 void store32(RegisterID src, ImplicitAddress address)
304 {
305 m_assembler.dataTransfer32(false, src, address.base, address.offset);
306 }
307
308 void store32(RegisterID src, BaseIndex address)
309 {
310 m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
311 }
312
313 void store32(Imm32 imm, ImplicitAddress address)
314 {
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000315 if (imm.m_isPointer)
eric@webkit.org734dd062009-08-20 00:02:24 +0000316 m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000317 else
eric@webkit.org734dd062009-08-20 00:02:24 +0000318 move(imm, ARMRegisters::S1);
319 store32(ARMRegisters::S1, address);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000320 }
321
322 void store32(RegisterID src, void* address)
323 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000324 m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
325 m_assembler.dtr_u(false, src, ARMRegisters::S0, 0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000326 }
327
328 void store32(Imm32 imm, void* address)
329 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000330 m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000331 if (imm.m_isPointer)
eric@webkit.org734dd062009-08-20 00:02:24 +0000332 m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000333 else
eric@webkit.org734dd062009-08-20 00:02:24 +0000334 m_assembler.moveImm(imm.m_value, ARMRegisters::S1);
335 m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000336 }
337
338 void pop(RegisterID dest)
339 {
340 m_assembler.pop_r(dest);
341 }
342
343 void push(RegisterID src)
344 {
345 m_assembler.push_r(src);
346 }
347
348 void push(Address address)
349 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000350 load32(address, ARMRegisters::S1);
351 push(ARMRegisters::S1);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000352 }
353
354 void push(Imm32 imm)
355 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000356 move(imm, ARMRegisters::S0);
357 push(ARMRegisters::S0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000358 }
359
360 void move(Imm32 imm, RegisterID dest)
361 {
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000362 if (imm.m_isPointer)
363 m_assembler.ldr_un_imm(dest, imm.m_value);
364 else
365 m_assembler.moveImm(imm.m_value, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000366 }
367
368 void move(RegisterID src, RegisterID dest)
369 {
370 m_assembler.mov_r(dest, src);
371 }
372
373 void move(ImmPtr imm, RegisterID dest)
374 {
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000375 move(Imm32(imm), dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000376 }
377
378 void swap(RegisterID reg1, RegisterID reg2)
379 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000380 m_assembler.mov_r(ARMRegisters::S0, reg1);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000381 m_assembler.mov_r(reg1, reg2);
eric@webkit.org734dd062009-08-20 00:02:24 +0000382 m_assembler.mov_r(reg2, ARMRegisters::S0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000383 }
384
385 void signExtend32ToPtr(RegisterID src, RegisterID dest)
386 {
387 if (src != dest)
388 move(src, dest);
389 }
390
391 void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
392 {
393 if (src != dest)
394 move(src, dest);
395 }
396
loki@webkit.org2acccd02010-03-09 09:36:06 +0000397 Jump branch8(Condition cond, Address left, Imm32 right)
398 {
399 load8(left, ARMRegisters::S1);
400 return branch32(cond, ARMRegisters::S1, right);
401 }
402
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000403 Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000404 {
405 m_assembler.cmp_r(left, right);
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000406 return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000407 }
408
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000409 Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0)
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000410 {
barraclough@apple.com0192e2c2009-08-06 05:22:42 +0000411 if (right.m_isPointer) {
eric@webkit.org734dd062009-08-20 00:02:24 +0000412 m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
413 m_assembler.cmp_r(left, ARMRegisters::S0);
loki@webkit.org5b1bd322010-10-27 13:48:11 +0000414 } else {
415 ARMWord tmp = m_assembler.getOp2(-right.m_value);
416 if (tmp != ARMAssembler::INVALID_IMM)
417 m_assembler.cmn_r(left, tmp);
418 else
419 m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
420 }
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000421 return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000422 }
423
424 Jump branch32(Condition cond, RegisterID left, Address right)
425 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000426 load32(right, ARMRegisters::S1);
427 return branch32(cond, left, ARMRegisters::S1);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000428 }
429
430 Jump branch32(Condition cond, Address left, RegisterID right)
431 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000432 load32(left, ARMRegisters::S1);
433 return branch32(cond, ARMRegisters::S1, right);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000434 }
435
436 Jump branch32(Condition cond, Address left, Imm32 right)
437 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000438 load32(left, ARMRegisters::S1);
439 return branch32(cond, ARMRegisters::S1, right);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000440 }
441
442 Jump branch32(Condition cond, BaseIndex left, Imm32 right)
443 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000444 load32(left, ARMRegisters::S1);
445 return branch32(cond, ARMRegisters::S1, right);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000446 }
447
eric@webkit.org16d65d12009-09-26 02:27:02 +0000448 Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
449 {
450 load32WithUnalignedHalfWords(left, ARMRegisters::S1);
451 return branch32(cond, ARMRegisters::S1, right);
452 }
453
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000454 Jump branch16(Condition cond, BaseIndex left, RegisterID right)
455 {
456 UNUSED_PARAM(cond);
457 UNUSED_PARAM(left);
458 UNUSED_PARAM(right);
459 ASSERT_NOT_REACHED();
460 return jump();
461 }
462
463 Jump branch16(Condition cond, BaseIndex left, Imm32 right)
464 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000465 load16(left, ARMRegisters::S0);
466 move(right, ARMRegisters::S1);
467 m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S1);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000468 return m_assembler.jmp(ARMCondition(cond));
469 }
470
loki@webkit.org2acccd02010-03-09 09:36:06 +0000471 Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
472 {
473 load8(address, ARMRegisters::S1);
474 return branchTest32(cond, ARMRegisters::S1, mask);
475 }
476
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000477 Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
478 {
479 ASSERT((cond == Zero) || (cond == NonZero));
480 m_assembler.tst_r(reg, mask);
481 return Jump(m_assembler.jmp(ARMCondition(cond)));
482 }
483
484 Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
485 {
486 ASSERT((cond == Zero) || (cond == NonZero));
eric@webkit.org734dd062009-08-20 00:02:24 +0000487 ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000488 if (w & ARMAssembler::OP2_INV_IMM)
eric@webkit.org734dd062009-08-20 00:02:24 +0000489 m_assembler.bics_r(ARMRegisters::S0, reg, w & ~ARMAssembler::OP2_INV_IMM);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000490 else
491 m_assembler.tst_r(reg, w);
492 return Jump(m_assembler.jmp(ARMCondition(cond)));
493 }
494
495 Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
496 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000497 load32(address, ARMRegisters::S1);
498 return branchTest32(cond, ARMRegisters::S1, mask);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000499 }
500
501 Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
502 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000503 load32(address, ARMRegisters::S1);
504 return branchTest32(cond, ARMRegisters::S1, mask);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000505 }
506
507 Jump jump()
508 {
509 return Jump(m_assembler.jmp());
510 }
511
512 void jump(RegisterID target)
513 {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000514 m_assembler.bx(target);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000515 }
516
517 void jump(Address address)
518 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000519 load32(address, ARMRegisters::pc);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000520 }
521
522 Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
523 {
524 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
525 add32(src, dest);
526 return Jump(m_assembler.jmp(ARMCondition(cond)));
527 }
528
529 Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
530 {
531 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
532 add32(imm, dest);
533 return Jump(m_assembler.jmp(ARMCondition(cond)));
534 }
535
536 void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
537 {
538 if (src1 == dest) {
eric@webkit.org734dd062009-08-20 00:02:24 +0000539 move(src1, ARMRegisters::S0);
540 src1 = ARMRegisters::S0;
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000541 }
eric@webkit.org734dd062009-08-20 00:02:24 +0000542 m_assembler.mull_r(ARMRegisters::S1, dest, src2, src1);
543 m_assembler.cmp_r(ARMRegisters::S1, m_assembler.asr(dest, 31));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000544 }
545
546 Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
547 {
548 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
549 if (cond == Overflow) {
550 mull32(src, dest, dest);
551 cond = NonZero;
552 }
553 else
554 mul32(src, dest);
555 return Jump(m_assembler.jmp(ARMCondition(cond)));
556 }
557
558 Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
559 {
560 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
561 if (cond == Overflow) {
eric@webkit.org734dd062009-08-20 00:02:24 +0000562 move(imm, ARMRegisters::S0);
563 mull32(ARMRegisters::S0, src, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000564 cond = NonZero;
565 }
566 else
567 mul32(imm, src, dest);
568 return Jump(m_assembler.jmp(ARMCondition(cond)));
569 }
570
571 Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
572 {
573 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
574 sub32(src, dest);
575 return Jump(m_assembler.jmp(ARMCondition(cond)));
576 }
577
578 Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
579 {
580 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
581 sub32(imm, dest);
582 return Jump(m_assembler.jmp(ARMCondition(cond)));
583 }
584
ggaren@apple.com5a0ed292010-03-22 18:33:23 +0000585 Jump branchNeg32(Condition cond, RegisterID srcDest)
586 {
587 ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
588 neg32(srcDest);
589 return Jump(m_assembler.jmp(ARMCondition(cond)));
590 }
591
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000592 Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
593 {
594 ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
595 or32(src, dest);
596 return Jump(m_assembler.jmp(ARMCondition(cond)));
597 }
598
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000599 void breakpoint()
600 {
601 m_assembler.bkpt(0);
602 }
603
604 Call nearCall()
605 {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000606#if WTF_ARM_ARCH_AT_LEAST(5)
607 ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
608 m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true);
609 return Call(m_assembler.blx(ARMRegisters::S1), Call::LinkableNear);
610#else
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000611 prepareCall();
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000612 return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::LinkableNear);
eric@webkit.org6a210e72010-04-22 13:24:56 +0000613#endif
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000614 }
615
616 Call call(RegisterID target)
617 {
loki@webkit.orgea6cf182010-11-24 13:04:35 +0000618 return Call(m_assembler.blx(target), Call::None);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000619 }
620
621 void call(Address address)
622 {
623 call32(address.base, address.offset);
624 }
625
626 void ret()
627 {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000628 m_assembler.bx(linkRegister);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000629 }
630
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000631 void set32Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000632 {
633 m_assembler.cmp_r(left, right);
634 m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
635 m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
636 }
637
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000638 void set32Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000639 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000640 m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000641 m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
642 m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
643 }
644
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000645 void set8Compare32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000646 {
647 // ARM doesn't have byte registers
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000648 set32Compare32(cond, left, right, dest);
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000649 }
650
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000651 void set8Compare32(Condition cond, Address left, RegisterID right, RegisterID dest)
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000652 {
653 // ARM doesn't have byte registers
654 load32(left, ARMRegisters::S1);
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000655 set32Compare32(cond, ARMRegisters::S1, right, dest);
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000656 }
657
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000658 void set8Compare32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000659 {
660 // ARM doesn't have byte registers
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000661 set32Compare32(cond, left, right, dest);
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000662 }
663
commit-queue@webkit.org4fa9acd2011-02-01 14:40:03 +0000664 void set32Test32(Condition cond, RegisterID reg, Imm32 mask, RegisterID dest)
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000665 {
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000666 if (mask.m_value == -1)
commit-queue@webkit.org4fa9acd2011-02-01 14:40:03 +0000667 m_assembler.cmp_r(0, reg);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000668 else
commit-queue@webkit.org4fa9acd2011-02-01 14:40:03 +0000669 m_assembler.tst_r(reg, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000670 m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
671 m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
672 }
673
commit-queue@webkit.org4fa9acd2011-02-01 14:40:03 +0000674 void set32Test32(Condition cond, Address address, Imm32 mask, RegisterID dest)
675 {
676 load32(address, ARMRegisters::S1);
677 set32Test32(cond, ARMRegisters::S1, mask, dest);
678 }
679
barraclough@apple.comb79c1c02010-12-04 02:46:49 +0000680 void set32Test8(Condition cond, Address address, Imm32 mask, RegisterID dest)
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000681 {
commit-queue@webkit.org4fa9acd2011-02-01 14:40:03 +0000682 load8(address, ARMRegisters::S1);
683 set32Test32(cond, ARMRegisters::S1, mask, dest);
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000684 }
685
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000686 void add32(Imm32 imm, RegisterID src, RegisterID dest)
687 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000688 m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000689 }
690
691 void add32(Imm32 imm, AbsoluteAddress address)
692 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000693 m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
694 m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
695 add32(imm, ARMRegisters::S1);
696 m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
697 m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000698 }
699
700 void sub32(Imm32 imm, AbsoluteAddress address)
701 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000702 m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
703 m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
704 sub32(imm, ARMRegisters::S1);
705 m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
706 m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000707 }
708
709 void load32(void* address, RegisterID dest)
710 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000711 m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
712 m_assembler.dtr_u(true, dest, ARMRegisters::S0, 0);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000713 }
714
715 Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
716 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000717 load32(left.m_ptr, ARMRegisters::S1);
718 return branch32(cond, ARMRegisters::S1, right);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000719 }
720
721 Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
722 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000723 load32(left.m_ptr, ARMRegisters::S1);
724 return branch32(cond, ARMRegisters::S1, right);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000725 }
726
loki@webkit.org0f28f9b2010-11-20 22:02:36 +0000727 void relativeTableJump(RegisterID index, int scale)
728 {
729 ASSERT(scale >= 0 && scale <= 31);
730 m_assembler.add_r(ARMRegisters::pc, ARMRegisters::pc, m_assembler.lsl(index, scale));
731
732 // NOP the default prefetching
733 m_assembler.mov_r(ARMRegisters::r0, ARMRegisters::r0);
734 }
735
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000736 Call call()
737 {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000738#if WTF_ARM_ARCH_AT_LEAST(5)
739 ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
740 m_assembler.loadBranchTarget(ARMRegisters::S1, ARMAssembler::AL, true);
741 return Call(m_assembler.blx(ARMRegisters::S1), Call::Linkable);
742#else
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000743 prepareCall();
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000744 return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::Linkable);
eric@webkit.org6a210e72010-04-22 13:24:56 +0000745#endif
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000746 }
747
748 Call tailRecursiveCall()
749 {
750 return Call::fromTailJump(jump());
751 }
752
753 Call makeTailRecursiveCall(Jump oldJump)
754 {
755 return Call::fromTailJump(oldJump);
756 }
757
758 DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
759 {
760 DataLabelPtr dataLabel(this);
761 m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
762 return dataLabel;
763 }
764
765 Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
766 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000767 dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1);
768 Jump jump = branch32(cond, left, ARMRegisters::S1, true);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000769 return jump;
770 }
771
772 Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
773 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000774 load32(left, ARMRegisters::S1);
775 dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
776 Jump jump = branch32(cond, ARMRegisters::S0, ARMRegisters::S1, true);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000777 return jump;
778 }
779
780 DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
781 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000782 DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
783 store32(ARMRegisters::S1, address);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000784 return dataLabel;
785 }
786
787 DataLabelPtr storePtrWithPatch(ImplicitAddress address)
788 {
789 return storePtrWithPatch(ImmPtr(0), address);
790 }
791
792 // Floating point operators
793 bool supportsFloatingPoint() const
794 {
zoltan@webkit.org212e83e2009-09-15 11:29:33 +0000795 return s_isVFPPresent;
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000796 }
797
798 bool supportsFloatingPointTruncate() const
799 {
loki@webkit.org86097ad2010-08-25 07:52:16 +0000800 return s_isVFPPresent;
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000801 }
802
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000803 bool supportsFloatingPointSqrt() const
804 {
zherczeg@webkit.orgfa3e9212010-04-29 14:08:44 +0000805 return s_isVFPPresent;
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000806 }
807
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000808 void loadDouble(ImplicitAddress address, FPRegisterID dest)
809 {
barraclough@apple.com9ef61d52009-08-06 05:33:27 +0000810 m_assembler.doubleTransfer(true, dest, address.base, address.offset);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000811 }
812
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000813 void loadDouble(const void* address, FPRegisterID dest)
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000814 {
815 m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address);
816 m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0);
817 }
818
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000819 void storeDouble(FPRegisterID src, ImplicitAddress address)
820 {
barraclough@apple.com9ef61d52009-08-06 05:33:27 +0000821 m_assembler.doubleTransfer(false, src, address.base, address.offset);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000822 }
823
824 void addDouble(FPRegisterID src, FPRegisterID dest)
825 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000826 m_assembler.vadd_f64_r(dest, dest, src);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000827 }
828
829 void addDouble(Address src, FPRegisterID dest)
830 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000831 loadDouble(src, ARMRegisters::SD0);
832 addDouble(ARMRegisters::SD0, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000833 }
834
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000835 void divDouble(FPRegisterID src, FPRegisterID dest)
836 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000837 m_assembler.vdiv_f64_r(dest, dest, src);
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000838 }
839
840 void divDouble(Address src, FPRegisterID dest)
841 {
842 ASSERT_NOT_REACHED(); // Untested
843 loadDouble(src, ARMRegisters::SD0);
844 divDouble(ARMRegisters::SD0, dest);
845 }
846
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000847 void subDouble(FPRegisterID src, FPRegisterID dest)
848 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000849 m_assembler.vsub_f64_r(dest, dest, src);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000850 }
851
852 void subDouble(Address src, FPRegisterID dest)
853 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000854 loadDouble(src, ARMRegisters::SD0);
855 subDouble(ARMRegisters::SD0, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000856 }
857
858 void mulDouble(FPRegisterID src, FPRegisterID dest)
859 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000860 m_assembler.vmul_f64_r(dest, dest, src);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000861 }
862
863 void mulDouble(Address src, FPRegisterID dest)
864 {
eric@webkit.org734dd062009-08-20 00:02:24 +0000865 loadDouble(src, ARMRegisters::SD0);
866 mulDouble(ARMRegisters::SD0, dest);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000867 }
868
zherczeg@webkit.orgfa3e9212010-04-29 14:08:44 +0000869 void sqrtDouble(FPRegisterID src, FPRegisterID dest)
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000870 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000871 m_assembler.vsqrt_f64_r(dest, src);
oliver@apple.com2bd947e2010-04-29 03:57:16 +0000872 }
873
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000874 void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
875 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000876 m_assembler.vmov_vfp_r(dest << 1, src);
877 m_assembler.vcvt_f64_s32_r(dest, dest << 1);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000878 }
879
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000880 void convertInt32ToDouble(Address src, FPRegisterID dest)
881 {
882 ASSERT_NOT_REACHED(); // Untested
883 // flds does not worth the effort here
884 load32(src, ARMRegisters::S1);
885 convertInt32ToDouble(ARMRegisters::S1, dest);
886 }
887
888 void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
889 {
890 ASSERT_NOT_REACHED(); // Untested
891 // flds does not worth the effort here
892 m_assembler.ldr_un_imm(ARMRegisters::S1, (ARMWord)src.m_ptr);
893 m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
894 convertInt32ToDouble(ARMRegisters::S1, dest);
895 }
896
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000897 Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
898 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000899 m_assembler.vcmp_f64_r(left, right);
900 m_assembler.vmrs_apsr();
ossy@webkit.orgcb981302009-11-06 07:28:56 +0000901 if (cond & DoubleConditionBitSpecial)
902 m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS);
903 return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask)));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000904 }
905
906 // Truncates 'src' to an integer, and places the resulting 'dest'.
907 // If the result is not representable as a 32 bit value, branch.
908 // May also branch for some values that are representable in 32 bits
loki@webkit.org86097ad2010-08-25 07:52:16 +0000909 // (specifically, in this case, INT_MIN and INT_MAX).
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000910 Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
911 {
loki@webkit.org86097ad2010-08-25 07:52:16 +0000912 m_assembler.vcvtr_s32_f64_r(ARMRegisters::SD0 << 1, src);
913 // If VCVTR.S32.F64 can't fit the result into a 32-bit
914 // integer, it saturates at INT_MAX or INT_MIN. Testing this is
915 // probably quicker than testing FPSCR for exception.
916 m_assembler.vmov_arm_r(dest, ARMRegisters::SD0 << 1);
917 m_assembler.sub_r(ARMRegisters::S0, dest, ARMAssembler::getOp2(0x80000000));
918 m_assembler.cmn_r(ARMRegisters::S0, ARMAssembler::getOp2(1), ARMCondition(NotEqual));
919 return Jump(m_assembler.jmp(ARMCondition(Equal)));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000920 }
921
ossy@webkit.orgcb981302009-11-06 07:28:56 +0000922 // Convert 'src' to an integer, and places the resulting 'dest'.
923 // If the result is not representable as a 32 bit value, branch.
924 // May also branch for some values that are representable in 32 bits
925 // (specifically, in this case, 0).
926 void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
927 {
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000928 m_assembler.vcvt_s32_f64_r(ARMRegisters::SD0 << 1, src);
929 m_assembler.vmov_arm_r(dest, ARMRegisters::SD0 << 1);
ossy@webkit.orgcb981302009-11-06 07:28:56 +0000930
931 // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
zherczeg@webkit.orgb6994142010-08-13 06:49:16 +0000932 m_assembler.vcvt_f64_s32_r(ARMRegisters::SD0, ARMRegisters::SD0 << 1);
zoltan@webkit.org086fa8f2009-11-17 07:16:22 +0000933 failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0));
ossy@webkit.orgcb981302009-11-06 07:28:56 +0000934
935 // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0
936 failureCases.append(branchTest32(Zero, dest));
937 }
938
barraclough@apple.com07d783c2011-01-07 00:38:37 +0000939 Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000940 {
941 m_assembler.mov_r(ARMRegisters::S0, ARMAssembler::getOp2(0));
barraclough@apple.com07d783c2011-01-07 00:38:37 +0000942 convertInt32ToDouble(ARMRegisters::S0, scratch);
943 return branchDouble(DoubleNotEqual, reg, scratch);
944 }
945
946 Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
947 {
948 m_assembler.mov_r(ARMRegisters::S0, ARMAssembler::getOp2(0));
949 convertInt32ToDouble(ARMRegisters::S0, scratch);
950 return branchDouble(DoubleEqualOrUnordered, reg, scratch);
zoltan@webkit.org1916f842009-11-14 00:44:42 +0000951 }
952
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000953protected:
954 ARMAssembler::Condition ARMCondition(Condition cond)
955 {
956 return static_cast<ARMAssembler::Condition>(cond);
957 }
958
barraclough@apple.com970af2c2009-08-13 05:58:36 +0000959 void ensureSpace(int insnSpace, int constSpace)
960 {
961 m_assembler.ensureSpace(insnSpace, constSpace);
962 }
963
964 int sizeOfConstantPool()
965 {
966 return m_assembler.sizeOfConstantPool();
967 }
968
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000969 void prepareCall()
970 {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000971#if WTF_ARM_ARCH_VERSION < 5
eric@webkit.org6fe95ae2009-10-26 22:49:23 +0000972 ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000973
eric@webkit.org6fe95ae2009-10-26 22:49:23 +0000974 m_assembler.mov_r(linkRegister, ARMRegisters::pc);
eric@webkit.org6a210e72010-04-22 13:24:56 +0000975#endif
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000976 }
977
978 void call32(RegisterID base, int32_t offset)
979 {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000980#if WTF_ARM_ARCH_AT_LEAST(5)
981 int targetReg = ARMRegisters::S1;
982#else
983 int targetReg = ARMRegisters::pc;
984#endif
985 int tmpReg = ARMRegisters::S1;
986
eric@webkit.org734dd062009-08-20 00:02:24 +0000987 if (base == ARMRegisters::sp)
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000988 offset += 4;
989
990 if (offset >= 0) {
991 if (offset <= 0xfff) {
992 prepareCall();
eric@webkit.org6a210e72010-04-22 13:24:56 +0000993 m_assembler.dtr_u(true, targetReg, base, offset);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000994 } else if (offset <= 0xfffff) {
eric@webkit.org6a210e72010-04-22 13:24:56 +0000995 m_assembler.add_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000996 prepareCall();
eric@webkit.org6a210e72010-04-22 13:24:56 +0000997 m_assembler.dtr_u(true, targetReg, tmpReg, offset & 0xfff);
barraclough@apple.com5ea68952009-07-17 21:56:28 +0000998 } else {
loki@webkit.orge5c430e2010-07-13 18:56:18 +0000999 m_assembler.moveImm(offset, tmpReg);
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001000 prepareCall();
loki@webkit.orge5c430e2010-07-13 18:56:18 +00001001 m_assembler.dtr_ur(true, targetReg, base, tmpReg);
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001002 }
1003 } else {
1004 offset = -offset;
1005 if (offset <= 0xfff) {
1006 prepareCall();
eric@webkit.org6a210e72010-04-22 13:24:56 +00001007 m_assembler.dtr_d(true, targetReg, base, offset);
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001008 } else if (offset <= 0xfffff) {
eric@webkit.org6a210e72010-04-22 13:24:56 +00001009 m_assembler.sub_r(tmpReg, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001010 prepareCall();
eric@webkit.org6a210e72010-04-22 13:24:56 +00001011 m_assembler.dtr_d(true, targetReg, tmpReg, offset & 0xfff);
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001012 } else {
loki@webkit.orge5c430e2010-07-13 18:56:18 +00001013 m_assembler.moveImm(offset, tmpReg);
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001014 prepareCall();
loki@webkit.orge5c430e2010-07-13 18:56:18 +00001015 m_assembler.dtr_dr(true, targetReg, base, tmpReg);
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001016 }
1017 }
eric@webkit.org6a210e72010-04-22 13:24:56 +00001018#if WTF_ARM_ARCH_AT_LEAST(5)
1019 m_assembler.blx(targetReg);
1020#endif
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001021 }
1022
barraclough@apple.com96e73432009-07-22 03:24:34 +00001023private:
1024 friend class LinkBuffer;
1025 friend class RepatchBuffer;
1026
1027 static void linkCall(void* code, Call call, FunctionPtr function)
1028 {
1029 ARMAssembler::linkCall(code, call.m_jmp, function.value());
1030 }
1031
1032 static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
1033 {
1034 ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1035 }
1036
1037 static void repatchCall(CodeLocationCall call, FunctionPtr destination)
1038 {
1039 ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
1040 }
1041
zoltan@webkit.org212e83e2009-09-15 11:29:33 +00001042 static const bool s_isVFPPresent;
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001043};
1044
1045}
1046
mjs@apple.comcc668212010-01-04 11:38:56 +00001047#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL)
barraclough@apple.com5ea68952009-07-17 21:56:28 +00001048
1049#endif // MacroAssemblerARM_h