~ubuntu-branches/ubuntu/saucy/mozjs17/saucy

« back to all changes in this revision

Viewing changes to js/src/assembler/assembler/MacroAssemblerX86Common.h

  • Committer: Package Import Robot
  • Author(s): Rico Tzschichholz
  • Date: 2013-05-25 12:24:23 UTC
  • Revision ID: package-import@ubuntu.com-20130525122423-zmxucrhtensw90xy
Tags: upstream-17.0.0
ImportĀ upstreamĀ versionĀ 17.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 
2
 * vim: set ts=8 sw=4 et tw=79:
 
3
 *
 
4
 * ***** BEGIN LICENSE BLOCK *****
 
5
 * Copyright (C) 2008 Apple Inc. All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted provided that the following conditions
 
9
 * are met:
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 * 2. Redistributions in binary form must reproduce the above copyright
 
13
 *    notice, this list of conditions and the following disclaimer in the
 
14
 *    documentation and/or other materials provided with the distribution.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 
17
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
18
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
19
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 
20
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
21
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
22
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
23
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 
24
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
26
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 
27
 * 
 
28
 * ***** END LICENSE BLOCK ***** */
 
29
 
 
30
#ifndef MacroAssemblerX86Common_h
 
31
#define MacroAssemblerX86Common_h
 
32
 
 
33
#include "assembler/wtf/Platform.h"
 
34
 
 
35
#if ENABLE_ASSEMBLER
 
36
 
 
37
#include "X86Assembler.h"
 
38
#include "AbstractMacroAssembler.h"
 
39
 
 
40
#if WTF_COMPILER_MSVC
 
41
#if WTF_CPU_X86_64
 
42
/* for __cpuid */
 
43
#include <intrin.h>
 
44
#endif
 
45
#endif
 
