Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * vim: set ts=8 sts=4 et sw=4 tw=99: |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #ifndef jit_mips_Architecture_mips_h |
michael@0 | 8 | #define jit_mips_Architecture_mips_h |
michael@0 | 9 | |
michael@0 | 10 | #include <limits.h> |
michael@0 | 11 | #include <stdint.h> |
michael@0 | 12 | |
michael@0 | 13 | #include "js/Utility.h" |
michael@0 | 14 | |
michael@0 | 15 | // gcc appears to use _mips_hard_float to denote |
michael@0 | 16 | // that the target is a hard-float target. |
michael@0 | 17 | #ifdef _mips_hard_float |
michael@0 | 18 | #define JS_CODEGEN_MIPS_HARDFP |
michael@0 | 19 | #endif |
michael@0 | 20 | namespace js { |
michael@0 | 21 | namespace jit { |
michael@0 | 22 | |
michael@0 | 23 | // Shadow stack space is not required on MIPS. |
michael@0 | 24 | static const uint32_t ShadowStackSpace = 0; |
michael@0 | 25 | |
michael@0 | 26 | // These offsets are specific to nunboxing, and capture offsets into the |
michael@0 | 27 | // components of a js::Value. |
michael@0 | 28 | // Size of MIPS32 general purpose registers is 32 bits. |
michael@0 | 29 | static const int32_t NUNBOX32_TYPE_OFFSET = 4; |
michael@0 | 30 | static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0; |
michael@0 | 31 | |
michael@0 | 32 | // Size of each bailout table entry. |
michael@0 | 33 | // For MIPS this is 2 instructions relative call. |
michael@0 | 34 | static const uint32_t BAILOUT_TABLE_ENTRY_SIZE = 2 * sizeof(void *); |
michael@0 | 35 | |
michael@0 | 36 | class Registers |
michael@0 | 37 | { |
michael@0 | 38 | public: |
michael@0 | 39 | enum RegisterID { |
michael@0 | 40 | r0 = 0, |
michael@0 | 41 | r1, |
michael@0 | 42 | r2, |
michael@0 | 43 | r3, |
michael@0 | 44 | r4, |
michael@0 | 45 | r5, |
michael@0 | 46 | r6, |
michael@0 | 47 | r7, |
michael@0 | 48 | r8, |
michael@0 | 49 | r9, |
michael@0 | 50 | r10, |
michael@0 | 51 | r11, |
michael@0 | 52 | r12, |
michael@0 | 53 | r13, |
michael@0 | 54 | r14, |
michael@0 | 55 | r15, |
michael@0 | 56 | r16, |
michael@0 | 57 | r17, |
michael@0 | 58 | r18, |
michael@0 | 59 | r19, |
michael@0 | 60 | r20, |
michael@0 | 61 | r21, |
michael@0 | 62 | r22, |
michael@0 | 63 | r23, |
michael@0 | 64 | r24, |
michael@0 | 65 | r25, |
michael@0 | 66 | r26, |
michael@0 | 67 | r27, |
michael@0 | 68 | r28, |
michael@0 | 69 | r29, |
michael@0 | 70 | r30, |
michael@0 | 71 | r31, |
michael@0 | 72 | zero = r0, |
michael@0 | 73 | at = r1, |
michael@0 | 74 | v0 = r2, |
michael@0 | 75 | v1 = r3, |
michael@0 | 76 | a0 = r4, |
michael@0 | 77 | a1 = r5, |
michael@0 | 78 | a2 = r6, |
michael@0 | 79 | a3 = r7, |
michael@0 | 80 | t0 = r8, |
michael@0 | 81 | t1 = r9, |
michael@0 | 82 | t2 = r10, |
michael@0 | 83 | t3 = r11, |
michael@0 | 84 | t4 = r12, |
michael@0 | 85 | t5 = r13, |
michael@0 | 86 | t6 = r14, |
michael@0 | 87 | t7 = r15, |
michael@0 | 88 | s0 = r16, |
michael@0 | 89 | s1 = r17, |
michael@0 | 90 | s2 = r18, |
michael@0 | 91 | s3 = r19, |
michael@0 | 92 | s4 = r20, |
michael@0 | 93 | s5 = r21, |
michael@0 | 94 | s6 = r22, |
michael@0 | 95 | s7 = r23, |
michael@0 | 96 | t8 = r24, |
michael@0 | 97 | t9 = r25, |
michael@0 | 98 | k0 = r26, |
michael@0 | 99 | k1 = r27, |
michael@0 | 100 | gp = r28, |
michael@0 | 101 | sp = r29, |
michael@0 | 102 | fp = r30, |
michael@0 | 103 | ra = r31, |
michael@0 | 104 | invalid_reg |
michael@0 | 105 | }; |
michael@0 | 106 | typedef RegisterID Code; |
michael@0 | 107 | |
michael@0 | 108 | static const char *GetName(Code code) { |
michael@0 | 109 | static const char * const Names[] = { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", |
michael@0 | 110 | "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", |
michael@0 | 111 | "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
michael@0 | 112 | "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"}; |
michael@0 | 113 | return Names[code]; |
michael@0 | 114 | } |
michael@0 | 115 | static const char *GetName(uint32_t i) { |
michael@0 | 116 | JS_ASSERT(i < Total); |
michael@0 | 117 | return GetName(Code(i)); |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | static Code FromName(const char *name); |
michael@0 | 121 | |
michael@0 | 122 | static const Code StackPointer = sp; |
michael@0 | 123 | static const Code Invalid = invalid_reg; |
michael@0 | 124 | |
michael@0 | 125 | static const uint32_t Total = 32; |
michael@0 | 126 | static const uint32_t Allocatable = 14; |
michael@0 | 127 | |
michael@0 | 128 | static const uint32_t AllMask = 0xffffffff; |
michael@0 | 129 | static const uint32_t ArgRegMask = (1 << a0) | (1 << a1) | (1 << a2) | (1 << a3); |
michael@0 | 130 | |
michael@0 | 131 | static const uint32_t VolatileMask = |
michael@0 | 132 | (1 << Registers::v0) | |
michael@0 | 133 | (1 << Registers::v1) | |
michael@0 | 134 | (1 << Registers::a0) | |
michael@0 | 135 | (1 << Registers::a1) | |
michael@0 | 136 | (1 << Registers::a2) | |
michael@0 | 137 | (1 << Registers::a3) | |
michael@0 | 138 | (1 << Registers::t0) | |
michael@0 | 139 | (1 << Registers::t1) | |
michael@0 | 140 | (1 << Registers::t2) | |
michael@0 | 141 | (1 << Registers::t3) | |
michael@0 | 142 | (1 << Registers::t4) | |
michael@0 | 143 | (1 << Registers::t5) | |
michael@0 | 144 | (1 << Registers::t6) | |
michael@0 | 145 | (1 << Registers::t7); |
michael@0 | 146 | |
michael@0 | 147 | static const uint32_t NonVolatileMask = |
michael@0 | 148 | (1 << Registers::s0) | |
michael@0 | 149 | (1 << Registers::s1) | |
michael@0 | 150 | (1 << Registers::s2) | |
michael@0 | 151 | (1 << Registers::s3) | |
michael@0 | 152 | (1 << Registers::s4) | |
michael@0 | 153 | (1 << Registers::s5) | |
michael@0 | 154 | (1 << Registers::s6) | |
michael@0 | 155 | (1 << Registers::s7); |
michael@0 | 156 | |
michael@0 | 157 | static const uint32_t WrapperMask = |
michael@0 | 158 | VolatileMask | // = arguments |
michael@0 | 159 | (1 << Registers::t0) | // = outReg |
michael@0 | 160 | (1 << Registers::t1); // = argBase |
michael@0 | 161 | |
michael@0 | 162 | static const uint32_t NonAllocatableMask = |
michael@0 | 163 | (1 << Registers::zero) | |
michael@0 | 164 | (1 << Registers::at) | // at = scratch |
michael@0 | 165 | (1 << Registers::t8) | // t8 = scratch |
michael@0 | 166 | (1 << Registers::t9) | // t9 = scratch |
michael@0 | 167 | (1 << Registers::k0) | |
michael@0 | 168 | (1 << Registers::k1) | |
michael@0 | 169 | (1 << Registers::gp) | |
michael@0 | 170 | (1 << Registers::sp) | |
michael@0 | 171 | (1 << Registers::fp) | |
michael@0 | 172 | (1 << Registers::ra); |
michael@0 | 173 | |
michael@0 | 174 | // Registers that can be allocated without being saved, generally. |
michael@0 | 175 | static const uint32_t TempMask = VolatileMask & ~NonAllocatableMask; |
michael@0 | 176 | |
michael@0 | 177 | // Registers returned from a JS -> JS call. |
michael@0 | 178 | static const uint32_t JSCallMask = |
michael@0 | 179 | (1 << Registers::v0) | |
michael@0 | 180 | (1 << Registers::v1); |
michael@0 | 181 | |
michael@0 | 182 | // Registers returned from a JS -> C call. |
michael@0 | 183 | static const uint32_t CallMask = |
michael@0 | 184 | (1 << Registers::v0) | |
michael@0 | 185 | (1 << Registers::v1); // used for double-size returns |
michael@0 | 186 | |
michael@0 | 187 | static const uint32_t AllocatableMask = AllMask & ~NonAllocatableMask; |
michael@0 | 188 | }; |
michael@0 | 189 | |
michael@0 | 190 | // Smallest integer type that can hold a register bitmask. |
michael@0 | 191 | typedef uint32_t PackedRegisterMask; |
michael@0 | 192 | |
michael@0 | 193 | |
michael@0 | 194 | // MIPS32 can have two types of floating-point coprocessors: |
michael@0 | 195 | // - 32 bit floating-point coprocessor - In this case, there are 32 single |
michael@0 | 196 | // precision registers and pairs of even and odd float registers are used as |
michael@0 | 197 | // double precision registers. Example: f0 (double) is composed of |
michael@0 | 198 | // f0 and f1 (single). |
michael@0 | 199 | // - 64 bit floating-point coprocessor - In this case, there are 32 double |
michael@0 | 200 | // precision register which can also be used as single precision registers. |
michael@0 | 201 | |
michael@0 | 202 | // When using O32 ABI, floating-point coprocessor is 32 bit |
michael@0 | 203 | // When using N32 ABI, floating-point coprocessor is 64 bit. |
michael@0 | 204 | class FloatRegisters |
michael@0 | 205 | { |
michael@0 | 206 | public: |
michael@0 | 207 | enum FPRegisterID { |
michael@0 | 208 | f0 = 0, |
michael@0 | 209 | f1, |
michael@0 | 210 | f2, |
michael@0 | 211 | f3, |
michael@0 | 212 | f4, |
michael@0 | 213 | f5, |
michael@0 | 214 | f6, |
michael@0 | 215 | f7, |
michael@0 | 216 | f8, |
michael@0 | 217 | f9, |
michael@0 | 218 | f10, |
michael@0 | 219 | f11, |
michael@0 | 220 | f12, |
michael@0 | 221 | f13, |
michael@0 | 222 | f14, |
michael@0 | 223 | f15, |
michael@0 | 224 | f16, |
michael@0 | 225 | f17, |
michael@0 | 226 | f18, |
michael@0 | 227 | f19, |
michael@0 | 228 | f20, |
michael@0 | 229 | f21, |
michael@0 | 230 | f22, |
michael@0 | 231 | f23, |
michael@0 | 232 | f24, |
michael@0 | 233 | f25, |
michael@0 | 234 | f26, |
michael@0 | 235 | f27, |
michael@0 | 236 | f28, |
michael@0 | 237 | f29, |
michael@0 | 238 | f30, |
michael@0 | 239 | f31, |
michael@0 | 240 | invalid_freg |
michael@0 | 241 | }; |
michael@0 | 242 | typedef FPRegisterID Code; |
michael@0 | 243 | |
michael@0 | 244 | static const char *GetName(Code code) { |
michael@0 | 245 | static const char * const Names[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
michael@0 | 246 | "f8", "f9", "f10", "f11", "f12", "f13", |
michael@0 | 247 | "f14", "f15", "f16", "f17", "f18", "f19", |
michael@0 | 248 | "f20", "f21", "f22", "f23", "f24", "f25", |
michael@0 | 249 | "f26", "f27", "f28", "f29", "f30", "f31"}; |
michael@0 | 250 | return Names[code]; |
michael@0 | 251 | } |
michael@0 | 252 | static const char *GetName(uint32_t i) { |
michael@0 | 253 | JS_ASSERT(i < Total); |
michael@0 | 254 | return GetName(Code(i)); |
michael@0 | 255 | } |
michael@0 | 256 | |
michael@0 | 257 | static Code FromName(const char *name); |
michael@0 | 258 | |
michael@0 | 259 | static const Code Invalid = invalid_freg; |
michael@0 | 260 | |
michael@0 | 261 | static const uint32_t Total = 32; |
michael@0 | 262 | // :TODO: (Bug 972836) // Fix this once odd regs can be used as float32 |
michael@0 | 263 | // only. For now we don't allocate odd regs for O32 ABI. |
michael@0 | 264 | static const uint32_t Allocatable = 14; |
michael@0 | 265 | |
michael@0 | 266 | static const uint32_t AllMask = 0xffffffff; |
michael@0 | 267 | |
michael@0 | 268 | static const uint32_t VolatileMask = |
michael@0 | 269 | (1 << FloatRegisters::f0) | |
michael@0 | 270 | (1 << FloatRegisters::f2) | |
michael@0 | 271 | (1 << FloatRegisters::f4) | |
michael@0 | 272 | (1 << FloatRegisters::f6) | |
michael@0 | 273 | (1 << FloatRegisters::f8) | |
michael@0 | 274 | (1 << FloatRegisters::f10) | |
michael@0 | 275 | (1 << FloatRegisters::f12) | |
michael@0 | 276 | (1 << FloatRegisters::f14) | |
michael@0 | 277 | (1 << FloatRegisters::f16) | |
michael@0 | 278 | (1 << FloatRegisters::f18); |
michael@0 | 279 | static const uint32_t NonVolatileMask = |
michael@0 | 280 | (1 << FloatRegisters::f20) | |
michael@0 | 281 | (1 << FloatRegisters::f22) | |
michael@0 | 282 | (1 << FloatRegisters::f24) | |
michael@0 | 283 | (1 << FloatRegisters::f26) | |
michael@0 | 284 | (1 << FloatRegisters::f28) | |
michael@0 | 285 | (1 << FloatRegisters::f30); |
michael@0 | 286 | |
michael@0 | 287 | static const uint32_t WrapperMask = VolatileMask; |
michael@0 | 288 | |
michael@0 | 289 | // :TODO: (Bug 972836) // Fix this once odd regs can be used as float32 |
michael@0 | 290 | // only. For now we don't allocate odd regs for O32 ABI. |
michael@0 | 291 | static const uint32_t NonAllocatableMask = |
michael@0 | 292 | (1 << FloatRegisters::f1) | |
michael@0 | 293 | (1 << FloatRegisters::f3) | |
michael@0 | 294 | (1 << FloatRegisters::f5) | |
michael@0 | 295 | (1 << FloatRegisters::f7) | |
michael@0 | 296 | (1 << FloatRegisters::f9) | |
michael@0 | 297 | (1 << FloatRegisters::f11) | |
michael@0 | 298 | (1 << FloatRegisters::f13) | |
michael@0 | 299 | (1 << FloatRegisters::f15) | |
michael@0 | 300 | (1 << FloatRegisters::f17) | |
michael@0 | 301 | (1 << FloatRegisters::f19) | |
michael@0 | 302 | (1 << FloatRegisters::f21) | |
michael@0 | 303 | (1 << FloatRegisters::f23) | |
michael@0 | 304 | (1 << FloatRegisters::f25) | |
michael@0 | 305 | (1 << FloatRegisters::f27) | |
michael@0 | 306 | (1 << FloatRegisters::f29) | |
michael@0 | 307 | (1 << FloatRegisters::f31) | |
michael@0 | 308 | // f18 and f16 are MIPS scratch float registers. |
michael@0 | 309 | (1 << FloatRegisters::f16) | |
michael@0 | 310 | (1 << FloatRegisters::f18); |
michael@0 | 311 | |
michael@0 | 312 | // Registers that can be allocated without being saved, generally. |
michael@0 | 313 | static const uint32_t TempMask = VolatileMask & ~NonAllocatableMask; |
michael@0 | 314 | |
michael@0 | 315 | static const uint32_t AllocatableMask = AllMask & ~NonAllocatableMask; |
michael@0 | 316 | }; |
michael@0 | 317 | |
michael@0 | 318 | uint32_t GetMIPSFlags(); |
michael@0 | 319 | bool hasFPU(); |
michael@0 | 320 | |
michael@0 | 321 | } // namespace jit |
michael@0 | 322 | } // namespace js |
michael@0 | 323 | |
michael@0 | 324 | #endif /* jit_mips_Architecture_mips_h */ |