~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Apple Inc.
 
3
 * Copyright (C) 2009 University of Szeged
 
4
 * 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
 
 
31
#include <wtf/Platform.h>
 
32
 
 
33
#if ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL)
 
34
 
 
35
#include "ARMAssembler.h"
 
36
#include "AbstractMacroAssembler.h"
 
37
 
 
38
namespace JSC {
 
39
 
 
40
class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> {
 
41
public:
 
42
    enum Condition {
 
43
        Equal = ARMAssembler::EQ,
 
44
        NotEqual = ARMAssembler::NE,
 
45
        Above = ARMAssembler::HI,
 
46
        AboveOrEqual = ARMAssembler::CS,
 
47
        Below = ARMAssembler::CC,
 
48
        BelowOrEqual = ARMAssembler::LS,
 
49
        GreaterThan = ARMAssembler::GT,
 
50
        GreaterThanOrEqual = ARMAssembler::GE,
 
51
        LessThan = ARMAssembler::LT,
 
52
        LessThanOrEqual = ARMAssembler::LE,
 
53
        Overflow = ARMAssembler::VS,
 
54
        Signed = ARMAssembler::MI,
 
55
        Zero = ARMAssembler::EQ,
 
56
        NonZero = ARMAssembler::NE
 
57
    };
 
58
 
 
59
    enum DoubleCondition {
 
60
        DoubleEqual = ARMAssembler::EQ,
 
61
        DoubleGreaterThan = ARMAssembler::GT,
 
62
        DoubleGreaterThanOrEqual = ARMAssembler::GE,
 
63
        DoubleLessThan = ARMAssembler::LT,
 
64
        DoubleLessThanOrEqual = ARMAssembler::LE,
 
65
    };
 
66
 
 
67
    static const RegisterID stackPointerRegister = ARMRegisters::sp;
 
68
 
 
69
    static const Scale ScalePtr = TimesFour;
 
70
 
 
71
    void add32(RegisterID src, RegisterID dest)
 
72
    {
 
73
        m_assembler.adds_r(dest, dest, src);
 
74
    }
 
75
 
 
76
    void add32(Imm32 imm, Address address)
 
77
    {
 
78
        load32(address, ARMRegisters::S1);
 
79
        add32(imm, ARMRegisters::S1);
 
80
        store32(ARMRegisters::S1, address);
 
81
    }
 
82
 
 
83
    void add32(Imm32 imm, RegisterID dest)
 
84
    {
 
85
        m_assembler.adds_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
 
86
    }
 
87
 
 
88
    void add32(Address src, RegisterID dest)
 
89
    {
 
90
        load32(src, ARMRegisters::S1);
 
91
        add32(ARMRegisters::S1, dest);
 
92
    }
 
93
 
 
94
    void and32(RegisterID src, RegisterID dest)
 
95
    {
 
96
        m_assembler.ands_r(dest, dest, src);
 
97
    }
 
98
 
 
99
    void and32(Imm32 imm, RegisterID dest)
 
100
    {
 
101
        ARMWord w = m_assembler.getImm(imm.m_value, ARMRegisters::S0, true);
 
102
        if (w & ARMAssembler::OP2_INV_IMM)
 
103
            m_assembler.bics_r(dest, dest, w & ~ARMAssembler::OP2_INV_IMM);
 
104
        else
 
105
            m_assembler.ands_r(dest, dest, w);
 
106
    }
 
107
 
 
108
    void lshift32(Imm32 imm, RegisterID dest)
 
109
    {
 
110
        m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f));
 
111
    }
 
112
 
 
113
    void lshift32(RegisterID shift_amount, RegisterID dest)
 
114
    {
 
115
        m_assembler.movs_r(dest, m_assembler.lsl_r(dest, shift_amount));
 
116
    }
 
117
 
 
118
    void mul32(RegisterID src, RegisterID dest)
 
119
    {
 
120
        if (src == dest) {
 
121
            move(src, ARMRegisters::S0);
 
122
            src = ARMRegisters::S0;
 
123
        }
 
124
        m_assembler.muls_r(dest, dest, src);
 
125
    }
 