46
 
 
47
namespace JSC {
 
48
 
 
49
class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
 
50
    static const int DoubleConditionBitInvert = 0x10;
 
51
    static const int DoubleConditionBitSpecial = 0x20;
 
52
    static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
 
53
 
 
54
protected:
 
55
#if WTF_CPU_X86_64
 
56
    static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
 
57
#endif
 
58
 
 
59
public:
 
60
 
 
61
    enum Condition {
 
62
        Equal = X86Assembler::ConditionE,
 
63
        NotEqual = X86Assembler::ConditionNE,
 
64
        Above = X86Assembler::ConditionA,
 
65
        AboveOrEqual = X86Assembler::ConditionAE,
 
66
        Below = X86Assembler::ConditionB,
 
67
        BelowOrEqual = X86Assembler::ConditionBE,
 
68
        GreaterThan = X86Assembler::ConditionG,
 
69
        GreaterThanOrEqual = X86Assembler::ConditionGE,
 
70
        LessThan = X86Assembler::ConditionL,
 
71
        LessThanOrEqual = X86Assembler::ConditionLE,
 
72
        Overflow = X86Assembler::ConditionO,
 
73
        Signed = X86Assembler::ConditionS,
 
74
        Zero = X86Assembler::ConditionE,
 
75
        NonZero = X86Assembler::ConditionNE
 
76
    };
 
77
 
 
78
    enum DoubleCondition {
 
79
        // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
 
80
        DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial,
 
81
        DoubleNotEqual = X86Assembler::ConditionNE,
 
82
        DoubleGreaterThan = X86Assembler::ConditionA,
 
83
        DoubleGreaterThanOrEqual = X86Assembler::ConditionAE,
 
84
        DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert,
 
85
        DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert,
 
86
        // If either operand is NaN, these conditions always evaluate to true.
 
87
        DoubleEqualOrUnordered = X86Assembler::ConditionE,
 
88
        DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial,
 
89
        DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert,
 
90
        DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert,
 
91
        DoubleLessThanOrUnordered = X86Assembler::ConditionB,
 
92
        DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE
 
93
    };
 
94
    static void staticAsserts() {
 
95
        COMPILE_ASSERT(
 
96
            !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits),
 
97
            DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
 
98
    }
 
99
 
 
100
    static const RegisterID stackPointerRegister = X86Registers::esp;
 
101
 
 
102
    static inline bool CanUse8Bit(RegisterID reg) {
 
103
        return !!((1 << reg) & ~((1 << X86Registers::esp) |
 
104
                                 (1 << X86Registers::edi) |
 
105
                                 (1 << X86Registers::esi) |
 
106
                                 (1 << X86Registers::ebp)));
 
107
    }
 
108
 
 
109
    // Integer arithmetic operations:
 
110
    //
 
111
    // Operations are typically two operand - operation(source, srcDst)
 
112
    // For many operations the source may be an Imm32, the srcDst operand
 
113
    // may often be a memory location (explictly described using an Address
 
114
    // object).
 
115
 
 
116
    void add32(RegisterID src, RegisterID dest)
 
117
    {
 
118
        m_assembler.addl_rr(src, dest);
 
119
    }
 
120
 
 
121
    void add32(TrustedImm32 imm, Address address)
 
122
    {
 
123
        m_assembler.addl_im(imm.m_value, address.offset, address.base);
 
124
    }
 
125
 
 
126
    void add32(TrustedImm32 imm, RegisterID dest)
 
127
    {
 
128
        m_assembler.addl_ir(imm.m_value, dest);
 
129
    }
 
130
    
 
131
    void add32(Address src, RegisterID dest)
 
132
    {
 
133
        m_assembler.addl_mr(src.offset, src.base, dest);
 
134
    }
 
135
 
 
136
    void add32(RegisterID src, Address dest)
 
137
    {
 
138
        m_assembler.addl_rm(src, dest.offset, dest.base);
 
139
    }
 
140
    
 
141
    void and32(RegisterID src, RegisterID dest)
 
142
    {
 
143
        m_assembler.andl_rr(src, dest);
 
144
    }
 
145
 
 
146
    void and32(Imm32 imm, RegisterID dest)
 
147
    {
 
148
        m_assembler.andl_ir(imm.m_value, dest);
 
149
    }
 
150
 
 
151
    void and32(RegisterID src, Address dest)
 
152
    {
 
153
        m_assembler.andl_rm(src, dest.offset, dest.base);
 
154
    }
 
155
 
 
156
    void and32(Address src, RegisterID dest)
 
157
    {
 
158
        m_assembler.andl_mr(src.offset, src.base, dest);
 
159
    }
 
160
 
 
161
    void and32(Imm32 imm, Address address)
 
162
    {
 
163
        m_assembler.andl_im(imm.m_value, address.offset, address.base);
 
164
    }
 
165
 
 
166
    void lshift32(Imm32 imm, RegisterID dest)
 
167
    {
 
168
        m_assembler.shll_i8r(imm.m_value, dest);
 
169
    }
 
170
    
 
171
    void lshift32(RegisterID shift_amount, RegisterID dest)
 
172
    {
 
173
        // On x86 we can only shift by ecx; if asked to shift by another register we'll
 
174
        // need rejig the shift amount into ecx first, and restore the registers afterwards.
 
175
        if (shift_amount != X86Registers::ecx) {
 
176
            swap(shift_amount, X86Registers::ecx);
 
177
 
 
178
            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
 
179
            if (dest == shift_amount)
 
180
                m_assembler.shll_CLr(X86Registers::ecx);
 
181
            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
 
182
            else if (dest == X86Registers::ecx)
 
183
                m_assembler.shll_CLr(shift_amount);
 
184
            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
 
185
            else
 
186
                m_assembler.shll_CLr(dest);
 
187
        
 
188
            swap(shift_amount, X86Registers::ecx);
 
189
        } else
 
190
            m_assembler.shll_CLr(dest);
 
191
    }
 
192
    
 
193
    void mul32(RegisterID src, RegisterID dest)
 
194
    {
 
195
        m_assembler.imull_rr(src, dest);
 
196
    }
 
197
 
 
198
    void mul32(Address src, RegisterID dest)
 
199
    {
 
200
        m_assembler.imull_mr(src.offset, src.base, dest);
 
201
    }
 
202
    
 
203
    void mul32(Imm32 imm, RegisterID src, RegisterID dest)
 
204
    {
 
205
        m_assembler.imull_i32r(src, imm.m_value, dest);
 
206
    }
 
207
 
 
208
    void idiv(RegisterID reg)
 
209
    {
 
210
        m_assembler.cdq();
 
211
        m_assembler.idivl_r(reg);
 
212
    }
 
213
 
 
214
    void neg32(RegisterID srcDest)
 
215
    {
 
216
        m_assembler.negl_r(srcDest);
 
217
    }
 
218
 
 
219
    void neg32(Address srcDest)
 
220
    {
 
221
        m_assembler.negl_m(srcDest.offset, srcDest.base);
 
222
    }
 
223
 
 
224
    void not32(RegisterID srcDest)
 
225
    {
 
226
        m_assembler.notl_r(srcDest);
 
227
    }
 
228
 
 
229
    void not32(Address srcDest)
 
230
    {
 
231
        m_assembler.notl_m(srcDest.offset, srcDest.base);
 
232
    }
 
233
    
 
234
    void or32(RegisterID src, RegisterID dest)
 
235
    {
 
236
        m_assembler.orl_rr(src, dest);
 
237
    }
 
238
 
 
239
    void or32(TrustedImm32 imm, RegisterID dest)
 
240
    {
 
241
        m_assembler.orl_ir(imm.m_value, dest);
 
242
    }
 
243
 
 
244
    void or32(RegisterID src, Address dest)
 
245
    {
 
246
        m_assembler.orl_rm(src, dest.offset, dest.base);
 
247
    }
 
248
 
 
249
    void or32(Address src, RegisterID dest)
 
250
    {
 
251
        m_assembler.orl_mr(src.offset, src.base, dest);
 
252
    }
 
253
 
 
254
    void or32(TrustedImm32 imm, Address address)
 
255
    {
 
256
        m_assembler.orl_im(imm.m_value, address.offset, address.base);
 
257
    }
 
258
 
 
259
    void rshift32(RegisterID shift_amount, RegisterID dest)
 
260
    {
 
261
        // On x86 we can only shift by ecx; if asked to shift by another register we'll
 
262
        // need rejig the shift amount into ecx first, and restore the registers afterwards.
 
263
        if (shift_amount != X86Registers::ecx) {
 
264
            swap(shift_amount, X86Registers::ecx);
 
265
 
 
266
            // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
 
267
            if (dest == shift_amount)
 
268
                m_assembler.sarl_CLr(X86Registers::ecx);
 
269
            // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx"
 
270
            else if (dest == X86Registers::ecx)
 
271
                m_assembler.sarl_CLr(shift_amount);
 
272
            // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx"
 
273
            else
 
274
                m_assembler.sarl_CLr(dest);
 
275
        
 
276
            swap(shift_amount, X86Registers::ecx);
 
277
        } else
 
278
            m_assembler.sarl_CLr(dest);
 
279
    }
 
280
 
 
281
    void rshift32(Imm32 imm, RegisterID dest)
 
282
    {
 
283
        m_assembler.sarl_i8r(imm.m_value, dest);
 
284
    }
 
285
    
 
286
    void urshift32(RegisterID shift_amount, RegisterID dest)
 
287
    {
 
288
        // On x86 we can only shift by ecx; if asked to shift by another register we'll
 
289
        // need rejig the shift amount into ecx first, and restore the registers afterwards.
 
290
        if (shift_amount != X86Registers::ecx) {
 
291
            swap(shift_amount, X86Registers::ecx);
 
292
            
 
293
            // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx"
 
294
            if (dest == shift_amount)
 
295
                m_assembler.shrl_CLr(X86Registers::ecx);
 
296
            // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx"
 
297
            else if (dest == X86Registers::ecx)
 
298
                m_assembler.shrl_CLr(shift_amount);
 
299
            // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx"
 
300
            else
 
301
                m_assembler.shrl_CLr(dest);
 
302
            
 
303
            swap(shift_amount, X86Registers::ecx);
 
304
        } else
 
305
            m_assembler.shrl_CLr(dest);
 
306
    }
 
307
    
 
308
    void urshift32(Imm32 imm, RegisterID dest)
 
309
    {
 
310
        m_assembler.shrl_i8r(imm.m_value, dest);
 
311
    }
 
312
 
 
313
    void sub32(RegisterID src, RegisterID dest)
 
314
    {
 
315
        m_assembler.subl_rr(src, dest);
 
316
    }
 
317
    
 
318
    void sub32(TrustedImm32 imm, RegisterID dest)
 
319
    {
 
320
        m_assembler.subl_ir(imm.m_value, dest);
 
321
    }
 
322
    
 
323
    void sub32(TrustedImm32 imm, Address address)
 
324
    {
 
325
        m_assembler.subl_im(imm.m_value, address.offset, address.base);
 
326
    }
 
327
 
 
328
    void sub32(Address src, RegisterID dest)
 
329
    {
 
330
        m_assembler.subl_mr(src.offset, src.base, dest);
 
331
    }
 
332
 
 
333
    void sub32(RegisterID src, Address dest)
 
334
    {
 
335
        m_assembler.subl_rm(src, dest.offset, dest.base);
 
336
    }
 
337
 
 
338
 
 
339
    void xor32(RegisterID src, RegisterID dest)
 
340
    {
 
341
        m_assembler.xorl_rr(src, dest);
 
342
    }
 
343
 
 
344
    void xor32(TrustedImm32 imm, Address dest)
 
345
    {
 
346
        m_assembler.xorl_im(imm.m_value, dest.offset, dest.base);
 
347
    }
 
348
 
 
349
    void xor32(TrustedImm32 imm, RegisterID dest)
 
350
    {
 
351
        m_assembler.xorl_ir(imm.m_value, dest);
 
352
    }
 
353
 
 
354
    void xor32(RegisterID src, Address dest)
 
355
    {
 
356
        m_assembler.xorl_rm(src, dest.offset, dest.base);
 
357
    }
 
358
 
 
359
    void xor32(Address src, RegisterID dest)
 
360
    {
 
361
        m_assembler.xorl_mr(src.offset, src.base, dest);
 
362
    }
 
363
    
 
364
    void sqrtDouble(FPRegisterID src, FPRegisterID dst)
 
365
    {
 
366
        m_assembler.sqrtsd_rr(src, dst);
 
367
    }
 
368
 
 
369
    // Memory access operations:
 
370
    //
 
371
    // Loads are of the form load(address, destination) and stores of the form
 
372
    // store(source, address).  The source for a store may be an Imm32.  Address
 
373
    // operand objects to loads and store will be implicitly constructed if a
 
374
    // register is passed.
 
375
 
 
376
    void load32(ImplicitAddress address, RegisterID dest)
 
377
    {
 
378
        m_assembler.movl_mr(address.offset, address.base, dest);
 
379
    }
 
380
 
 
381
    void load32(BaseIndex address, RegisterID dest)
 
382
    {
 
383
        m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
 
384
    }
 
385
 
 
386
    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
 
387
    {
 
388
        load32(address, dest);
 
389
    }
 
390
 
 
391
    DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
 
392
    {
 
393
        m_assembler.movl_mr_disp32(address.offset, address.base, dest);
 
394
        return DataLabel32(this);
 
395
    }
 
396
 
 
397
    void store8(RegisterID src, Address address)
 
398
    {
 
399
        m_assembler.movb_rm(src, address.offset, address.base);
 
400
    }
 
401
 
 
402
    void store8(RegisterID src, BaseIndex address)
 
403
    {
 
404
        m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
 
405
    }
 
406
 
 
407
    void store16(RegisterID src, Address address)
 
408
    {
 
409
        m_assembler.movw_rm(src, address.offset, address.base);
 
410
    }
 
411
 
 
412
    void store16(RegisterID src, BaseIndex address)
 
413
    {
 
414
        m_assembler.movw_rm(src, address.offset, address.base, address.index, address.scale);
 
415
    }
 
416
 
 
417
    void load8ZeroExtend(BaseIndex address, RegisterID dest)
 
418
    {
 
419
        m_assembler.movzbl_mr(address.offset, address.base, address.index, address.scale, dest);
 
420
    }
 
421
    
 
422
    void load8ZeroExtend(Address address, RegisterID dest)
 
423
    {
 
424
        m_assembler.movzbl_mr(address.offset, address.base, dest);
 
425
    }
 
426
 
 
427
    void load8SignExtend(BaseIndex address, RegisterID dest)
 
428
    {
 
429
        m_assembler.movxbl_mr(address.offset, address.base, address.index, address.scale, dest);
 
430
    }
 
431
    
 
432
    void load8SignExtend(Address address, RegisterID dest)
 
433
    {
 
434
        m_assembler.movxbl_mr(address.offset, address.base, dest);
 
435
    }
 
436
 
 
437
    void load16SignExtend(BaseIndex address, RegisterID dest)
 
438
    {
 
439
        m_assembler.movxwl_mr(address.offset, address.base, address.index, address.scale, dest);
 
440
    }
 
441
    
 
442
    void load16SignExtend(Address address, RegisterID dest)
 
443
    {
 
444
        m_assembler.movxwl_mr(address.offset, address.base, dest);
 
445
    }
 
446
 
 
447
    void load16(BaseIndex address, RegisterID dest)
 
448
    {
 
449
        m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
 
450
    }
 
451
    
 
452
    void load16(Address address, RegisterID dest)
 
453
    {
 
454
        m_assembler.movzwl_mr(address.offset, address.base, dest);
 
455
    }
 
456
 
 
457
    DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
 
458
    {
 
459
        m_assembler.movl_rm_disp32(src, address.offset, address.base);
 
460
        return DataLabel32(this);
 
461
    }
 
462
 
 
463
    void store32(RegisterID src, ImplicitAddress address)
 
464
    {
 
465
        m_assembler.movl_rm(src, address.offset, address.base);
 
466
    }
 
467
 
 
468
    void store32(RegisterID src, BaseIndex address)
 
469
    {
 
470
        m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
 
471
    }
 
472
 
 
473
    void store32(TrustedImm32 imm, BaseIndex address)
 
474
    {
 
475
        m_assembler.movl_i32m(imm.m_value, address.offset, address.base, address.index, address.scale);
 
476
    }
 
477
 
 
478
    void store16(Imm32 imm, BaseIndex address)
 
479
    {
 
480
        m_assembler.movw_i16m(imm.m_value, address.offset, address.base, address.index, address.scale);
 
481
    }
 
482
 
 
483
    void store8(Imm32 imm, BaseIndex address)
 
484
    {
 
485
        m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
 
486
    }
 
487
 
 
488
    void store32(TrustedImm32 imm, ImplicitAddress address)
 
489
    {
 
490
        m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
 
491
    }
 
492
 
 
493
    void store16(Imm32 imm, ImplicitAddress address)
 
494
    {
 
495
        m_assembler.movw_i16m(imm.m_value, address.offset, address.base);
 
496
    }
 
497
 
 
498
    void store8(Imm32 imm, ImplicitAddress address)
 
499
    {
 
500
        m_assembler.movb_i8m(imm.m_value, address.offset, address.base);
 
501
    }
 
502
 
 
503
 
 
504
    // Floating-point operation:
 
505
    //
 
506
    // Presently only supports SSE, not x87 floating point.
 
507
 
 
508
    void moveDouble(FPRegisterID src, FPRegisterID dest)
 
509
    {
 
510
        ASSERT(isSSE2Present());
 
511
        m_assembler.movsd_rr(src, dest);
 
512
    }
 
513
 
 
514
    void loadFloat(ImplicitAddress address, FPRegisterID dest)
 
515
    {
 
516
        ASSERT(isSSE2Present());
 
517
        m_assembler.movss_mr(address.offset, address.base, dest);
 
518
        m_assembler.cvtss2sd_rr(dest, dest);
 
519
    }
 
520
 
 
521
    void loadFloat(BaseIndex address, FPRegisterID dest)
 
522
    {
 
523
        ASSERT(isSSE2Present());
 
524
        m_assembler.movss_mr(address.offset, address.base, address.index, address.scale, dest);
 
525
        m_assembler.cvtss2sd_rr(dest, dest);
 
526
    }
 
527
 
 
528
    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
 
529
    {
 
530
        ASSERT(isSSE2Present());
 
531
        m_assembler.cvtsd2ss_rr(src, dest);
 
532
    }
 
533
 
 
534
    void loadDouble(ImplicitAddress address, FPRegisterID dest)
 
535
    {
 
536
        ASSERT(isSSE2Present());
 
537
        m_assembler.movsd_mr(address.offset, address.base, dest);
 
538
    }
 
539
 
 
540
    void loadDouble(BaseIndex address, FPRegisterID dest)
 
541
    {
 
542
        ASSERT(isSSE2Present());
 
543
        m_assembler.movsd_mr(address.offset, address.base, address.index, address.scale, dest);
 
544
    }
 
545
 
 
546
    void storeFloat(ImmDouble imm, Address address)
 
547
    {
 
548
        union {
 
549
            float f;
 
550
            uint32_t u32;
 
551
        } u;
 
552
        u.f = imm.u.d;
 
553
        store32(Imm32(u.u32), address);
 
554
    }
 
555
 
 
556
    void storeFloat(ImmDouble imm, BaseIndex address)
 
557
    {
 
558
        union {
 
559
            float f;
 
560
            uint32_t u32;
 
561
        } u;
 
562
        u.f = imm.u.d;
 
563
        store32(Imm32(u.u32), address);
 
564
    }
 
565
 
 
566
    void storeDouble(FPRegisterID src, ImplicitAddress address)
 
567
    {
 
568
        ASSERT(isSSE2Present());
 
569
        m_assembler.movsd_rm(src, address.offset, address.base);
 
570
    }
 
571
 
 
572
    void storeFloat(FPRegisterID src, ImplicitAddress address)
 
573
    {
 
574
        ASSERT(isSSE2Present());
 
575
        m_assembler.movss_rm(src, address.offset, address.base);
 
576
    }
 
577
 
 
578
    void storeDouble(FPRegisterID src, BaseIndex address)
 
579
    {
 
580
        ASSERT(isSSE2Present());
 
581
        m_assembler.movsd_rm(src, address.offset, address.base, address.index, address.scale);
 
582
    }
 
583
 
 
584
    void storeFloat(FPRegisterID src, BaseIndex address)
 
585
    {
 
586
        ASSERT(isSSE2Present());
 
587
        m_assembler.movss_rm(src, address.offset, address.base, address.index, address.scale);
 
588
    }
 
589
 
 
590
    void addDouble(FPRegisterID src, FPRegisterID dest)
 
591
    {
 
592
        ASSERT(isSSE2Present());
 
593
        m_assembler.addsd_rr(src, dest);
 
594
    }
 
595
 
 
596
    void addDouble(Address src, FPRegisterID dest)
 
597
    {
 
598
        ASSERT(isSSE2Present());
 
599
        m_assembler.addsd_mr(src.offset, src.base, dest);
 
600
    }
 
601
 
 
602
    void divDouble(FPRegisterID src, FPRegisterID dest)
 
603
    {
 
604
        ASSERT(isSSE2Present());
 
605
        m_assembler.divsd_rr(src, dest);
 
606
    }
 
607
 
 
608
    void divDouble(Address src, FPRegisterID dest)
 
609
    {
 
610
        ASSERT(isSSE2Present());
 
611
        m_assembler.divsd_mr(src.offset, src.base, dest);
 
612
    }
 
613
 
 
614
    void subDouble(FPRegisterID src, FPRegisterID dest)
 
615
    {
 
616
        ASSERT(isSSE2Present());
 
617
        m_assembler.subsd_rr(src, dest);
 
618
    }
 
619
 
 
620
    void subDouble(Address src, FPRegisterID dest)
 
621
    {
 
622
        ASSERT(isSSE2Present());
 
623
        m_assembler.subsd_mr(src.offset, src.base, dest);
 
624
    }
 
625
 
 
626
    void mulDouble(FPRegisterID src, FPRegisterID dest)
 
627
    {
 
628
        ASSERT(isSSE2Present());
 
629
        m_assembler.mulsd_rr(src, dest);
 
630
    }
 
631
 
 
632
    void mulDouble(Address src, FPRegisterID dest)
 
633
    {
 
634
        ASSERT(isSSE2Present());
 
635
        m_assembler.mulsd_mr(src.offset, src.base, dest);
 
636
    }
 
637
 
 
638
    void xorDouble(FPRegisterID src, FPRegisterID dest)
 
639
    {
 
640
        ASSERT(isSSE2Present());
 
641
        m_assembler.xorpd_rr(src, dest);
 
642
    }
 
643
 
 
644
    void andDouble(FPRegisterID src, FPRegisterID dest)
 
645
    {
 
646
        ASSERT(isSSE2Present());
 
647
        m_assembler.andpd_rr(src, dest);
 
648
    }
 
649
 
 
650
    void absDouble(FPRegisterID src, FPRegisterID dest)
 
651
    {
 
652
        ASSERT(isSSE2Present());
 
653
        /* Compile abs(x) as x & -x. */
 
654
        zeroDouble(dest);
 
655
        subDouble(src, dest);
 
656
        andDouble(src, dest);
 
657
    }
 
658
 
 
659
    void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
 
660
    {
 
661
        ASSERT(isSSE2Present());
 
662
        m_assembler.cvtsi2sd_rr(src, dest);
 
663
    }
 
664
 
 
665
    void convertInt32ToDouble(Address src, FPRegisterID dest)
 
666
    {
 
667
        ASSERT(isSSE2Present());
 
668
        m_assembler.cvtsi2sd_mr(src.offset, src.base, dest);
 
669
    }
 
670
 
 
671
    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
 
672
    {
 
673
        ASSERT(isSSE2Present());
 
674
 
 
675
        if (cond & DoubleConditionBitInvert)
 
676
            m_assembler.ucomisd_rr(left, right);
 
677
        else
 
678
            m_assembler.ucomisd_rr(right, left);
 
679
 
 
680
        if (cond == DoubleEqual) {
 
681
            Jump isUnordered(m_assembler.jp());
 
682
            Jump result = Jump(m_assembler.je());
 
683
            isUnordered.link(this);
 
684
            return result;
 
685
        } else if (cond == DoubleNotEqualOrUnordered) {
 
686
            Jump isUnordered(m_assembler.jp());
 
687
            Jump isEqual(m_assembler.je());
 
688
            isUnordered.link(this);
 
689
            Jump result = jump();
 
690
            isEqual.link(this);
 
691
            return result;
 
692
        }
 
693
 
 
694
        ASSERT(!(cond & DoubleConditionBitSpecial));
 
695
        return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits)));
 
