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