126
 
 
127
    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
 
128
    {
 
129
        move(imm, ARMRegisters::S0);
 
130
        m_assembler.muls_r(dest, src, ARMRegisters::S0);
 
131
    }
 
132
 
 
133
    void not32(RegisterID dest)
 
134
    {
 
135
        m_assembler.mvns_r(dest, dest);
 
136
    }
 
137
 
 
138
    void or32(RegisterID src, RegisterID dest)
 
139
    {
 
140
        m_assembler.orrs_r(dest, dest, src);
 
141
    }
 
142
 
 
143
    void or32(Imm32 imm, RegisterID dest)
 
144
    {
 
145
        m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
 
146
    }
 
147
 
 
148
    void rshift32(RegisterID shift_amount, RegisterID dest)
 
149
    {
 
150
        m_assembler.movs_r(dest, m_assembler.asr_r(dest, shift_amount));
 
151
    }
 
152
 
 
153
    void rshift32(Imm32 imm, RegisterID dest)
 
154
    {
 
155
        m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
 
156
    }
 
157
 
 
158
    void sub32(RegisterID src, RegisterID dest)
 
159
    {
 
160
        m_assembler.subs_r(dest, dest, src);
 
161
    }
 
162
 
 
163
    void sub32(Imm32 imm, RegisterID dest)
 
164
    {
 
165
        m_assembler.subs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
 
166
    }
 
167
 
 
168
    void sub32(Imm32 imm, Address address)
 
169
    {
 
170
        load32(address, ARMRegisters::S1);
 
171
        sub32(imm, ARMRegisters::S1);
 
172
        store32(ARMRegisters::S1, address);
 
173
    }
 
174
 
 
175
    void sub32(Address src, RegisterID dest)
 
176
    {
 
177
        load32(src, ARMRegisters::S1);
 
178
        sub32(ARMRegisters::S1, dest);
 
179
    }
 
180
 
 
181
    void xor32(RegisterID src, RegisterID dest)
 
182
    {
 
183
        m_assembler.eors_r(dest, dest, src);
 
184
    }
 
185
 
 
186
    void xor32(Imm32 imm, RegisterID dest)
 
187
    {
 
188
        m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
 
189
    }
 
190
 
 
191
    void load32(ImplicitAddress address, RegisterID dest)
 
192
    {
 
193
        m_assembler.dataTransfer32(true, dest, address.base, address.offset);
 
194
    }
 
195
 
 
196
    void load32(BaseIndex address, RegisterID dest)
 
197
    {
 
198
        m_assembler.baseIndexTransfer32(true, dest, address.base, address.index, static_cast<int>(address.scale), address.offset);
 
199
    }
 
200
 
 
201
#if defined(ARM_REQUIRE_NATURAL_ALIGNMENT) && ARM_REQUIRE_NATURAL_ALIGNMENT
 
202
    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest);
 
203
#else
 
204
    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
 
205
    {
 
206
        load32(address, dest);
 
207
    }
 
208
#endif
 
209
 
 
210
    DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
 
211
    {
 
212
        DataLabel32 dataLabel(this);
 
213
        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
 
214
        m_assembler.dtr_ur(true, dest, address.base, ARMRegisters::S0);
 
215
        return dataLabel;
 
216
    }
 
217
 
 
218
    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
 
219
    {
 
220
        Label label(this);
 
221
        load32(address, dest);
 
222
        return label;
 
223
    }
 
224
 
 
225
    void load16(BaseIndex address, RegisterID dest)
 
226
    {
 
227
        m_assembler.add_r(ARMRegisters::S0, address.base, m_assembler.lsl(address.index, address.scale));
 
228
        if (address.offset>=0)
 
229
            m_assembler.ldrh_u(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(address.offset));
 
230
        else
 
231
            m_assembler.ldrh_d(dest, ARMRegisters::S0, ARMAssembler::getOp2Byte(-address.offset));
 
232
    }
 
233
 
 
234
    DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
 