696
    }
 
697
 
 
698
    // Truncates 'src' to an integer, and places the resulting 'dest'.
 
699
    // If the result is not representable as a 32 bit value, branch.
 
700
    // May also branch for some values that are representable in 32 bits
 
701
    // (specifically, in this case, INT_MIN).
 
702
    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
 
703
    {
 
704
        ASSERT(isSSE2Present());
 
705
        m_assembler.cvttsd2si_rr(src, dest);
 
706
        return branch32(Equal, dest, Imm32(0x80000000));
 
707
    }
 
708
 
 
709
    // Convert 'src' to an integer, and places the resulting 'dest'.
 
710
    // If the result is not representable as a 32 bit value, branch.
 
711
    // May also branch for some values that are representable in 32 bits
 
712
    // (specifically, in this case, 0).
 
713
    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
 
714
    {
 
715
        ASSERT(isSSE2Present());
 
716
        ASSERT(src != fpTemp); 
 
717
        m_assembler.cvttsd2si_rr(src, dest);
 
718
 
 
719
        // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
 
720
        failureCases.append(branchTest32(Zero, dest));
 
721
 
 
722
        // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
 
723
        convertInt32ToDouble(dest, fpTemp);
 
724
        m_assembler.ucomisd_rr(fpTemp, src);
 
725
        failureCases.append(m_assembler.jp());
 
726
        failureCases.append(m_assembler.jne());
 
727
    }
 
