1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/jit/arm/LIR-arm.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,475 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#ifndef jit_arm_LIR_arm_h 1.11 +#define jit_arm_LIR_arm_h 1.12 + 1.13 +namespace js { 1.14 +namespace jit { 1.15 + 1.16 +class LBox : public LInstructionHelper<2, 1, 0> 1.17 +{ 1.18 + MIRType type_; 1.19 + 1.20 + public: 1.21 + LIR_HEADER(Box); 1.22 + 1.23 + LBox(const LAllocation &in_payload, MIRType type) 1.24 + : type_(type) 1.25 + { 1.26 + setOperand(0, in_payload); 1.27 + } 1.28 + 1.29 + MIRType type() const { 1.30 + return type_; 1.31 + } 1.32 + const char *extraName() const { 1.33 + return StringFromMIRType(type_); 1.34 + } 1.35 +}; 1.36 + 1.37 +class LBoxFloatingPoint : public LInstructionHelper<2, 1, 1> 1.38 +{ 1.39 + MIRType type_; 1.40 + 1.41 + public: 1.42 + LIR_HEADER(BoxFloatingPoint); 1.43 + 1.44 + LBoxFloatingPoint(const LAllocation &in, const LDefinition &temp, MIRType type) 1.45 + : type_(type) 1.46 + { 1.47 + setOperand(0, in); 1.48 + setTemp(0, temp); 1.49 + } 1.50 + 1.51 + MIRType type() const { 1.52 + return type_; 1.53 + } 1.54 + const char *extraName() const { 1.55 + return StringFromMIRType(type_); 1.56 + } 1.57 +}; 1.58 + 1.59 +class LUnbox : public LInstructionHelper<1, 2, 0> 1.60 +{ 1.61 + public: 1.62 + LIR_HEADER(Unbox); 1.63 + 1.64 + MUnbox *mir() const { 1.65 + return mir_->toUnbox(); 1.66 + } 1.67 + const LAllocation *payload() { 1.68 + return getOperand(0); 1.69 + } 1.70 + const LAllocation *type() { 1.71 + return getOperand(1); 1.72 + } 1.73 + const char *extraName() const { 1.74 + return StringFromMIRType(mir()->type()); 1.75 + } 1.76 +}; 1.77 + 1.78 +class LUnboxFloatingPoint : public LInstructionHelper<1, 2, 0> 1.79 +{ 1.80 + MIRType type_; 1.81 + 1.82 + public: 1.83 + LIR_HEADER(UnboxFloatingPoint); 1.84 + 1.85 + static const size_t Input = 0; 1.86 + 1.87 + LUnboxFloatingPoint(MIRType type) 1.88 + : type_(type) 1.89 + { } 1.90 + 1.91 + MUnbox *mir() const { 1.92 + return mir_->toUnbox(); 1.93 + } 1.94 + 1.95 + MIRType type() const { 1.96 + return type_; 1.97 + } 1.98 + const char *extraName() const { 1.99 + return StringFromMIRType(type_); 1.100 + } 1.101 +}; 1.102 + 1.103 +// Convert a 32-bit unsigned integer to a double. 1.104 +class LAsmJSUInt32ToDouble : public LInstructionHelper<1, 1, 0> 1.105 +{ 1.106 + public: 1.107 + LIR_HEADER(AsmJSUInt32ToDouble) 1.108 + 1.109 + LAsmJSUInt32ToDouble(const LAllocation &input) { 1.110 + setOperand(0, input); 1.111 + } 1.112 +}; 1.113 + 1.114 +// Convert a 32-bit unsigned integer to a float32. 1.115 +class LAsmJSUInt32ToFloat32 : public LInstructionHelper<1, 1, 0> 1.116 +{ 1.117 + public: 1.118 + LIR_HEADER(AsmJSUInt32ToFloat32) 1.119 + 1.120 + LAsmJSUInt32ToFloat32(const LAllocation &input) { 1.121 + setOperand(0, input); 1.122 + } 1.123 +}; 1.124 + 1.125 +class LDivI : public LBinaryMath<1> 1.126 +{ 1.127 + public: 1.128 + LIR_HEADER(DivI); 1.129 + 1.130 + LDivI(const LAllocation &lhs, const LAllocation &rhs, 1.131 + const LDefinition &temp) { 1.132 + setOperand(0, lhs); 1.133 + setOperand(1, rhs); 1.134 + setTemp(0, temp); 1.135 + } 1.136 + 1.137 + MDiv *mir() const { 1.138 + return mir_->toDiv(); 1.139 + } 1.140 +}; 1.141 + 1.142 +// LSoftDivI is a software divide for ARM cores that don't support a hardware 1.143 +// divide instruction. 1.144 +// 1.145 +// It is implemented as a proper C function so it trashes r0, r1, r2 and r3. 1.146 +// The call also trashes lr, and has the ability to trash ip. The function also 1.147 +// takes two arguments (dividend in r0, divisor in r1). The LInstruction gets 1.148 +// encoded such that the divisor and dividend are passed in their apropriate 1.149 +// registers and end their life at the start of the instruction by the use of 1.150 +// useFixedAtStart. The result is returned in r0 and the other three registers 1.151 +// that can be trashed are marked as temps. For the time being, the link 1.152 +// register is not marked as trashed because we never allocate to the link 1.153 +// register. The FP registers are not trashed. 1.154 +class LSoftDivI : public LBinaryMath<3> 1.155 +{ 1.156 + public: 1.157 + LIR_HEADER(SoftDivI); 1.158 + 1.159 + LSoftDivI(const LAllocation &lhs, const LAllocation &rhs, 1.160 + const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3) { 1.161 + setOperand(0, lhs); 1.162 + setOperand(1, rhs); 1.163 + setTemp(0, temp1); 1.164 + setTemp(1, temp2); 1.165 + setTemp(2, temp3); 1.166 + } 1.167 + 1.168 + MDiv *mir() const { 1.169 + return mir_->toDiv(); 1.170 + } 1.171 +}; 1.172 + 1.173 +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> 1.174 +{ 1.175 + const int32_t shift_; 1.176 + 1.177 + public: 1.178 + LIR_HEADER(DivPowTwoI) 1.179 + 1.180 + LDivPowTwoI(const LAllocation &lhs, int32_t shift) 1.181 + : shift_(shift) 1.182 + { 1.183 + setOperand(0, lhs); 1.184 + } 1.185 + 1.186 + const LAllocation *numerator() { 1.187 + return getOperand(0); 1.188 + } 1.189 + 1.190 + int32_t shift() { 1.191 + return shift_; 1.192 + } 1.193 + 1.194 + MDiv *mir() const { 1.195 + return mir_->toDiv(); 1.196 + } 1.197 +}; 1.198 + 1.199 +class LModI : public LBinaryMath<1> 1.200 +{ 1.201 + public: 1.202 + LIR_HEADER(ModI); 1.203 + 1.204 + LModI(const LAllocation &lhs, const LAllocation &rhs, 1.205 + const LDefinition &callTemp) 1.206 + { 1.207 + setOperand(0, lhs); 1.208 + setOperand(1, rhs); 1.209 + setTemp(0, callTemp); 1.210 + } 1.211 + 1.212 + const LDefinition *callTemp() { 1.213 + return getTemp(0); 1.214 + } 1.215 + 1.216 + MMod *mir() const { 1.217 + return mir_->toMod(); 1.218 + } 1.219 +}; 1.220 + 1.221 +class LSoftModI : public LBinaryMath<4> 1.222 +{ 1.223 + public: 1.224 + LIR_HEADER(SoftModI); 1.225 + 1.226 + LSoftModI(const LAllocation &lhs, const LAllocation &rhs, 1.227 + const LDefinition &temp1, const LDefinition &temp2, const LDefinition &temp3, 1.228 + const LDefinition &callTemp) 1.229 + { 1.230 + setOperand(0, lhs); 1.231 + setOperand(1, rhs); 1.232 + setTemp(0, temp1); 1.233 + setTemp(1, temp2); 1.234 + setTemp(2, temp3); 1.235 + setTemp(3, callTemp); 1.236 + } 1.237 + 1.238 + const LDefinition *callTemp() { 1.239 + return getTemp(3); 1.240 + } 1.241 + 1.242 + MMod *mir() const { 1.243 + return mir_->toMod(); 1.244 + } 1.245 +}; 1.246 + 1.247 +class LModPowTwoI : public LInstructionHelper<1, 1, 0> 1.248 +{ 1.249 + const int32_t shift_; 1.250 + 1.251 + public: 1.252 + LIR_HEADER(ModPowTwoI); 1.253 + int32_t shift() 1.254 + { 1.255 + return shift_; 1.256 + } 1.257 + 1.258 + LModPowTwoI(const LAllocation &lhs, int32_t shift) 1.259 + : shift_(shift) 1.260 + { 1.261 + setOperand(0, lhs); 1.262 + } 1.263 + 1.264 + MMod *mir() const { 1.265 + return mir_->toMod(); 1.266 + } 1.267 +}; 1.268 + 1.269 +class LModMaskI : public LInstructionHelper<1, 1, 2> 1.270 +{ 1.271 + const int32_t shift_; 1.272 + 1.273 + public: 1.274 + LIR_HEADER(ModMaskI); 1.275 + 1.276 + LModMaskI(const LAllocation &lhs, const LDefinition &temp1, const LDefinition &temp2, 1.277 + int32_t shift) 1.278 + : shift_(shift) 1.279 + { 1.280 + setOperand(0, lhs); 1.281 + setTemp(0, temp1); 1.282 + setTemp(1, temp2); 1.283 + } 1.284 + 1.285 + int32_t shift() const { 1.286 + return shift_; 1.287 + } 1.288 + 1.289 + MMod *mir() const { 1.290 + return mir_->toMod(); 1.291 + } 1.292 +}; 1.293 + 1.294 +class LPowHalfD : public LInstructionHelper<1, 1, 0> 1.295 +{ 1.296 + public: 1.297 + LIR_HEADER(PowHalfD); 1.298 + LPowHalfD(const LAllocation &input) { 1.299 + setOperand(0, input); 1.300 + } 1.301 + 1.302 + const LAllocation *input() { 1.303 + return getOperand(0); 1.304 + } 1.305 + const LDefinition *output() { 1.306 + return getDef(0); 1.307 + } 1.308 +}; 1.309 + 1.310 +// Takes a tableswitch with an integer to decide 1.311 +class LTableSwitch : public LInstructionHelper<0, 1, 1> 1.312 +{ 1.313 + public: 1.314 + LIR_HEADER(TableSwitch); 1.315 + 1.316 + LTableSwitch(const LAllocation &in, const LDefinition &inputCopy, MTableSwitch *ins) { 1.317 + setOperand(0, in); 1.318 + setTemp(0, inputCopy); 1.319 + setMir(ins); 1.320 + } 1.321 + 1.322 + MTableSwitch *mir() const { 1.323 + return mir_->toTableSwitch(); 1.324 + } 1.325 + 1.326 + const LAllocation *index() { 1.327 + return getOperand(0); 1.328 + } 1.329 + const LDefinition *tempInt() { 1.330 + return getTemp(0); 1.331 + } 1.332 + // This is added to share the same CodeGenerator prefixes. 1.333 + const LDefinition *tempPointer() { 1.334 + return nullptr; 1.335 + } 1.336 +}; 1.337 + 1.338 +// Takes a tableswitch with an integer to decide 1.339 +class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2> 1.340 +{ 1.341 + public: 1.342 + LIR_HEADER(TableSwitchV); 1.343 + 1.344 + LTableSwitchV(const LDefinition &inputCopy, const LDefinition &floatCopy, 1.345 + MTableSwitch *ins) 1.346 + { 1.347 + setTemp(0, inputCopy); 1.348 + setTemp(1, floatCopy); 1.349 + setMir(ins); 1.350 + } 1.351 + 1.352 + MTableSwitch *mir() const { 1.353 + return mir_->toTableSwitch(); 1.354 + } 1.355 + 1.356 + static const size_t InputValue = 0; 1.357 + 1.358 + const LDefinition *tempInt() { 1.359 + return getTemp(0); 1.360 + } 1.361 + const LDefinition *tempFloat() { 1.362 + return getTemp(1); 1.363 + } 1.364 + const LDefinition *tempPointer() { 1.365 + return nullptr; 1.366 + } 1.367 +}; 1.368 + 1.369 +class LGuardShape : public LInstructionHelper<0, 1, 1> 1.370 +{ 1.371 + public: 1.372 + LIR_HEADER(GuardShape); 1.373 + 1.374 + LGuardShape(const LAllocation &in, const LDefinition &temp) { 1.375 + setOperand(0, in); 1.376 + setTemp(0, temp); 1.377 + } 1.378 + const MGuardShape *mir() const { 1.379 + return mir_->toGuardShape(); 1.380 + } 1.381 + const LDefinition *tempInt() { 1.382 + return getTemp(0); 1.383 + } 1.384 +}; 1.385 + 1.386 +class LGuardObjectType : public LInstructionHelper<0, 1, 1> 1.387 +{ 1.388 + public: 1.389 + LIR_HEADER(GuardObjectType); 1.390 + 1.391 + LGuardObjectType(const LAllocation &in, const LDefinition &temp) { 1.392 + setOperand(0, in); 1.393 + setTemp(0, temp); 1.394 + } 1.395 + const MGuardObjectType *mir() const { 1.396 + return mir_->toGuardObjectType(); 1.397 + } 1.398 + const LDefinition *tempInt() { 1.399 + return getTemp(0); 1.400 + } 1.401 +}; 1.402 + 1.403 +class LInterruptCheck : public LInstructionHelper<0, 0, 0> 1.404 +{ 1.405 + public: 1.406 + LIR_HEADER(InterruptCheck); 1.407 +}; 1.408 + 1.409 +class LMulI : public LBinaryMath<0> 1.410 +{ 1.411 + public: 1.412 + LIR_HEADER(MulI); 1.413 + 1.414 + MMul *mir() { 1.415 + return mir_->toMul(); 1.416 + } 1.417 +}; 1.418 + 1.419 +class LUDiv : public LBinaryMath<0> 1.420 +{ 1.421 + public: 1.422 + LIR_HEADER(UDiv); 1.423 + 1.424 + MDiv *mir() { 1.425 + return mir_->toDiv(); 1.426 + } 1.427 +}; 1.428 + 1.429 +class LUMod : public LBinaryMath<0> 1.430 +{ 1.431 + public: 1.432 + LIR_HEADER(UMod); 1.433 + 1.434 + MMod *mir() { 1.435 + return mir_->toMod(); 1.436 + } 1.437 +}; 1.438 + 1.439 +// This class performs a simple x86 'div', yielding either a quotient or remainder depending on 1.440 +// whether this instruction is defined to output eax (quotient) or edx (remainder). 1.441 +class LSoftUDivOrMod : public LBinaryMath<3> 1.442 +{ 1.443 + public: 1.444 + LIR_HEADER(SoftUDivOrMod); 1.445 + 1.446 + LSoftUDivOrMod(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp1, 1.447 + const LDefinition &temp2, const LDefinition &temp3) { 1.448 + setOperand(0, lhs); 1.449 + setOperand(1, rhs); 1.450 + setTemp(0, temp1); 1.451 + setTemp(1, temp2); 1.452 + setTemp(2, temp3); 1.453 + } 1.454 +}; 1.455 + 1.456 +class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 1> 1.457 +{ 1.458 + public: 1.459 + LIR_HEADER(AsmJSLoadFuncPtr); 1.460 + LAsmJSLoadFuncPtr(const LAllocation &index, const LDefinition &temp) { 1.461 + setOperand(0, index); 1.462 + setTemp(0, temp); 1.463 + } 1.464 + const MAsmJSLoadFuncPtr *mir() const { 1.465 + return mir_->toAsmJSLoadFuncPtr(); 1.466 + } 1.467 + const LAllocation *index() { 1.468 + return getOperand(0); 1.469 + } 1.470 + const LDefinition *temp() { 1.471 + return getTemp(0); 1.472 + } 1.473 +}; 1.474 + 1.475 +} // namespace jit 1.476 +} // namespace js 1.477 + 1.478 +#endif /* jit_arm_LIR_arm_h */