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

« back to all changes in this revision

Viewing changes to src/3rdparty/webkit/JavaScriptCore/assembler/ARMAssembler.cpp

  • 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) 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
#include "config.h"
 
28
 
 
29
#if ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL)
 
30
 
 
31
#include "ARMAssembler.h"
 
32
 
 
33
namespace JSC {
 
34
 
 
35
// Patching helpers
 
36
 
 
37
ARMWord* ARMAssembler::getLdrImmAddress(ARMWord* insn, uint32_t* constPool)
 
38
{
 
39
    // Must be an ldr ..., [pc +/- imm]
 
40
    ASSERT((*insn & 0x0f7f0000) == 0x051f0000);
 
41
 
 
42
    if (constPool && (*insn & 0x1))
 
43
        return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1));
 
44
 
 
45
    ARMWord addr = reinterpret_cast<ARMWord>(insn) + 2 * sizeof(ARMWord);
 
46
    if (*insn & DT_UP)
 
47
        return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK));
 
48
    else
 
49
        return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK));
 
50
}
 
51
 
 
52
void ARMAssembler::linkBranch(void* code, JmpSrc from, void* to, int useConstantPool)
 
53
{
 
54
    ARMWord* insn = reinterpret_cast<ARMWord*>(code) + (from.m_offset / sizeof(ARMWord));
 
55
 
 
56
    if (!useConstantPool) {
 
57
        int diff = reinterpret_cast<ARMWord*>(to) - reinterpret_cast<ARMWord*>(insn + 2);
 
58
 
 
59
        if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) {
 
60
            *insn = B | getConditionalField(*insn) | (diff & BRANCH_MASK);
 
61
            ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord));
 
62
            return;
 
63
        }
 
64
    }
 
65
    ARMWord* addr = getLdrImmAddress(insn);
 
66
    *addr = reinterpret_cast<ARMWord>(to);
 
67
    ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord));
 
68
}
 
69
 
 
70
void ARMAssembler::patchConstantPoolLoad(void* loadAddr, void* constPoolAddr)
 
71
{
 
72
    ARMWord *ldr = reinterpret_cast<ARMWord*>(loadAddr);
 
73
    ARMWord diff = reinterpret_cast<ARMWord*>(constPoolAddr) - ldr;
 
74
    ARMWord index = (*ldr & 0xfff) >> 1;
 
75
 
 
76
    ASSERT(diff >= 1);
 
77
    if (diff >= 2 || index > 0) {
 
78
        diff = (diff + index - 2) * sizeof(ARMWord);
 
79
        ASSERT(diff <= 0xfff);
 
80
        *ldr = (*ldr & ~0xfff) | diff;
 
81
    } else
 
82
        *ldr = (*ldr & ~(0xfff | ARMAssembler::DT_UP)) | sizeof(ARMWord);
 
83
}
 
84
 
 
85
// Handle immediates
 
86
 
 
87
ARMWord ARMAssembler::getOp2(ARMWord imm)
 
88
{
 
89
    int rol;
 
90
 
 
91
    if (imm <= 0xff)
 
92
        return OP2_IMM | imm;
 
93
 
 
94
    if ((imm & 0xff000000) == 0) {
 
95
        imm <<= 8;
 
96
        rol = 8;
 
97
    }
 
98
    else {
 
99
        imm = (imm << 24) | (imm >> 8);
 
100
        rol = 0;
 
101
    }
 
102
 
 
103
    if ((imm & 0xff000000) == 0) {
 
104
        imm <<= 8;
 
105
        rol += 4;
 
106
    }
 
107
 
 
108
    if ((imm & 0xf0000000) == 0) {
 
109
        imm <<= 4;
 
110
        rol += 2;
 
111
    }
 
112
 
 
113
    if ((imm & 0xc0000000) == 0) {
 
114
        imm <<= 2;
 
115
        rol += 1;
 
116
    }
 
117
 
 
118
    if ((imm & 0x00ffffff) == 0)
 
119
        return OP2_IMM | (imm >> 24) | (rol << 8);
 
120
 
 
121
    return 0;
 
122
}
 
123
 
 
124
int ARMAssembler::genInt(int reg, ARMWord imm, bool positive)
 
