1/*
2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef DFGFPRInfo_h
27#define DFGFPRInfo_h
28
29#if ENABLE(DFG_JIT)
30
31#include "DFGRegisterBank.h"
32#include "MacroAssembler.h"
33
34namespace JSC { namespace DFG {
35
36typedef MacroAssembler::FPRegisterID FPRReg;
37#define InvalidFPRReg ((FPRReg)-1)
38
39#if CPU(X86) || CPU(X86_64)
40
41class FPRInfo {
42public:
43    typedef FPRReg RegisterType;
44    static const unsigned numberOfRegisters = 6;
45
46    // Temporary registers.
47    static const FPRReg fpRegT0 = X86Registers::xmm0;
48    static const FPRReg fpRegT1 = X86Registers::xmm1;
49    static const FPRReg fpRegT2 = X86Registers::xmm2;
50    static const FPRReg fpRegT3 = X86Registers::xmm3;
51    static const FPRReg fpRegT4 = X86Registers::xmm4;
52    static const FPRReg fpRegT5 = X86Registers::xmm5;
53#if CPU(X86_64)
54    // Only X86_64 passes aguments in xmm registers
55    static const FPRReg argumentFPR0 = X86Registers::xmm0; // fpRegT0
56    static const FPRReg argumentFPR1 = X86Registers::xmm1; // fpRegT1
57    static const FPRReg argumentFPR2 = X86Registers::xmm2; // fpRegT2
58    static const FPRReg argumentFPR3 = X86Registers::xmm3; // fpRegT3
59#endif
60    // On X86 the return will actually be on the x87 stack,
61    // so we'll copy to xmm0 for sanity!
62    static const FPRReg returnValueFPR = X86Registers::xmm0; // fpRegT0
63
64    // FPRReg mapping is direct, the machine regsiter numbers can
65    // be used directly as indices into the FPR RegisterBank.
66    COMPILE_ASSERT(X86Registers::xmm0 == 0, xmm0_is_0);
67    COMPILE_ASSERT(X86Registers::xmm1 == 1, xmm1_is_1);
68    COMPILE_ASSERT(X86Registers::xmm2 == 2, xmm2_is_2);
69    COMPILE_ASSERT(X86Registers::xmm3 == 3, xmm3_is_3);
70    COMPILE_ASSERT(X86Registers::xmm4 == 4, xmm4_is_4);
71    COMPILE_ASSERT(X86Registers::xmm5 == 5, xmm5_is_5);
72    static FPRReg toRegister(unsigned index)
73    {
74        return (FPRReg)index;
75    }
76    static unsigned toIndex(FPRReg reg)
77    {
78        return (unsigned)reg;
79    }
80
81    static const char* debugName(FPRReg reg)
82    {
83        ASSERT(reg != InvalidFPRReg);
84#if CPU(X86_64)
85        ASSERT(static_cast<int>(reg) < 16);
86        static const char* nameForRegister[16] = {
87            "xmm0", "xmm1", "xmm2", "xmm3",
88            "xmm4", "xmm5", "xmm6", "xmm7",
89            "xmm8", "xmm9", "xmm10", "xmm11",
90            "xmm12", "xmm13", "xmm14", "xmm15"
91        };
92#elif CPU(X86)
93        ASSERT(static_cast<int>(reg) < 8);
94        static const char* nameForRegister[8] = {
95            "xmm0", "xmm1", "xmm2", "xmm3",
96            "xmm4", "xmm5", "xmm6", "xmm7"
97        };
98#endif
99        return nameForRegister[reg];
100    }
101};
102
103#endif
104
105#if CPU(ARM)
106
107class FPRInfo {
108public:
109    typedef FPRReg RegisterType;
110    static const unsigned numberOfRegisters = 6;
111
112    // Temporary registers.
113    // d7 is use by the MacroAssembler as fpTempRegister.
114    static const FPRReg fpRegT0 = ARMRegisters::d0;
115    static const FPRReg fpRegT1 = ARMRegisters::d1;
116    static const FPRReg fpRegT2 = ARMRegisters::d2;
117    static const FPRReg fpRegT3 = ARMRegisters::d3;
118    static const FPRReg fpRegT4 = ARMRegisters::d4;
119    static const FPRReg fpRegT5 = ARMRegisters::d5;
120    // ARMv7 doesn't pass arguments in fp registers. The return
121    // value is also actually in integer registers, for now
122    // we'll return in d0 for simplicity.
123    static const FPRReg returnValueFPR = ARMRegisters::d0; // fpRegT0
124
125#if CPU(ARM_HARDFP)
126    static const FPRReg argumentFPR0 = ARMRegisters::d0; // fpRegT0
127    static const FPRReg argumentFPR1 = ARMRegisters::d1; // fpRegT1
128#endif
129
130    // FPRReg mapping is direct, the machine regsiter numbers can
131    // be used directly as indices into the FPR RegisterBank.
132    COMPILE_ASSERT(ARMRegisters::d0 == 0, d0_is_0);
133    COMPILE_ASSERT(ARMRegisters::d1 == 1, d1_is_1);
134    COMPILE_ASSERT(ARMRegisters::d2 == 2, d2_is_2);
135    COMPILE_ASSERT(ARMRegisters::d3 == 3, d3_is_3);
136    COMPILE_ASSERT(ARMRegisters::d4 == 4, d4_is_4);
137    COMPILE_ASSERT(ARMRegisters::d5 == 5, d5_is_5);
138    static FPRReg toRegister(unsigned index)
139    {
140        return (FPRReg)index;
141    }
142    static unsigned toIndex(FPRReg reg)
143    {
144        return (unsigned)reg;
145    }
146
147    static const char* debugName(FPRReg reg)
148    {
149        ASSERT(reg != InvalidFPRReg);
150        ASSERT(static_cast<int>(reg) < 32);
151        static const char* nameForRegister[32] = {
152            "d0", "d1", "d2", "d3",
153            "d4", "d5", "d6", "d7",
154            "d8", "d9", "d10", "d11",
155            "d12", "d13", "d14", "d15",
156            "d16", "d17", "d18", "d19",
157            "d20", "d21", "d22", "d23",
158            "d24", "d25", "d26", "d27",
159            "d28", "d29", "d30", "d31"
160        };
161        return nameForRegister[reg];
162    }
163};
164
165#endif
166
167#if CPU(MIPS)
168
169class FPRInfo {
170public:
171    typedef FPRReg RegisterType;
172    static const unsigned numberOfRegisters = 6;
173
174    // Temporary registers.
175    static const FPRReg fpRegT0 = MIPSRegisters::f0;
176    static const FPRReg fpRegT1 = MIPSRegisters::f4;
177    static const FPRReg fpRegT2 = MIPSRegisters::f6;
178    static const FPRReg fpRegT3 = MIPSRegisters::f8;
179    static const FPRReg fpRegT4 = MIPSRegisters::f10;
180    static const FPRReg fpRegT5 = MIPSRegisters::f18;
181
182    static const FPRReg returnValueFPR = MIPSRegisters::f0;
183
184    static const FPRReg argumentFPR0 = MIPSRegisters::f12;
185    static const FPRReg argumentFPR1 = MIPSRegisters::f14;
186
187    static FPRReg toRegister(unsigned index)
188    {
189        static const FPRReg registerForIndex[numberOfRegisters] = {
190            fpRegT0, fpRegT1, fpRegT2, fpRegT3, fpRegT4, fpRegT5 };
191
192        ASSERT(index < numberOfRegisters);
193        return registerForIndex[index];
194    }
195
196    static unsigned toIndex(FPRReg reg)
197    {
198        ASSERT(reg != InvalidFPRReg);
199        ASSERT(reg < 20);
200        static const unsigned indexForRegister[20] = {
201            0, InvalidIndex, InvalidIndex, InvalidIndex,
202            1, InvalidIndex, 2, InvalidIndex,
203            3, InvalidIndex, 4, InvalidIndex,
204            InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex,
205            InvalidIndex, InvalidIndex, 5, InvalidIndex,
206        };
207        unsigned result = indexForRegister[reg];
208        ASSERT(result != InvalidIndex);
209        return result;
210    }
211
212    static const char* debugName(FPRReg reg)
213    {
214        ASSERT(reg != InvalidFPRReg);
215        ASSERT(reg < 32);
216        static const char* nameForRegister[32] = {
217            "f0", "f1", "f2", "f3",
218            "f4", "f5", "f6", "f7",
219            "f8", "f9", "f10", "f11",
220            "f12", "f13", "f14", "f15"
221            "f16", "f17", "f18", "f19"
222            "f20", "f21", "f22", "f23"
223            "f24", "f25", "f26", "f27"
224            "f28", "f29", "f30", "f31"
225        };
226        return nameForRegister[reg];
227    }
228private:
229
230    static const unsigned InvalidIndex = 0xffffffff;
231};
232
233#endif
234
235typedef RegisterBank<FPRInfo>::iterator fpr_iterator;
236
237} } // namespace JSC::DFG
238
239#endif
240#endif
241