235
    {
 
236
        DataLabel32 dataLabel(this);
 
237
        m_assembler.ldr_un_imm(ARMRegisters::S0, 0);
 
238
        m_assembler.dtr_ur(false, src, address.base, ARMRegisters::S0);
 
239
        return dataLabel;
 
240
    }
 
241
 
 
242
    void store32(RegisterID src, ImplicitAddress address)
 
243
    {
 
244
        m_assembler.dataTransfer32(false, src, address.base, address.offset);
 
245
    }
 
246
 
 
247
    void store32(RegisterID src, BaseIndex address)
 
248
    {
 
249
        m_assembler.baseIndexTransfer32(false, src, address.base, address.index, static_cast<int>(address.scale), address.offset);
 
250
    }
 
251
 
 
252
    void store32(Imm32 imm, ImplicitAddress address)
 
253
    {
 
254
        if (imm.m_isPointer)
 
255
            m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
 
256
        else
 
257
            move(imm, ARMRegisters::S1);
 
258
        store32(ARMRegisters::S1, address);
 
259
    }
 
260
 
 
261
    void store32(RegisterID src, void* address)
 
262
    {
 
263
        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
 
264
        m_assembler.dtr_u(false, src, ARMRegisters::S0, 0);
 
265
    }
 
266
 
 
267
    void store32(Imm32 imm, void* address)
 
268
    {
 
269
        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
 
270
        if (imm.m_isPointer)
 
271
            m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value);
 
272
        else
 
273
            m_assembler.moveImm(imm.m_value, ARMRegisters::S1);
 
274
        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
 
275
    }
 
276
 
 
277
    void pop(RegisterID dest)
 
278
    {
 
279
        m_assembler.pop_r(dest);
 
280
    }
 
281
 
 
282
    void push(RegisterID src)
 
283
    {
 
284
        m_assembler.push_r(src);
 
285
    }
 
286
 
 
287
    void push(Address address)
 
288
    {
 
289
        load32(address, ARMRegisters::S1);
 
290
        push(ARMRegisters::S1);
 
291
    }
 
292
 
 
293
    void push(Imm32 imm)
 
294
    {
 
295
        move(imm, ARMRegisters::S0);
 
296
        push(ARMRegisters::S0);
 
297
    }
 
298
 
 
299
    void move(Imm32 imm, RegisterID dest)
 
300
    {
 
301
        if (imm.m_isPointer)
 
302
            m_assembler.ldr_un_imm(dest, imm.m_value);
 
303
        else
 
304
            m_assembler.moveImm(imm.m_value, dest);
 
305
    }
 
306
 
 
307
    void move(RegisterID src, RegisterID dest)
 
308
    {
 
309
        m_assembler.mov_r(dest, src);
 
310
    }
 
311
 
 
312
    void move(ImmPtr imm, RegisterID dest)
 
313
    {
 
314
        move(Imm32(imm), dest);
 
315
    }
 
316
 
 
317
    void swap(RegisterID reg1, RegisterID reg2)
 
318
    {
 
319
        m_assembler.mov_r(ARMRegisters::S0, reg1);
 
320
        m_assembler.mov_r(reg1, reg2);
 
321
        m_assembler.mov_r(reg2, ARMRegisters::S0);
 
322
    }
 
323
 
 
324
    void signExtend32ToPtr(RegisterID src, RegisterID dest)
 
325
    {
 
326
        if (src != dest)
 
327
            move(src, dest);
 
328
    }
 
329
 
 
330
    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
 
331
    {
 
332
        if (src != dest)
 
333
            move(src, dest);
 
334
    }
 
335
 
 
336
    Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0)
 
337
    {
 
338
        m_assembler.cmp_r(left, right);
 
339
        return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
 
340
    }
 
341
 
 
342
    Jump branch32(Condition cond, RegisterID left, Imm32 right, int useConstantPool = 0)
 
343
    {
 
344
        if (right.m_isPointer) {
 
345
            m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value);
 
346
            m_assembler.cmp_r(left, ARMRegisters::S0);
 
347
        } else
 
348
            m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
 
349
        return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool));
 
350
    }
 
351
 
 
352
    Jump branch32(Condition cond, RegisterID left, Address right)
 
