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