728
 
 
729
    void zeroDouble(FPRegisterID srcDest)
 
730
    {
 
731
        ASSERT(isSSE2Present());
 
732
        m_assembler.xorpd_rr(srcDest, srcDest);
 
733
    }
 
734
 
 
735
 
 
736
    // Stack manipulation operations:
 
737
    //
 
738
    // The ABI is assumed to provide a stack abstraction to memory,
 
739
    // containing machine word sized units of data.  Push and pop
 
740
    // operations add and remove a single register sized unit of data
 
741
    // to or from the stack.  Peek and poke operations read or write
 
742
    // values on the stack, without moving the current stack position.
 
743
    
 
744
    void pop(RegisterID dest)
 
745
    {
 
746
        m_assembler.pop_r(dest);
 
747
    }
 
748
 
 
749
    void push(RegisterID src)
 
750
    {
 
751
        m_assembler.push_r(src);
 
752
    }
 
753
 
 
754
    void push(Address address)
 
755
    {
 
756
        m_assembler.push_m(address.offset, address.base);
 
757
    }
 
758
 
 
759
    void push(Imm32 imm)
 
760
    {
 
761
        m_assembler.push_i32(imm.m_value);
 
762
    }
 
763
 
 
764
 
 
765
    // Register move operations:
 
766
    //
 
767
    // Move values in registers.
 
768
 
 
769
    void move(TrustedImm32 imm, RegisterID dest)
 
770
    {
 
771
        // Note: on 64-bit the Imm32 value is zero extended into the register, it
 
772
        // may be useful to have a separate version that sign extends the value?
 
773
        if (!imm.m_value)
 
774
            m_assembler.xorl_rr(dest, dest);
 
775
        else
 
776
            m_assembler.movl_i32r(imm.m_value, dest);
 
777
    }
 
778
 
 
779
#if WTF_CPU_X86_64
 
780
    void move(RegisterID src, RegisterID dest)
 
781
    {
 
782
        // Note: on 64-bit this is is a full register move; perhaps it would be
 
783
        // useful to have separate move32 & movePtr, with move32 zero extending?
 
784
        if (src != dest)
 
785
            m_assembler.movq_rr(src, dest);
 
786
    }
 
787
 
 
788
    void move(TrustedImmPtr imm, RegisterID dest)
 
789
    {
 
790
        m_assembler.movq_i64r(imm.asIntptr(), dest);
 
791
    }
 
792
 
 
793
    void swap(RegisterID reg1, RegisterID reg2)
 
794
    {
 
795
        // XCHG is extremely slow. Don't use XCHG.
 
796
        if (reg1 != reg2) {
 
797
            m_assembler.movq_rr(reg1, scratchRegister);
 
798
            m_assembler.movq_rr(reg2, reg1);
 
799
            m_assembler.movq_rr(scratchRegister, reg2);
 
800
        }
 
801
    }
 
802
 
 
803
    void signExtend32ToPtr(RegisterID src, RegisterID dest)
 
804
    {
 
805
        m_assembler.movsxd_rr(src, dest);
 
806
    }
 
807
 
 
808
    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
 
809
    {
 
810
        m_assembler.movl_rr(src, dest);
 
811
    }
 
812
#else
 
813
    void move(RegisterID src, RegisterID dest)
 
814
    {
 
815
        if (src != dest)
 
816
            m_assembler.movl_rr(src, dest);
 
817
    }
 
818
 
 
819
    void move(TrustedImmPtr imm, RegisterID dest)
 
820
    {
 
821
        m_assembler.movl_i32r(imm.asIntptr(), dest);
 
822
    }
 
823
 
 
824
    void swap(RegisterID reg1, RegisterID reg2)
 
825
    {
 
826
        if (reg1 != reg2)
 
827
            m_assembler.xchgl_rr(reg1, reg2);
 
828
    }
 
829
 
 
830
    void signExtend32ToPtr(RegisterID src, RegisterID dest)
 
831
    {
 
832
        move(src, dest);
 
833
    }
 
834
 
 
835
    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
 
836
    {
 
837
        move(src, dest);
 
838
    }
 
839
#endif
 
840
 
 
841
 
 
842
    // Forwards / external control flow operations:
 
843
    //
 
844
    // This set of jump and conditional branch operations return a Jump
 
845
    // object which may linked at a later point, allow forwards jump,
 
846
    // or jumps that will require external linkage (after the code has been
 
847
    // relocated).
 
848
    //
 
849
    // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
 
850
    // respecitvely, for unsigned comparisons the names b, a, be, and ae are
 
851
    // used (representing the names 'below' and 'above').
 
852
    //
 
853
    // Operands to the comparision are provided in the expected order, e.g.
 
854
    // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
 
855
    // treated as a signed 32bit value, is less than or equal to 5.
 
856
    //
 
857
    // jz and jnz test whether the first operand is equal to zero, and take
 
858
    // an optional second operand of a mask under which to perform the test.
 
859
 
 
860
public:
 
861
    Jump branch8(Condition cond, Address left, Imm32 right)
 
862
    {
 
863
        m_assembler.cmpb_im(right.m_value, left.offset, left.base);
 
864
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
865
    }
 
866
 
 
867
    Jump branch32(Condition cond, RegisterID left, RegisterID right)
 
868
    {
 
869
        m_assembler.cmpl_rr(right, left);
 
870
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
871
    }
 
872
 
 
873
    Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
 
874
    {
 
875
        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
 
876
            m_assembler.testl_rr(left, left);
 
877
        else
 
878
            m_assembler.cmpl_ir(right.m_value, left);
 
879
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
880
    }
 
881
    
 
882
    // Branch based on a 32-bit comparison, forcing the size of the
 
883
    // immediate operand to 32 bits in the native code stream to ensure that
 
884
    // the length of code emitted by this instruction is consistent.
 
885
    Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
 
886
    {
 
887
        m_assembler.cmpl_ir_force32(right.m_value, left);
 
888
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
889
    }
 
890
 
 
891
    // Branch and record a label after the comparison.
 
892
    Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32 &dataLabel)
 
893
    {
 
894
        // Always use cmpl, since the value is to be patched.
 
895
        m_assembler.cmpl_ir_force32(right.m_value, left);
 
896
        dataLabel = DataLabel32(this);
 
897
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
898
    }
 
899
 
 
900
    Jump branch32WithPatch(Condition cond, Address left, TrustedImm32 right, DataLabel32 &dataLabel)
 
901
    {
 
902
        m_assembler.cmpl_im_force32(right.m_value, left.offset, left.base);
 
903
        dataLabel = DataLabel32(this);
 
904
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
905
    }
 
906
 
 
907
    Jump branch32(Condition cond, RegisterID left, Address right)
 
908
    {
 
909
        m_assembler.cmpl_mr(right.offset, right.base, left);
 
910
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
911
    }
 
912
    
 
913
    Jump branch32(Condition cond, Address left, RegisterID right)
 
914
    {
 
915
        m_assembler.cmpl_rm(right, left.offset, left.base);
 
916
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
917
    }
 
918
 
 
919
    Jump branch32(Condition cond, Address left, TrustedImm32 right)
 
920
    {
 
921
        m_assembler.cmpl_im(right.m_value, left.offset, left.base);
 
922
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
923
    }
 
924
 
 
925
    Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
 
926
    {
 
927
        m_assembler.cmpl_im(right.m_value, left.offset, left.base, left.index, left.scale);
 
928
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
929
    }
 
930
 
 
931
    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
 
932
    {
 
933
        return branch32(cond, left, right);
 
934
    }
 
935
 
 
936
    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
 
937
    {
 
938
        m_assembler.cmpw_rm(right, left.offset, left.base, left.index, left.scale);
 
939
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
940
    }
 
941
 
 
942
    Jump branch16(Condition cond, BaseIndex left, Imm32 right)
 
943
    {
 
944
        ASSERT(!(right.m_value & 0xFFFF0000));
 
945
 
 
946
        m_assembler.cmpw_im(right.m_value, left.offset, left.base, left.index, left.scale);
 
947
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
948
    }
 
949
 
 
950
    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
 
951
    {
 
952
        ASSERT((cond == Zero) || (cond == NonZero));
 
953
        m_assembler.testl_rr(reg, mask);
 
954
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
955
    }
 
956
 
 
957
    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
 
958
    {
 
959
        ASSERT((cond == Zero) || (cond == NonZero));
 
960
        // if we are only interested in the low seven bits, this can be tested with a testb
 
961
        if (mask.m_value == -1)
 
962
            m_assembler.testl_rr(reg, reg);
 
963
        else if (CanUse8Bit(reg) && (mask.m_value & ~0x7f) == 0)
 
964
            m_assembler.testb_i8r(mask.m_value, reg);
 
965
        else
 
966
            m_assembler.testl_i32r(mask.m_value, reg);
 
967
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
968
    }
 
969
 
 
970
    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
 
971
    {
 
972
        ASSERT((cond == Zero) || (cond == NonZero));
 
973
        if (mask.m_value == -1)
 
974
            m_assembler.cmpl_im(0, address.offset, address.base);
 
975
        else
 
976
            m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
 
977
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
978
    }
 
979
 
 
980
    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
 
981
    {
 
982
        ASSERT((cond == Zero) || (cond == NonZero));
 
983
        if (mask.m_value == -1)
 
984
            m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
 
985
        else
 
986
            m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
 
987
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
988
    }
 
989
    
 
990
    Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
 
991
    {
 
992
        ASSERT((cond == Zero) || (cond == NonZero));
 
993
        if (mask.m_value == -1)
 
994
            m_assembler.cmpb_im(0, address.offset, address.base);
 
995
        else
 
996
            m_assembler.testb_im(mask.m_value, address.offset, address.base);
 
997
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
998
    }
 
999
    
 
1000
    Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
 
1001
    {
 
1002
        ASSERT((cond == Zero) || (cond == NonZero));
 
1003
        if (mask.m_value == -1)
 
1004
            m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale);
 
1005
        else
 
1006
            m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale);
 
1007
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1008
    }
 
1009
 
 
1010
    Jump jump()
 
1011
    {
 
1012
        return Jump(m_assembler.jmp());
 
1013
    }
 
1014
 
 
1015
    void jump(RegisterID target)
 
1016
    {
 
1017
        m_assembler.jmp_r(target);
 
1018
    }
 
1019
 
 
1020
    // Address is a memory location containing the address to jump to
 
1021
    void jump(Address address)
 
1022
    {
 
1023
        m_assembler.jmp_m(address.offset, address.base);
 
1024
    }
 
1025
 
 
1026
    void jump(BaseIndex address)
 
1027
    {
 
1028
        m_assembler.jmp_m(address.offset, address.base, address.index, address.scale);
 
1029
    }
 
1030
 
 
1031
    // Arithmetic control flow operations:
 
1032
    //
 
1033
    // This set of conditional branch operations branch based
 
1034
    // on the result of an arithmetic operation.  The operation
 
1035
    // is performed as normal, storing the result.
 
1036
    //
 
1037
    // * jz operations branch if the result is zero.
 
1038
    // * jo operations branch if the (signed) arithmetic
 
1039
    //   operation caused an overflow to occur.
 
1040
    
 
1041
    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
 
1042
    {
 
1043
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
1044
        add32(src, dest);
 
1045
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1046
    }
 
1047
 
 
1048
    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
 
1049
    {
 
1050
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
1051
        add32(imm, dest);
 
1052
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1053
    }
 
1054
    
 
1055
    Jump branchAdd32(Condition cond, Imm32 src, Address dest)
 
1056
    {
 
1057
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1058
        add32(src, dest);
 
1059
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1060
    }
 
1061
 
 
1062
    Jump branchAdd32(Condition cond, RegisterID src, Address dest)
 
1063
    {
 
1064
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1065
        add32(src, dest);
 
1066
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1067
    }
 
1068
 
 
1069
    Jump branchAdd32(Condition cond, Address src, RegisterID dest)
 
1070
    {
 
1071
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1072
        add32(src, dest);
 
1073
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1074
    }
 
1075
 
 
1076
    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
 
1077
    {
 
1078
        ASSERT(cond == Overflow);
 
1079
        mul32(src, dest);
 
1080
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1081
    }
 
1082
 
 
1083
    Jump branchMul32(Condition cond, Address src, RegisterID dest)
 
1084
    {
 
1085
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1086
        mul32(src, dest);
 
1087
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1088
    }
 
1089
    
 
1090
    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
 
1091
    {
 
1092
        ASSERT(cond == Overflow);
 
1093
        mul32(imm, src, dest);
 
1094
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1095
    }
 
1096
    
 
1097
    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
 
1098
    {
 
1099
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
1100
        sub32(src, dest);
 
1101
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1102
    }
 
1103
    
 
1104
    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
 
1105
    {
 
1106
        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
 
1107
        sub32(imm, dest);
 
1108
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1109
    }
 
1110
 
 
1111
    Jump branchSub32(Condition cond, Imm32 imm, Address dest)
 
1112
    {
 
1113
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1114
        sub32(imm, dest);
 
1115
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1116
    }
 
1117
 
 
1118
    Jump branchSub32(Condition cond, RegisterID src, Address dest)
 
1119
    {
 
1120
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1121
        sub32(src, dest);
 
1122
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1123
    }
 
1124
 
 
1125
    Jump branchSub32(Condition cond, Address src, RegisterID dest)
 
1126
    {
 
1127
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1128
        sub32(src, dest);
 
1129
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1130
    }
 
1131
 
 
1132
    Jump branchNeg32(Condition cond, RegisterID srcDest)
 
1133
    {
 
1134
        ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero));
 
1135
        neg32(srcDest);
 
1136
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1137
    }
 
1138
 
 
1139
    Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
 
1140
    {
 
1141
        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
 
1142
        or32(src, dest);
 
1143
        return Jump(m_assembler.jCC(x86Condition(cond)));
 
1144
    }
 
1145
 
 
1146
 
 
1147
    // Miscellaneous operations:
 
1148
 
 
1149
    void breakpoint()
 
1150
    {
 
1151
        m_assembler.int3();
 
1152
    }
 
1153
 
 
1154
    Call nearCall()
 
1155
    {
 
1156
        return Call(m_assembler.call(), Call::LinkableNear);
 
1157
    }
 
1158
 
 
1159
    Call call(RegisterID target)
 
1160
    {
 
1161
        return Call(m_assembler.call(target), Call::None);
 
1162
    }
 
1163
 
 
1164
    void call(Address address)
 
1165
    {
 
1166
        m_assembler.call_m(address.offset, address.base);
 
1167
    }
 
1168
 
 
1169
    void ret()
 
1170
    {
 
1171
        m_assembler.ret();
 
1172
    }
 
1173
 
 
1174
    void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
 
1175
    {
 
1176
        m_assembler.cmpl_rr(right, left);
 
1177
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1178
    }
 
1179
 
 
1180
    void set8(Condition cond, Address left, RegisterID right, RegisterID dest)
 
1181
    {
 
1182
        m_assembler.cmpl_mr(left.offset, left.base, right);
 
1183
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1184
    }
 
1185
 
 
1186
    void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
 
1187
    {
 
1188
        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
 
1189
            m_assembler.testl_rr(left, left);
 
1190
        else
 
1191
            m_assembler.cmpl_ir(right.m_value, left);
 
1192
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1193
    }
 
1194
 
 
1195
    void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
 
1196
    {
 
1197
        m_assembler.cmpl_rm(right, left.offset, left.base);
 
1198
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1199
        m_assembler.movzbl_rr(dest, dest);
 
1200
    }
 
1201
 
 
1202
    void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
 
1203
    {
 
1204
        m_assembler.cmpl_mr(right.offset, right.base, left);
 
1205
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1206
        m_assembler.movzbl_rr(dest, dest);
 
1207
    }
 
1208
 
 
1209
    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
 
1210
    {
 
1211
        m_assembler.cmpl_rr(right, left);
 
1212
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1213
        m_assembler.movzbl_rr(dest, dest);
 
1214
    }
 
1215
 
 
1216
    void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
 
1217
    {
 
1218
        m_assembler.cmpl_im(right.m_value, left.offset, left.base);
 
1219
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1220
        m_assembler.movzbl_rr(dest, dest);
 
1221
    }
 
1222
 
 
1223
    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
 
1224
    {
 
1225
        if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)
 
1226
            m_assembler.testl_rr(left, left);
 
1227
        else
 
1228
            m_assembler.cmpl_ir(right.m_value, left);
 
1229
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1230
        m_assembler.movzbl_rr(dest, dest);
 
1231
    }
 
1232
 
 
1233
    // FIXME:
 
1234
    // The mask should be optional... paerhaps the argument order should be
 
1235
    // dest-src, operations always have a dest? ... possibly not true, considering
 
1236
    // asm ops like test, or pseudo ops like pop().
 
1237
 
 
1238
    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
 
1239
    {
 
1240
        if (mask.m_value == -1)
 
1241
            m_assembler.cmpb_im(0, address.offset, address.base);
 
1242
        else
 
1243
            m_assembler.testb_im(mask.m_value, address.offset, address.base);
 
1244
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1245
        m_assembler.movzbl_rr(dest, dest);
 
1246
    }
 
1247
 
 
1248
    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
 
1249
    {
 
1250
        if (mask.m_value == -1)
 
1251
            m_assembler.cmpl_im(0, address.offset, address.base);
 
1252
        else
 
1253
            m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
 
1254
        m_assembler.setCC_r(x86Condition(cond), dest);
 
1255
        m_assembler.movzbl_rr(dest, dest);
 
1256
    }
 
1257
 
 
1258
    // As the SSE's were introduced in order, the presence of a later SSE implies
 
1259
    // the presence of an earlier SSE. For example, SSE4_2 support implies SSE2 support.
 
1260
    enum SSECheckState {
 
1261
        NotCheckedSSE = 0,
 
1262
        NoSSE = 1,
 
1263
        HasSSE = 2,
 
1264
        HasSSE2 = 3,
 
1265
        HasSSE3 = 4,
 
1266
        HasSSSE3 = 5,
 
1267
        HasSSE4_1 = 6,
 
1268
        HasSSE4_2 = 7
 
1269
    };
 
1270
 
 
1271
    static SSECheckState getSSEState()
 
1272
    {
 
1273
        if (s_sseCheckState == NotCheckedSSE) {
 
1274
            MacroAssemblerX86Common::setSSECheckState();
 
1275
        }
 
1276
        // Only check once.
 
1277
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1278
 
 
1279
        return s_sseCheckState;
 
1280
    }
 
1281
 
 
1282
protected:
 
1283
    X86Assembler::Condition x86Condition(Condition cond)
 
1284
    {
 
1285
        return static_cast<X86Assembler::Condition>(cond);
 
1286
    }
 
1287
 
 
1288
private:
 
1289
    friend class MacroAssemblerX86;
 
1290
 
 
1291
    static SSECheckState s_sseCheckState;
 
1292
 
 
1293
    static void setSSECheckState()
 
1294
    {
 
1295
        // Default the flags value to zero; if the compiler is
 
1296
        // not MSVC or GCC we will read this as SSE2 not present.
 
1297
        volatile int flags_edx = 0;
 
1298
        volatile int flags_ecx = 0;
 
1299
#if WTF_COMPILER_MSVC
 
1300
#if WTF_CPU_X86_64
 
1301
        int cpuinfo[4];
 
1302
 
 
1303
        __cpuid(cpuinfo, 1);
 
1304
        flags_ecx = cpuinfo[2];
 
1305
        flags_edx = cpuinfo[3];
 
1306
#else
 
1307
        _asm {
 
1308
            mov eax, 1 // cpuid function 1 gives us the standard feature set
 
1309
            cpuid;
 
1310
            mov flags_ecx, ecx;
 
1311
            mov flags_edx, edx;
 
1312
        }
 
1313
#endif
 
1314
#elif WTF_COMPILER_GCC
 
1315
#if WTF_CPU_X86_64
 
1316
        asm (
 
1317
             "movl $0x1, %%eax;"
 
1318
             "pushq %%rbx;"
 
1319
             "cpuid;"
 
1320
             "popq %%rbx;"
 
1321
             "movl %%ecx, %0;"
 
1322
             "movl %%edx, %1;"
 
1323
             : "=g" (flags_ecx), "=g" (flags_edx)
 
1324
             :
 
1325
             : "%eax", "%ecx", "%edx"
 
1326
             );
 
1327
#else
 
1328
        asm (
 
1329
             "movl $0x1, %%eax;"
 
1330
             "pushl %%ebx;"
 
1331
             "cpuid;"
 
1332
             "popl %%ebx;"
 
1333
             "movl %%ecx, %0;"
 
1334
             "movl %%edx, %1;"
 
1335
             : "=g" (flags_ecx), "=g" (flags_edx)
 
1336
             :
 
1337
             : "%eax", "%ecx", "%edx"
 
1338
             );
 
1339
#endif
 
1340
#elif WTF_COMPILER_SUNCC
 
1341
#if WTF_CPU_X86_64
 
1342
        asm (
 
1343
             "movl $0x1, %%eax;"
 
1344
             "pushq %%rbx;"
 
1345
             "cpuid;"
 
1346
             "popq %%rbx;"
 
1347
             "movl %%ecx, (%rsi);"
 
1348
             "movl %%edx, (%rdi);"
 
1349
             :
 
1350
             : "S" (&flags_ecx), "D" (&flags_edx)
 
1351
             : "%eax", "%ecx", "%edx"
 
1352
             );
 
1353
#else
 
1354
        asm (
 
1355
             "movl $0x1, %eax;"
 
1356
             "pushl %ebx;"
 
1357
             "cpuid;"
 
1358
             "popl %ebx;"
 
1359
             "movl %ecx, (%esi);"
 
1360
             "movl %edx, (%edi);"
 
1361
             :
 
1362
             : "S" (&flags_ecx), "D" (&flags_edx)
 
1363
             : "%eax", "%ecx", "%edx"
 
1364
             );
 
1365
#endif
 
1366
#endif
 
1367
        static const int SSEFeatureBit = 1 << 25;
 
1368
        static const int SSE2FeatureBit = 1 << 26;
 
1369
        static const int SSE3FeatureBit = 1 << 0;
 
1370
        static const int SSSE3FeatureBit = 1 << 9;
 
1371
        static const int SSE41FeatureBit = 1 << 19;
 
1372
        static const int SSE42FeatureBit = 1 << 20;
 
1373
        if (flags_ecx & SSE42FeatureBit)
 
1374
            s_sseCheckState = HasSSE4_2;
 
1375
        else if (flags_ecx & SSE41FeatureBit)
 
1376
            s_sseCheckState = HasSSE4_1;
 
1377
        else if (flags_ecx & SSSE3FeatureBit)
 
1378
            s_sseCheckState = HasSSSE3;
 
1379
        else if (flags_ecx & SSE3FeatureBit)
 
1380
            s_sseCheckState = HasSSE3;
 
1381
        else if (flags_edx & SSE2FeatureBit)
 
1382
            s_sseCheckState = HasSSE2;
 
1383
        else if (flags_edx & SSEFeatureBit)
 
1384
            s_sseCheckState = HasSSE;
 
1385
        else
 
1386
            s_sseCheckState = NoSSE;
 
1387
    }
 
1388
 
 
1389
#if WTF_CPU_X86
 
1390
#if WTF_OS_MAC_OS_X
 
1391
 
 
1392
    // All X86 Macs are guaranteed to support at least SSE2
 
1393
    static bool isSSEPresent()
 
1394
    {
 
1395
        return true;
 
1396
    }
 
1397
 
 
1398
    static bool isSSE2Present()
 
1399
    {
 
1400
        return true;
 
1401
    }
 
1402
 
 
1403
#else // OS(MAC_OS_X)
 
1404
 
 
1405
    static bool isSSEPresent()
 
1406
    {
 
1407
        if (s_sseCheckState == NotCheckedSSE) {
 
1408
            setSSECheckState();
 
1409
        }
 
1410
        // Only check once.
 
1411
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1412
 
 
1413
        return s_sseCheckState >= HasSSE;
 
1414
    }
 
1415
 
 
1416
    static bool isSSE2Present()
 
1417
    {
 
1418
        if (s_sseCheckState == NotCheckedSSE) {
 
1419
            setSSECheckState();
 
1420
        }
 
1421
        // Only check once.
 
1422
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1423
 
 
1424
        return s_sseCheckState >= HasSSE2;
 
1425
    }
 
1426
    
 
1427
 
 
1428
#endif // PLATFORM(MAC)
 
1429
#elif !defined(NDEBUG) // CPU(X86)
 
1430
 
 
1431
    // On x86-64 we should never be checking for SSE2 in a non-debug build,
 
1432
    // but non debug add this method to keep the asserts above happy.
 
1433
    static bool isSSE2Present()
 
1434
    {
 
1435
        return true;
 
1436
    }
 
1437
 
 
1438
#endif
 
1439
    static bool isSSE3Present()
 
1440
    {
 
1441
        if (s_sseCheckState == NotCheckedSSE) {
 
1442
            setSSECheckState();
 
1443
        }
 
1444
        // Only check once.
 
1445
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1446
 
 
1447
        return s_sseCheckState >= HasSSE3;
 
1448
    }
 
1449
 
 
1450
    static bool isSSSE3Present()
 
1451
    {
 
1452
        if (s_sseCheckState == NotCheckedSSE) {
 
1453
            setSSECheckState();
 
1454
        }
 
1455
        // Only check once.
 
1456
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1457
 
 
1458
        return s_sseCheckState >= HasSSSE3;
 
1459
    }
 
1460
 
 
1461
    static bool isSSE41Present()
 
1462
    {
 
1463
        if (s_sseCheckState == NotCheckedSSE) {
 
1464
            setSSECheckState();
 
1465
        }
 
1466
        // Only check once.
 
1467
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1468
 
 
1469
        return s_sseCheckState >= HasSSE4_1;
 
1470
    }
 
1471
 
 
1472
    static bool isSSE42Present()
 
1473
    {
 
1474
        if (s_sseCheckState == NotCheckedSSE) {
 
1475
            setSSECheckState();
 
1476
        }
 
1477
        // Only check once.
 
1478
        ASSERT(s_sseCheckState != NotCheckedSSE);
 
1479
 
 
1480
        return s_sseCheckState >= HasSSE4_2;
 
1481
    }
 
1482
};
 
1483
 
 
1484
} // namespace JSC
 
1485
 
 
1486
#endif // ENABLE(ASSEMBLER)
 
1487
 
 
1488
#endif // MacroAssemblerX86Common_h