353
    {
 
354
        load32(right, ARMRegisters::S1);
 
355
        return branch32(cond, left, ARMRegisters::S1);
 
356
    }
 
357
 
 
358
    Jump branch32(Condition cond, Address left, RegisterID right)
 
359
    {
 
360
        load32(left, ARMRegisters::S1);
 
361
        return branch32(cond, ARMRegisters::S1, right);
 
362
    }
 
363
 
 
364
    Jump branch32(Condition cond, Address left, Imm32 right)
 
365
    {
 
366
        load32(left, ARMRegisters::S1);
 
367
        return branch32(cond, ARMRegisters::S1, right);
 
368
    }
 
369
 
 
370
    Jump branch32(Condition cond, BaseIndex left, Imm32 right)
 
371
    {
 
372
        load32(left, ARMRegisters::S1);
 
373
        return branch32(cond, ARMRegisters::S1, right);
 
374
    }
 
375
 
 
376
    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
 
377
    {
 
378
        load32WithUnalignedHalfWords(left, ARMRegisters::S1);
 
379
        return branch32(cond, ARMRegisters::S1, right);
 
380
    }
 
381
 
 
382
    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
 
383
    {
 
384
        UNUSED_PARAM(cond);
 
385
        UNUSED_PARAM(left);
 
386
        UNUSED_PARAM(right);
 
387
        ASSERT_NOT_REACHED();
 
388
        return jump();
 
389
    }
 
390
 
 
391
    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
 
392
    {
 
393
        load16(left, ARMRegisters::S0);
 
394
        move(right, ARMRegisters::S1);
 
395
        m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S1);
 
396
        return m_assembler.jmp(ARMCondition(cond));
 
397
    }
 
398
 
 
399
    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
 
400
    {
 
401
        ASSERT((cond == Zero) || (cond == NonZero));
 
402
        m_assembler.tst_r(reg, mask);
 
403
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
404
    }
 
405
 
 
406
    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
 
407
    {
 
408
        ASSERT((cond == Zero) || (cond == NonZero));
 
409
        ARMWord w = m_assembler.getImm(mask.m_value, ARMRegisters::S0, true);
 
410
        if (w & ARMAssembler::OP2_INV_IMM)
 
411
            m_assembler.bics_r(ARMRegisters::S0, reg, w & ~ARMAssembler::OP2_INV_IMM);
 
412
        else
 
413
            m_assembler.tst_r(reg, w);
 
414
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
415
    }
 
416
 
 
417
    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
 
418
    {
 
419
        load32(address, ARMRegisters::S1);
 
420
        return branchTest32(cond, ARMRegisters::S1, mask);
 
421
    }
 
422
 
 
423
    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
 
424
    {
 
425
        load32(address, ARMRegisters::S1);
 
426
        return branchTest32(cond, ARMRegisters::S1, mask);
 
427
    }
 
428
 
 
429
    Jump jump()
 
430
    {
 
431
        return Jump(m_assembler.jmp());
 
432
    }
 
433
 
 
434
    void jump(RegisterID target)
 
435
    {
 
436
        move(target, ARMRegisters::pc);
 
437
    }
 
438
 
 
439
    void jump(Address address)
 
440
    {
 
441
        load32(address, ARMRegisters::pc);
 
442
    }
 
443
 
 
444
    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
 
445
    {
 
446
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
447
        add32(src, dest);
 
448
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
449
    }
 
450
 
 
451
    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
 
452
    {
 
453
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
454
        add32(imm, dest);
 
455
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
456
    }
 
457
 
 
458
    void mull32(RegisterID src1, RegisterID src2, RegisterID dest)
 
459
    {
 
460
        if (src1 == dest) {
 
461
            move(src1, ARMRegisters::S0);
 
462
            src1 = ARMRegisters::S0;
 
463
        }
 
464
        m_assembler.mull_r(ARMRegisters::S1, dest, src2, src1);
 
465
        m_assembler.cmp_r(ARMRegisters::S1, m_assembler.asr(dest, 31));
 
466
    }
 
467
 
 
468
    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
 
469
    {
 
470
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
471
        if (cond == Overflow) {
 
472
            mull32(src, dest, dest);
 
473
            cond = NonZero;
 
474
        }
 
475
        else
 
476
            mul32(src, dest);
 
477
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
478
    }
 
479
 
 
480
    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
 
481
    {
 
482
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
483
        if (cond == Overflow) {
 
484
            move(imm, ARMRegisters::S0);
 
485
            mull32(ARMRegisters::S0, src, dest);
 
486
            cond = NonZero;
 
487
        }
 
488
        else
 
489
            mul32(imm, src, dest);
 
490
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
491
    }
 
492
 
 
493
    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
 
494
    {
 
495
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
496
        sub32(src, dest);
 
497
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
498
    }
 
499
 
 
500
    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
 
501
    {
 
502
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
503
        sub32(imm, dest);
 
504
        return Jump(m_assembler.jmp(ARMCondition(cond)));
 
505
    }
 
506
 
 
507
    void breakpoint()
 
508
    {
 
509
        m_assembler.bkpt(0);
 
510
    }
 
511
 
 
512
    Call nearCall()
 
513
    {
 
514
        prepareCall();
 
515
        return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::LinkableNear);
 
516
    }
 
517
 
 
518
    Call call(RegisterID target)
 
519
    {
 
520
        prepareCall();
 
521
        move(ARMRegisters::pc, target);
 
522
        JmpSrc jmpSrc;
 
523
        return Call(jmpSrc, Call::None);
 
524
    }
 
525
 
 
526
    void call(Address address)
 
527
    {
 
528
        call32(address.base, address.offset);
 
529
    }
 
530
 
 
531
    void ret()
 
532
    {
 
533
        pop(ARMRegisters::pc);
 
534
    }
 
535
 
 
536
    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
 
537
    {
 
538
        m_assembler.cmp_r(left, right);
 
539
        m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
 
540
        m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
 
541
    }
 
542
 
 
543
    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
 
544
    {
 
545
        m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0));
 
546
        m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
 
547
        m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
 
548
    }
 
549
 
 
550
    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
 
551
    {
 
552
        load32(address, ARMRegisters::S1);
 
553
        if (mask.m_value == -1)
 
554
            m_assembler.cmp_r(0, ARMRegisters::S1);
 
555
        else
 
556
            m_assembler.tst_r(ARMRegisters::S1, m_assembler.getImm(mask.m_value, ARMRegisters::S0));
 
557
        m_assembler.mov_r(dest, ARMAssembler::getOp2(0));
 
558
        m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond));
 
559
    }
 
560
 
 
561
    void add32(Imm32 imm, RegisterID src, RegisterID dest)
 
562
    {
 
563
        m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0));
 
564
    }
 
565
 
 
566
    void add32(Imm32 imm, AbsoluteAddress address)
 
567
    {
 
568
        m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
 
569
        m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
 
570
        add32(imm, ARMRegisters::S1);
 
571
        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
 
572
        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
 
573
    }
 
574
 
 
575
    void sub32(Imm32 imm, AbsoluteAddress address)
 
576
    {
 
577
        m_assembler.ldr_un_imm(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr));
 
578
        m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0);
 
579
        sub32(imm, ARMRegisters::S1);
 
580
        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr));
 
581
        m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0);
 
582
    }
 
583
 
 
584
    void load32(void* address, RegisterID dest)
 
585
    {
 
586
        m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address));
 
587
        m_assembler.dtr_u(true, dest, ARMRegisters::S0, 0);
 
588
    }
 
589
 
 
590
    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
 
591
    {
 
592
        load32(left.m_ptr, ARMRegisters::S1);
 
593
        return branch32(cond, ARMRegisters::S1, right);
 
594
    }
 
595
 
 
596
    Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right)
 
597
    {
 
598
        load32(left.m_ptr, ARMRegisters::S1);
 
599
        return branch32(cond, ARMRegisters::S1, right);
 
600
    }
 
601
 
 
602
    Call call()
 
603
    {
 
604
        prepareCall();
 
605
        return Call(m_assembler.jmp(ARMAssembler::AL, true), Call::Linkable);
 
606
    }
 
607
 
 
608
    Call tailRecursiveCall()
 
609
    {
 
610
        return Call::fromTailJump(jump());
 
611
    }
 
612
 
 
613
    Call makeTailRecursiveCall(Jump oldJump)
 
614
    {
 
615
        return Call::fromTailJump(oldJump);
 
616
    }
 
617
 
 
618
    DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest)
 
619
    {
 
620
        DataLabelPtr dataLabel(this);
 
621
        m_assembler.ldr_un_imm(dest, reinterpret_cast<ARMWord>(initialValue.m_value));
 
622
        return dataLabel;
 
623
    }
 
624
 
 
625
    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
 
626
    {
 
627
        dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1);
 
628
        Jump jump = branch32(cond, left, ARMRegisters::S1, true);
 
629
        return jump;
 
630
    }
 
631
 
 
632
    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
 
633
    {
 
634
        load32(left, ARMRegisters::S1);
 
635
        dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0);
 
636
        Jump jump = branch32(cond, ARMRegisters::S0, ARMRegisters::S1, true);
 
637
        return jump;
 
638
    }
 
639
 
 
640
    DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address)
 
641
    {
 
642
        DataLabelPtr dataLabel = moveWithPatch(initialValue, ARMRegisters::S1);
 
643
        store32(ARMRegisters::S1, address);
 
644
        return dataLabel;
 
645
    }
 
646
 
 
647
    DataLabelPtr storePtrWithPatch(ImplicitAddress address)
 
648
    {
 
649
        return storePtrWithPatch(ImmPtr(0), address);
 
650
    }
 
651
 
 
652
    // Floating point operators
 
653
    bool supportsFloatingPoint() const
 
654
    {
 
655
        return s_isVFPPresent;
 
656
    }
 
657
 
 
658
    bool supportsFloatingPointTruncate() const
 
659
    {
 
660
        return false;
 
661
    }
 
662
 
 
663
    void loadDouble(ImplicitAddress address, FPRegisterID dest)
 
664
    {
 
665
        m_assembler.doubleTransfer(true, dest, address.base, address.offset);
 
666
    }
 
667
 
 
668
    void storeDouble(FPRegisterID src, ImplicitAddress address)
 
669
    {
 
670
        m_assembler.doubleTransfer(false, src, address.base, address.offset);
 
671
    }
 
672
 
 
673
    void addDouble(FPRegisterID src, FPRegisterID dest)
 
674
    {
 
675
        m_assembler.faddd_r(dest, dest, src);
 
676
    }
 
677
 
 
678
    void addDouble(Address src, FPRegisterID dest)
 
679
    {
 
680
        loadDouble(src, ARMRegisters::SD0);
 
681
        addDouble(ARMRegisters::SD0, dest);
 
682
    }
 
683
 
 
684
    void subDouble(FPRegisterID src, FPRegisterID dest)
 
685
    {
 
686
        m_assembler.fsubd_r(dest, dest, src);
 
687
    }
 
688
 
 
689
    void subDouble(Address src, FPRegisterID dest)
 
690
    {
 
691
        loadDouble(src, ARMRegisters::SD0);
 
692
        subDouble(ARMRegisters::SD0, dest);
 
693
    }
 
694
 
 
695
    void mulDouble(FPRegisterID src, FPRegisterID dest)
 
696
    {
 
697
        m_assembler.fmuld_r(dest, dest, src);
 
698
    }
 
699
 
 
700
    void mulDouble(Address src, FPRegisterID dest)
 
701
    {
 
702
        loadDouble(src, ARMRegisters::SD0);
 
703
        mulDouble(ARMRegisters::SD0, dest);
 
704
    }
 
705
 
 
706
    void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
 
707
    {
 
708
        m_assembler.fmsr_r(dest, src);
 
709
        m_assembler.fsitod_r(dest, dest);
 
710
    }
 
711
 
 
712
    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
 
713
    {
 
714
        m_assembler.fcmpd_r(left, right);
 
715
        m_assembler.fmstat();
 
716
        return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond)));
 
717
    }
 
718
 
 
719
    // Truncates 'src' to an integer, and places the resulting 'dest'.
 
720
    // If the result is not representable as a 32 bit value, branch.
 
721
    // May also branch for some values that are representable in 32 bits
 
722
    // (specifically, in this case, INT_MIN).
 
723
    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
 
724
    {
 
725
        UNUSED_PARAM(src);
 
726
        UNUSED_PARAM(dest);
 
727
        ASSERT_NOT_REACHED();
 
728
        return jump();
 
729
    }
 
730
 
 
731
protected:
 
732
    ARMAssembler::Condition ARMCondition(Condition cond)
 
733
    {
 
734
        return static_cast<ARMAssembler::Condition>(cond);
 
735
    }
 
736
 
 
737
    void ensureSpace(int insnSpace, int constSpace)
 
738
    {
 
739
        m_assembler.ensureSpace(insnSpace, constSpace);
 
740
    }
 
741
 
 
742
    int sizeOfConstantPool()
 
743
    {
 
744
        return m_assembler.sizeOfConstantPool();
 
745
    }
 
746
 
 
747
    void prepareCall()
 
748
    {
 
749
        ensureSpace(3 * sizeof(ARMWord), sizeof(ARMWord));
 
750
 
 
751
        // S0 might be used for parameter passing
 
752
        m_assembler.add_r(ARMRegisters::S1, ARMRegisters::pc, ARMAssembler::OP2_IMM | 0x4);
 
753
        m_assembler.push_r(ARMRegisters::S1);
 
754
    }
 
755
 
 
756
    void call32(RegisterID base, int32_t offset)
 
757
    {
 
758
        if (base == ARMRegisters::sp)
 
759
            offset += 4;
 
760
 
 
761
        if (offset >= 0) {
 
762
            if (offset <= 0xfff) {
 
763
                prepareCall();
 
764
                m_assembler.dtr_u(true, ARMRegisters::pc, base, offset);
 
765
            } else if (offset <= 0xfffff) {
 
766
                m_assembler.add_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
 
767
                prepareCall();
 
768
                m_assembler.dtr_u(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
 
769
            } else {
 
770
                ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
 
771
                prepareCall();
 
772
                m_assembler.dtr_ur(true, ARMRegisters::pc, base, reg);
 
773
            }
 
774
        } else  {
 
775
            offset = -offset;
 
776
            if (offset <= 0xfff) {
 
777
                prepareCall();
 
778
                m_assembler.dtr_d(true, ARMRegisters::pc, base, offset);
 
779
            } else if (offset <= 0xfffff) {
 
780
                m_assembler.sub_r(ARMRegisters::S0, base, ARMAssembler::OP2_IMM | (offset >> 12) | (10 << 8));
 
781
                prepareCall();
 
782
                m_assembler.dtr_d(true, ARMRegisters::pc, ARMRegisters::S0, offset & 0xfff);
 
783
            } else {
 
784
                ARMWord reg = m_assembler.getImm(offset, ARMRegisters::S0);
 
785
                prepareCall();
 
786
                m_assembler.dtr_dr(true, ARMRegisters::pc, base, reg);
 
787
            }
 
788
        }
 
789
    }
 
790
 
 
791
private:
 
792
    friend class LinkBuffer;
 
793
    friend class RepatchBuffer;
 
794
 
 
795
    static void linkCall(void* code, Call call, FunctionPtr function)
 
796
    {
 
797
        ARMAssembler::linkCall(code, call.m_jmp, function.value());
 
798
    }
 
799
 
 
800
    static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
 
801
    {
 
802
        ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
 
803
    }
 
804
 
 
805
    static void repatchCall(CodeLocationCall call, FunctionPtr destination)
 
806
    {
 
807
        ARMAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
 
808
    }
 
809
 
 
810
    static const bool s_isVFPPresent;
 
811
};
 
812
 
 
813
}
 
814
 
 
815
#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL)
 
816
 
 
817
#endif // MacroAssemblerARM_h