125
{
 
126
    // Step1: Search a non-immediate part
 
127
    ARMWord mask;
 
128
    ARMWord imm1;
 
129
    ARMWord imm2;
 
130
    int rol;
 
131
 
 
132
    mask = 0xff000000;
 
133
    rol = 8;
 
134
    while(1) {
 
135
        if ((imm & mask) == 0) {
 
136
            imm = (imm << rol) | (imm >> (32 - rol));
 
137
            rol = 4 + (rol >> 1);
 
138
            break;
 
139
        }
 
140
        rol += 2;
 
141
        mask >>= 2;
 
142
        if (mask & 0x3) {
 
143
            // rol 8
 
144
            imm = (imm << 8) | (imm >> 24);
 
145
            mask = 0xff00;
 
146
            rol = 24;
 
147
            while (1) {
 
148
                if ((imm & mask) == 0) {
 
149
                    imm = (imm << rol) | (imm >> (32 - rol));
 
150
                    rol = (rol >> 1) - 8;
 
151
                    break;
 
152
                }
 
153
                rol += 2;
 
154
                mask >>= 2;
 
155
                if (mask & 0x3)
 
156
                    return 0;
 
157
            }
 
158
            break;
 
159
        }
 
160
    }
 
161
 
 
162
    ASSERT((imm & 0xff) == 0);
 
163
 
 
164
    if ((imm & 0xff000000) == 0) {
 
165
        imm1 = OP2_IMM | ((imm >> 16) & 0xff) | (((rol + 4) & 0xf) << 8);
 
166
        imm2 = OP2_IMM | ((imm >> 8) & 0xff) | (((rol + 8) & 0xf) << 8);
 
167
    } else if (imm & 0xc0000000) {
 
168
        imm1 = OP2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
 
169
        imm <<= 8;
 
170
        rol += 4;
 
171
 
 
172
        if ((imm & 0xff000000) == 0) {
 
173
            imm <<= 8;
 
174
            rol += 4;
 
175
        }
 
176
 
 
177
        if ((imm & 0xf0000000) == 0) {
 
178
            imm <<= 4;
 
179
            rol += 2;
 
180
        }
 
181
 
 
182
        if ((imm & 0xc0000000) == 0) {
 
183
            imm <<= 2;
 
184
            rol += 1;
 
185
        }
 
186
 
 
187
        if ((imm & 0x00ffffff) == 0)
 
188
            imm2 = OP2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
 
189
        else
 
190
            return 0;
 
191
    } else {
 
192
        if ((imm & 0xf0000000) == 0) {
 
193
            imm <<= 4;
 
194
            rol += 2;
 
195
        }
 
196
 
 
197
        if ((imm & 0xc0000000) == 0) {
 
198
            imm <<= 2;
 
199
            rol += 1;
 
200
        }
 
201
 
 
202
        imm1 = OP2_IMM | ((imm >> 24) & 0xff) | ((rol & 0xf) << 8);
 
203
        imm <<= 8;
 
204
        rol += 4;
 
205
 
 
206
        if ((imm & 0xf0000000) == 0) {
 
207
            imm <<= 4;
 
208
            rol += 2;
 
209
        }
 
210
 
 
211
        if ((imm & 0xc0000000) == 0) {
 
212
            imm <<= 2;
 
213
            rol += 1;
 
214
        }
 
215
 
 
216
        if ((imm & 0x00ffffff) == 0)
 
217
            imm2 = OP2_IMM | (imm >> 24) | ((rol & 0xf) << 8);
 
218
        else
 
219
            return 0;
 
220
    }
 
221
 
 
222
    if (positive) {
 
223
        mov_r(reg, imm1);
 
224
        orr_r(reg, reg, imm2);
 
225
    } else {
 
226
        mvn_r(reg, imm1);
 
227
        bic_r(reg, reg, imm2);
 
228
    }
 
229
 
 
230
    return 1;
 
231
}
 
232
 
 
233
ARMWord ARMAssembler::getImm(ARMWord imm, int tmpReg, bool invert)
 
234
{
 
235
    ARMWord tmp;
 
236
 
 
237
    // Do it by 1 instruction
 
238
    tmp = getOp2(imm);
 
239
    if (tmp)
 
240
        return tmp;
 
241
 
 
242
    tmp = getOp2(~imm);
 
243
    if (tmp) {
 
244
        if (invert)
 
245
            return tmp | OP2_INV_IMM;
 
246
        mvn_r(tmpReg, tmp);
 
247
        return tmpReg;
 
248
    }
 
249
 
 
250
    // Do it by 2 instruction
 
251
    if (genInt(tmpReg, imm, true))
 
252
        return tmpReg;
 
253
    if (genInt(tmpReg, ~imm, false))
 
254
        return tmpReg;
 
255
 
 
256
    ldr_imm(tmpReg, imm);
 
257
    return tmpReg;
 
258
}
 
259
 
 
260
void ARMAssembler::moveImm(ARMWord imm, int dest)
 
261
{
 
262
    ARMWord tmp;
 
263
 
 
264
    // Do it by 1 instruction
 
265
    tmp = getOp2(imm);
 
266
    if (tmp) {
 
267
        mov_r(dest, tmp);
 
268
        return;
 
269
    }
 
270
 
 
271
    tmp = getOp2(~imm);
 
272
    if (tmp) {
 
273
        mvn_r(dest, tmp);
 
274
        return;
 
275
    }
 
276
 
 
277
    // Do it by 2 instruction
 
278
    if (genInt(dest, imm, true))
 
279
        return;
 
280
    if (genInt(dest, ~imm, false))
 
281
        return;
 
282
 
 
283
    ldr_imm(dest, imm);
 
284
}
 
