1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef jit_x86_shared_Constants_x86_shared_h
8 #define jit_x86_shared_Constants_x86_shared_h
9
10 #include "mozilla/ArrayUtils.h"
11 #include "mozilla/Assertions.h"
12
13 #include <stddef.h>
14 #include <stdint.h>
15
16 namespace js {
17 namespace jit {
18
19 namespace X86Encoding {
20
21 enum RegisterID : uint8_t {
22 rax,
23 rcx,
24 rdx,
25 rbx,
26 rsp,
27 rbp,
28 rsi,
29 rdi
30 #ifdef JS_CODEGEN_X64
31 ,
32 r8,
33 r9,
34 r10,
35 r11,
36 r12,
37 r13,
38 r14,
39 r15
40 #endif
41 ,
42 invalid_reg
43 };
44
45 enum HRegisterID { ah = rsp, ch = rbp, dh = rsi, bh = rdi };
46
47 enum XMMRegisterID {
48 xmm0,
49 xmm1,
50 xmm2,
51 xmm3,
52 xmm4,
53 xmm5,
54 xmm6,
55 xmm7
56 #ifdef JS_CODEGEN_X64
57 ,
58 xmm8,
59 xmm9,
60 xmm10,
61 xmm11,
62 xmm12,
63 xmm13,
64 xmm14,
65 xmm15
66 #endif
67 ,
68 invalid_xmm
69 };
70
XMMRegName(XMMRegisterID reg)71 inline const char* XMMRegName(XMMRegisterID reg) {
72 static const char* const names[] = {"%xmm0",
73 "%xmm1",
74 "%xmm2",
75 "%xmm3",
76 "%xmm4",
77 "%xmm5",
78 "%xmm6",
79 "%xmm7"
80 #ifdef JS_CODEGEN_X64
81 ,
82 "%xmm8",
83 "%xmm9",
84 "%xmm10",
85 "%xmm11",
86 "%xmm12",
87 "%xmm13",
88 "%xmm14",
89 "%xmm15"
90 #endif
91 };
92 MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
93 return names[reg];
94 }
95
96 #ifdef JS_CODEGEN_X64
GPReg64Name(RegisterID reg)97 inline const char* GPReg64Name(RegisterID reg) {
98 static const char* const names[] = {"%rax",
99 "%rcx",
100 "%rdx",
101 "%rbx",
102 "%rsp",
103 "%rbp",
104 "%rsi",
105 "%rdi"
106 #ifdef JS_CODEGEN_X64
107 ,
108 "%r8",
109 "%r9",
110 "%r10",
111 "%r11",
112 "%r12",
113 "%r13",
114 "%r14",
115 "%r15"
116 #endif
117 };
118 MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
119 return names[reg];
120 }
121 #endif
122
GPReg32Name(RegisterID reg)123 inline const char* GPReg32Name(RegisterID reg) {
124 static const char* const names[] = {"%eax",
125 "%ecx",
126 "%edx",
127 "%ebx",
128 "%esp",
129 "%ebp",
130 "%esi",
131 "%edi"
132 #ifdef JS_CODEGEN_X64
133 ,
134 "%r8d",
135 "%r9d",
136 "%r10d",
137 "%r11d",
138 "%r12d",
139 "%r13d",
140 "%r14d",
141 "%r15d"
142 #endif
143 };
144 MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
145 return names[reg];
146 }
147
GPReg16Name(RegisterID reg)148 inline const char* GPReg16Name(RegisterID reg) {
149 static const char* const names[] = {"%ax",
150 "%cx",
151 "%dx",
152 "%bx",
153 "%sp",
154 "%bp",
155 "%si",
156 "%di"
157 #ifdef JS_CODEGEN_X64
158 ,
159 "%r8w",
160 "%r9w",
161 "%r10w",
162 "%r11w",
163 "%r12w",
164 "%r13w",
165 "%r14w",
166 "%r15w"
167 #endif
168 };
169 MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
170 return names[reg];
171 }
172
GPReg8Name(RegisterID reg)173 inline const char* GPReg8Name(RegisterID reg) {
174 static const char* const names[] = {"%al",
175 "%cl",
176 "%dl",
177 "%bl"
178 #ifdef JS_CODEGEN_X64
179 ,
180 "%spl",
181 "%bpl",
182 "%sil",
183 "%dil",
184 "%r8b",
185 "%r9b",
186 "%r10b",
187 "%r11b",
188 "%r12b",
189 "%r13b",
190 "%r14b",
191 "%r15b"
192 #endif
193 };
194 MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
195 return names[reg];
196 }
197
GPRegName(RegisterID reg)198 inline const char* GPRegName(RegisterID reg) {
199 #ifdef JS_CODEGEN_X64
200 return GPReg64Name(reg);
201 #else
202 return GPReg32Name(reg);
203 #endif
204 }
205
HasSubregL(RegisterID reg)206 inline bool HasSubregL(RegisterID reg) {
207 #ifdef JS_CODEGEN_X64
208 // In 64-bit mode, all registers have an 8-bit lo subreg.
209 return true;
210 #else
211 // In 32-bit mode, only the first four registers do.
212 return reg <= rbx;
213 #endif
214 }
215
HasSubregH(RegisterID reg)216 inline bool HasSubregH(RegisterID reg) {
217 // The first four registers always have h registers. However, note that
218 // on x64, h registers may not be used in instructions using REX
219 // prefixes. Also note that this may depend on what other registers are
220 // used!
221 return reg <= rbx;
222 }
223
GetSubregH(RegisterID reg)224 inline HRegisterID GetSubregH(RegisterID reg) {
225 MOZ_ASSERT(HasSubregH(reg));
226 return HRegisterID(reg + 4);
227 }
228
HRegName8(HRegisterID reg)229 inline const char* HRegName8(HRegisterID reg) {
230 static const char* const names[] = {"%ah", "%ch", "%dh", "%bh"};
231 size_t index = reg - GetSubregH(rax);
232 MOZ_ASSERT(index < mozilla::ArrayLength(names));
233 return names[index];
234 }
235
236 enum Condition {
237 ConditionO,
238 ConditionNO,
239 ConditionB,
240 ConditionAE,
241 ConditionE,
242 ConditionNE,
243 ConditionBE,
244 ConditionA,
245 ConditionS,
246 ConditionNS,
247 ConditionP,
248 ConditionNP,
249 ConditionL,
250 ConditionGE,
251 ConditionLE,
252 ConditionG,
253
254 ConditionC = ConditionB,
255 ConditionNC = ConditionAE
256 };
257
CCName(Condition cc)258 inline const char* CCName(Condition cc) {
259 static const char* const names[] = {"o ", "no", "b ", "ae", "e ", "ne",
260 "be", "a ", "s ", "ns", "p ", "np",
261 "l ", "ge", "le", "g "};
262 MOZ_ASSERT(size_t(cc) < mozilla::ArrayLength(names));
263 return names[cc];
264 }
265
266 // Conditions for CMP instructions (CMPSS, CMPSD, CMPPS, CMPPD, etc).
267 enum ConditionCmp {
268 ConditionCmp_EQ = 0x0,
269 ConditionCmp_LT = 0x1,
270 ConditionCmp_LE = 0x2,
271 ConditionCmp_UNORD = 0x3,
272 ConditionCmp_NEQ = 0x4,
273 ConditionCmp_NLT = 0x5,
274 ConditionCmp_NLE = 0x6,
275 ConditionCmp_ORD = 0x7,
276 };
277
278 // Rounding modes for ROUNDSD.
279 enum RoundingMode {
280 RoundToNearest = 0x0,
281 RoundDown = 0x1,
282 RoundUp = 0x2,
283 RoundToZero = 0x3
284 };
285
286 // Test whether the given address will fit in an address immediate field.
287 // This is always true on x86, but on x64 it's only true for addreses which
288 // fit in the 32-bit immediate field.
IsAddressImmediate(const void * address)289 inline bool IsAddressImmediate(const void* address) {
290 intptr_t value = reinterpret_cast<intptr_t>(address);
291 int32_t immediate = static_cast<int32_t>(value);
292 return value == immediate;
293 }
294
295 // Convert the given address to a 32-bit immediate field value. This is a
296 // no-op on x86, but on x64 it asserts that the address is actually a valid
297 // address immediate.
AddressImmediate(const void * address)298 inline int32_t AddressImmediate(const void* address) {
299 MOZ_ASSERT(IsAddressImmediate(address));
300 return static_cast<int32_t>(reinterpret_cast<intptr_t>(address));
301 }
302
303 } // namespace X86Encoding
304
305 } // namespace jit
306 } // namespace js
307
308 #endif /* jit_x86_shared_Constants_x86_shared_h */
309