285
 
 
286
// Memory load/store helpers
 
287
 
 
288
void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset)
 
289
{
 
290
    if (offset >= 0) {
 
291
        if (offset <= 0xfff)
 
292
            dtr_u(isLoad, srcDst, base, offset);
 
293
        else if (offset <= 0xfffff) {
 
294
            add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
 
295
            dtr_u(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff);
 
296
        } else {
 
297
            ARMWord reg = getImm(offset, ARMRegisters::S0);
 
298
            dtr_ur(isLoad, srcDst, base, reg);
 
299
        }
 
300
    } else {
 
301
        offset = -offset;
 
302
        if (offset <= 0xfff)
 
303
            dtr_d(isLoad, srcDst, base, offset);
 
304
        else if (offset <= 0xfffff) {
 
305
            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8));
 
306
            dtr_d(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff);
 
307
        } else {
 
308
            ARMWord reg = getImm(offset, ARMRegisters::S0);
 
309
            dtr_dr(isLoad, srcDst, base, reg);
 
310
        }
 
311
    }
 
312
}
 
313
 
 
314
void ARMAssembler::baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset)
 
315
{
 
316
    ARMWord op2;
 
317
 
 
318
    ASSERT(scale >= 0 && scale <= 3);
 
319
    op2 = lsl(index, scale);
 
320
 
 
321
    if (offset >= 0 && offset <= 0xfff) {
 
322
        add_r(ARMRegisters::S0, base, op2);
 
323
        dtr_u(isLoad, srcDst, ARMRegisters::S0, offset);
 
324
        return;
 
325
    }
 
326
    if (offset <= 0 && offset >= -0xfff) {
 
327
        add_r(ARMRegisters::S0, base, op2);
 
328
        dtr_d(isLoad, srcDst, ARMRegisters::S0, -offset);
 
329
        return;
 
330
    }
 
331
 
 
332
    ldr_un_imm(ARMRegisters::S0, offset);
 
333
    add_r(ARMRegisters::S0, ARMRegisters::S0, op2);
 
334
    dtr_ur(isLoad, srcDst, base, ARMRegisters::S0);
 
335
}
 
336
 
 
337
void ARMAssembler::doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset)
 
338
{
 
339
    if (offset & 0x3) {
 
340
        if (offset <= 0x3ff && offset >= 0) {
 
341
            fdtr_u(isLoad, srcDst, base, offset >> 2);
 
342
            return;
 
343
        }
 
344
        if (offset <= 0x3ffff && offset >= 0) {
 
345
            add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 10) | (11 << 8));
 
346
            fdtr_u(isLoad, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
 
347
            return;
 
348
        }
 
349
        offset = -offset;
 
350
 
 
351
        if (offset <= 0x3ff && offset >= 0) {
 
352
            fdtr_d(isLoad, srcDst, base, offset >> 2);
 
353
            return;
 
354
        }
 
355
        if (offset <= 0x3ffff && offset >= 0) {
 
356
            sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 10) | (11 << 8));
 
357
            fdtr_d(isLoad, srcDst, ARMRegisters::S0, (offset >> 2) & 0xff);
 
358
            return;
 
359
        }
 
360
        offset = -offset;
 
361
    }
 
362
 
 
363
    ldr_un_imm(ARMRegisters::S0, offset);
 
364
    add_r(ARMRegisters::S0, ARMRegisters::S0, base);
 
365
    fdtr_u(isLoad, srcDst, ARMRegisters::S0, 0);
 
366
}
 
367
 
 
368
void* ARMAssembler::executableCopy(ExecutablePool* allocator)
 
369
{
 
370
    // 64-bit alignment is required for next constant pool and JIT code as well
 
371
    m_buffer.flushWithoutBarrier(true);
 
372
    if (m_buffer.uncheckedSize() & 0x7)
 
373
        bkpt(0);
 
374
 
 
375
    char* data = reinterpret_cast<char*>(m_buffer.executableCopy(allocator));
 
376
 
 
377
    for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
 
378
        // The last bit is set if the constant must be placed on constant pool.
 
379
        int pos = (*iter) & (~0x1);
 
380
        ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos);
 
381
        ARMWord offset = *getLdrImmAddress(ldrAddr);
 
382
        if (offset != 0xffffffff) {
 
383
            JmpSrc jmpSrc(pos);
 
384
            linkBranch(data, jmpSrc, data + offset, ((*iter) & 1));
 
385
        }
 
386
    }
 
387
 
 
388
    return data;
 
389
}
 
390
 
 
391
} // namespace JSC
 
392
 
 
393
#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL)