js/src/jit/mips/Lowering-mips.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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 #include "mozilla/MathAlgorithms.h"
michael@0 8
michael@0 9
michael@0 10 #include "jit/Lowering.h"
michael@0 11 #include "jit/mips/Assembler-mips.h"
michael@0 12 #include "jit/MIR.h"
michael@0 13
michael@0 14 #include "jit/shared/Lowering-shared-inl.h"
michael@0 15
michael@0 16 using namespace js;
michael@0 17 using namespace js::jit;
michael@0 18
michael@0 19 using mozilla::FloorLog2;
michael@0 20
michael@0 21 bool
michael@0 22 LIRGeneratorMIPS::useBox(LInstruction *lir, size_t n, MDefinition *mir,
michael@0 23 LUse::Policy policy, bool useAtStart)
michael@0 24 {
michael@0 25 MOZ_ASSERT(mir->type() == MIRType_Value);
michael@0 26
michael@0 27 if (!ensureDefined(mir))
michael@0 28 return false;
michael@0 29 lir->setOperand(n, LUse(mir->virtualRegister(), policy, useAtStart));
michael@0 30 lir->setOperand(n + 1, LUse(VirtualRegisterOfPayload(mir), policy, useAtStart));
michael@0 31 return true;
michael@0 32 }
michael@0 33
michael@0 34 bool
michael@0 35 LIRGeneratorMIPS::useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1,
michael@0 36 Register reg2)
michael@0 37 {
michael@0 38 MOZ_ASSERT(mir->type() == MIRType_Value);
michael@0 39 MOZ_ASSERT(reg1 != reg2);
michael@0 40
michael@0 41 if (!ensureDefined(mir))
michael@0 42 return false;
michael@0 43 lir->setOperand(n, LUse(reg1, mir->virtualRegister()));
michael@0 44 lir->setOperand(n + 1, LUse(reg2, VirtualRegisterOfPayload(mir)));
michael@0 45 return true;
michael@0 46 }
michael@0 47
michael@0 48 LAllocation
michael@0 49 LIRGeneratorMIPS::useByteOpRegister(MDefinition *mir)
michael@0 50 {
michael@0 51 return useRegister(mir);
michael@0 52 }
michael@0 53
michael@0 54 LAllocation
michael@0 55 LIRGeneratorMIPS::useByteOpRegisterOrNonDoubleConstant(MDefinition *mir)
michael@0 56 {
michael@0 57 return useRegisterOrNonDoubleConstant(mir);
michael@0 58 }
michael@0 59
michael@0 60 bool
michael@0 61 LIRGeneratorMIPS::lowerConstantDouble(double d, MInstruction *mir)
michael@0 62 {
michael@0 63 return define(new(alloc()) LDouble(d), mir);
michael@0 64 }
michael@0 65
michael@0 66 bool
michael@0 67 LIRGeneratorMIPS::lowerConstantFloat32(float d, MInstruction *mir)
michael@0 68 {
michael@0 69 return define(new(alloc()) LFloat32(d), mir);
michael@0 70 }
michael@0 71
michael@0 72 bool
michael@0 73 LIRGeneratorMIPS::visitConstant(MConstant *ins)
michael@0 74 {
michael@0 75 if (ins->type() == MIRType_Double)
michael@0 76 return lowerConstantDouble(ins->value().toDouble(), ins);
michael@0 77
michael@0 78 if (ins->type() == MIRType_Float32)
michael@0 79 return lowerConstantFloat32(ins->value().toDouble(), ins);
michael@0 80
michael@0 81 // Emit non-double constants at their uses.
michael@0 82 if (ins->canEmitAtUses())
michael@0 83 return emitAtUses(ins);
michael@0 84
michael@0 85 return LIRGeneratorShared::visitConstant(ins);
michael@0 86 }
michael@0 87
michael@0 88 bool
michael@0 89 LIRGeneratorMIPS::visitBox(MBox *box)
michael@0 90 {
michael@0 91 MDefinition *inner = box->getOperand(0);
michael@0 92
michael@0 93 // If the box wrapped a double, it needs a new register.
michael@0 94 if (IsFloatingPointType(inner->type()))
michael@0 95 return defineBox(new(alloc()) LBoxFloatingPoint(useRegisterAtStart(inner),
michael@0 96 tempCopy(inner, 0), inner->type()), box);
michael@0 97
michael@0 98 if (box->canEmitAtUses())
michael@0 99 return emitAtUses(box);
michael@0 100
michael@0 101 if (inner->isConstant())
michael@0 102 return defineBox(new(alloc()) LValue(inner->toConstant()->value()), box);
michael@0 103
michael@0 104 LBox *lir = new(alloc()) LBox(use(inner), inner->type());
michael@0 105
michael@0 106 // Otherwise, we should not define a new register for the payload portion
michael@0 107 // of the output, so bypass defineBox().
michael@0 108 uint32_t vreg = getVirtualRegister();
michael@0 109 if (vreg >= MAX_VIRTUAL_REGISTERS)
michael@0 110 return false;
michael@0 111
michael@0 112 // Note that because we're using PASSTHROUGH, we do not change the type of
michael@0 113 // the definition. We also do not define the first output as "TYPE",
michael@0 114 // because it has no corresponding payload at (vreg + 1). Also note that
michael@0 115 // although we copy the input's original type for the payload half of the
michael@0 116 // definition, this is only for clarity. PASSTHROUGH definitions are
michael@0 117 // ignored.
michael@0 118 lir->setDef(0, LDefinition(vreg, LDefinition::GENERAL));
michael@0 119 lir->setDef(1, LDefinition(inner->virtualRegister(), LDefinition::TypeFrom(inner->type()),
michael@0 120 LDefinition::PASSTHROUGH));
michael@0 121 box->setVirtualRegister(vreg);
michael@0 122 return add(lir);
michael@0 123 }
michael@0 124
michael@0 125 bool
michael@0 126 LIRGeneratorMIPS::visitUnbox(MUnbox *unbox)
michael@0 127 {
michael@0 128 // An unbox on mips reads in a type tag (either in memory or a register) and
michael@0 129 // a payload. Unlike most instructions consuming a box, we ask for the type
michael@0 130 // second, so that the result can re-use the first input.
michael@0 131 MDefinition *inner = unbox->getOperand(0);
michael@0 132
michael@0 133 if (!ensureDefined(inner))
michael@0 134 return false;
michael@0 135
michael@0 136 if (IsFloatingPointType(unbox->type())) {
michael@0 137 LUnboxFloatingPoint *lir = new(alloc()) LUnboxFloatingPoint(unbox->type());
michael@0 138 if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind()))
michael@0 139 return false;
michael@0 140 if (!useBox(lir, LUnboxFloatingPoint::Input, inner))
michael@0 141 return false;
michael@0 142 return define(lir, unbox);
michael@0 143 }
michael@0 144
michael@0 145 // Swap the order we use the box pieces so we can re-use the payload
michael@0 146 // register.
michael@0 147 LUnbox *lir = new(alloc()) LUnbox;
michael@0 148 lir->setOperand(0, usePayloadInRegisterAtStart(inner));
michael@0 149 lir->setOperand(1, useType(inner, LUse::REGISTER));
michael@0 150
michael@0 151 if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind()))
michael@0 152 return false;
michael@0 153
michael@0 154 // Note that PASSTHROUGH here is illegal, since types and payloads form two
michael@0 155 // separate intervals. If the type becomes dead before the payload, it
michael@0 156 // could be used as a Value without the type being recoverable. Unbox's
michael@0 157 // purpose is to eagerly kill the definition of a type tag, so keeping both
michael@0 158 // alive (for the purpose of gcmaps) is unappealing. Instead, we create a
michael@0 159 // new virtual register.
michael@0 160 return defineReuseInput(lir, unbox, 0);
michael@0 161 }
michael@0 162
michael@0 163 bool
michael@0 164 LIRGeneratorMIPS::visitReturn(MReturn *ret)
michael@0 165 {
michael@0 166 MDefinition *opd = ret->getOperand(0);
michael@0 167 MOZ_ASSERT(opd->type() == MIRType_Value);
michael@0 168
michael@0 169 LReturn *ins = new(alloc()) LReturn;
michael@0 170 ins->setOperand(0, LUse(JSReturnReg_Type));
michael@0 171 ins->setOperand(1, LUse(JSReturnReg_Data));
michael@0 172 return fillBoxUses(ins, 0, opd) && add(ins);
michael@0 173 }
michael@0 174
michael@0 175 // x = !y
michael@0 176 bool
michael@0 177 LIRGeneratorMIPS::lowerForALU(LInstructionHelper<1, 1, 0> *ins,
michael@0 178 MDefinition *mir, MDefinition *input)
michael@0 179 {
michael@0 180 ins->setOperand(0, useRegister(input));
michael@0 181 return define(ins, mir,
michael@0 182 LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
michael@0 183 }
michael@0 184
michael@0 185 // z = x+y
michael@0 186 bool
michael@0 187 LIRGeneratorMIPS::lowerForALU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
michael@0 188 MDefinition *lhs, MDefinition *rhs)
michael@0 189 {
michael@0 190 ins->setOperand(0, useRegister(lhs));
michael@0 191 ins->setOperand(1, useRegisterOrConstant(rhs));
michael@0 192 return define(ins, mir,
michael@0 193 LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
michael@0 194 }
michael@0 195
michael@0 196 bool
michael@0 197 LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 1, 0> *ins, MDefinition *mir,
michael@0 198 MDefinition *input)
michael@0 199 {
michael@0 200 ins->setOperand(0, useRegister(input));
michael@0 201 return define(ins, mir,
michael@0 202 LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
michael@0 203 }
michael@0 204
michael@0 205 bool
michael@0 206 LIRGeneratorMIPS::lowerForFPU(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
michael@0 207 MDefinition *lhs, MDefinition *rhs)
michael@0 208 {
michael@0 209 ins->setOperand(0, useRegister(lhs));
michael@0 210 ins->setOperand(1, useRegister(rhs));
michael@0 211 return define(ins, mir,
michael@0 212 LDefinition(LDefinition::TypeFrom(mir->type()), LDefinition::DEFAULT));
michael@0 213 }
michael@0 214
michael@0 215 bool
michael@0 216 LIRGeneratorMIPS::lowerForBitAndAndBranch(LBitAndAndBranch *baab, MInstruction *mir,
michael@0 217 MDefinition *lhs, MDefinition *rhs)
michael@0 218 {
michael@0 219 baab->setOperand(0, useRegisterAtStart(lhs));
michael@0 220 baab->setOperand(1, useRegisterOrConstantAtStart(rhs));
michael@0 221 return add(baab, mir);
michael@0 222 }
michael@0 223
michael@0 224 bool
michael@0 225 LIRGeneratorMIPS::defineUntypedPhi(MPhi *phi, size_t lirIndex)
michael@0 226 {
michael@0 227 LPhi *type = current->getPhi(lirIndex + VREG_TYPE_OFFSET);
michael@0 228 LPhi *payload = current->getPhi(lirIndex + VREG_DATA_OFFSET);
michael@0 229
michael@0 230 uint32_t typeVreg = getVirtualRegister();
michael@0 231 if (typeVreg >= MAX_VIRTUAL_REGISTERS)
michael@0 232 return false;
michael@0 233
michael@0 234 phi->setVirtualRegister(typeVreg);
michael@0 235
michael@0 236 uint32_t payloadVreg = getVirtualRegister();
michael@0 237 if (payloadVreg >= MAX_VIRTUAL_REGISTERS)
michael@0 238 return false;
michael@0 239 MOZ_ASSERT(typeVreg + 1 == payloadVreg);
michael@0 240
michael@0 241 type->setDef(0, LDefinition(typeVreg, LDefinition::TYPE));
michael@0 242 payload->setDef(0, LDefinition(payloadVreg, LDefinition::PAYLOAD));
michael@0 243 annotate(type);
michael@0 244 annotate(payload);
michael@0 245 return true;
michael@0 246 }
michael@0 247
michael@0 248 void
michael@0 249 LIRGeneratorMIPS::lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition,
michael@0 250 LBlock *block, size_t lirIndex)
michael@0 251 {
michael@0 252 MDefinition *operand = phi->getOperand(inputPosition);
michael@0 253 LPhi *type = block->getPhi(lirIndex + VREG_TYPE_OFFSET);
michael@0 254 LPhi *payload = block->getPhi(lirIndex + VREG_DATA_OFFSET);
michael@0 255 type->setOperand(inputPosition, LUse(operand->virtualRegister() + VREG_TYPE_OFFSET,
michael@0 256 LUse::ANY));
michael@0 257 payload->setOperand(inputPosition, LUse(VirtualRegisterOfPayload(operand), LUse::ANY));
michael@0 258 }
michael@0 259
michael@0 260 bool
michael@0 261 LIRGeneratorMIPS::lowerForShift(LInstructionHelper<1, 2, 0> *ins, MDefinition *mir,
michael@0 262 MDefinition *lhs, MDefinition *rhs)
michael@0 263 {
michael@0 264 ins->setOperand(0, useRegister(lhs));
michael@0 265 ins->setOperand(1, useRegisterOrConstant(rhs));
michael@0 266 return define(ins, mir);
michael@0 267 }
michael@0 268
michael@0 269 bool
michael@0 270 LIRGeneratorMIPS::lowerDivI(MDiv *div)
michael@0 271 {
michael@0 272 if (div->isUnsigned())
michael@0 273 return lowerUDiv(div);
michael@0 274
michael@0 275 // Division instructions are slow. Division by constant denominators can be
michael@0 276 // rewritten to use other instructions.
michael@0 277 if (div->rhs()->isConstant()) {
michael@0 278 int32_t rhs = div->rhs()->toConstant()->value().toInt32();
michael@0 279 // Check for division by a positive power of two, which is an easy and
michael@0 280 // important case to optimize. Note that other optimizations are also
michael@0 281 // possible; division by negative powers of two can be optimized in a
michael@0 282 // similar manner as positive powers of two, and division by other
michael@0 283 // constants can be optimized by a reciprocal multiplication technique.
michael@0 284 int32_t shift = FloorLog2(rhs);
michael@0 285 if (rhs > 0 && 1 << shift == rhs) {
michael@0 286 LDivPowTwoI *lir = new(alloc()) LDivPowTwoI(useRegister(div->lhs()), shift, temp());
michael@0 287 if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 288 return false;
michael@0 289 return define(lir, div);
michael@0 290 }
michael@0 291 }
michael@0 292
michael@0 293 LDivI *lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()), temp());
michael@0 294 if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 295 return false;
michael@0 296 return define(lir, div);
michael@0 297 }
michael@0 298
michael@0 299 bool
michael@0 300 LIRGeneratorMIPS::lowerMulI(MMul *mul, MDefinition *lhs, MDefinition *rhs)
michael@0 301 {
michael@0 302 LMulI *lir = new(alloc()) LMulI;
michael@0 303 if (mul->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 304 return false;
michael@0 305
michael@0 306 return lowerForALU(lir, mul, lhs, rhs);
michael@0 307 }
michael@0 308
michael@0 309 bool
michael@0 310 LIRGeneratorMIPS::lowerModI(MMod *mod)
michael@0 311 {
michael@0 312 if (mod->isUnsigned())
michael@0 313 return lowerUMod(mod);
michael@0 314
michael@0 315 if (mod->rhs()->isConstant()) {
michael@0 316 int32_t rhs = mod->rhs()->toConstant()->value().toInt32();
michael@0 317 int32_t shift = FloorLog2(rhs);
michael@0 318 if (rhs > 0 && 1 << shift == rhs) {
michael@0 319 LModPowTwoI *lir = new(alloc()) LModPowTwoI(useRegister(mod->lhs()), shift);
michael@0 320 if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 321 return false;
michael@0 322 return define(lir, mod);
michael@0 323 } else if (shift < 31 && (1 << (shift + 1)) - 1 == rhs) {
michael@0 324 LModMaskI *lir = new(alloc()) LModMaskI(useRegister(mod->lhs()),
michael@0 325 temp(LDefinition::GENERAL), shift + 1);
michael@0 326 if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 327 return false;
michael@0 328 return define(lir, mod);
michael@0 329 }
michael@0 330 }
michael@0 331 LModI *lir = new(alloc()) LModI(useRegister(mod->lhs()), useRegister(mod->rhs()),
michael@0 332 temp(LDefinition::GENERAL));
michael@0 333
michael@0 334 if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 335 return false;
michael@0 336 return define(lir, mod);
michael@0 337 }
michael@0 338
michael@0 339 bool
michael@0 340 LIRGeneratorMIPS::visitPowHalf(MPowHalf *ins)
michael@0 341 {
michael@0 342 MDefinition *input = ins->input();
michael@0 343 MOZ_ASSERT(input->type() == MIRType_Double);
michael@0 344 LPowHalfD *lir = new(alloc()) LPowHalfD(useRegisterAtStart(input));
michael@0 345 return defineReuseInput(lir, ins, 0);
michael@0 346 }
michael@0 347
michael@0 348 LTableSwitch *
michael@0 349 LIRGeneratorMIPS::newLTableSwitch(const LAllocation &in, const LDefinition &inputCopy,
michael@0 350 MTableSwitch *tableswitch)
michael@0 351 {
michael@0 352 return new(alloc()) LTableSwitch(in, inputCopy, temp(), tableswitch);
michael@0 353 }
michael@0 354
michael@0 355 LTableSwitchV *
michael@0 356 LIRGeneratorMIPS::newLTableSwitchV(MTableSwitch *tableswitch)
michael@0 357 {
michael@0 358 return new(alloc()) LTableSwitchV(temp(), tempFloat32(), temp(), tableswitch);
michael@0 359 }
michael@0 360
michael@0 361 bool
michael@0 362 LIRGeneratorMIPS::visitGuardShape(MGuardShape *ins)
michael@0 363 {
michael@0 364 MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
michael@0 365
michael@0 366 LDefinition tempObj = temp(LDefinition::OBJECT);
michael@0 367 LGuardShape *guard = new(alloc()) LGuardShape(useRegister(ins->obj()), tempObj);
michael@0 368 if (!assignSnapshot(guard, ins->bailoutKind()))
michael@0 369 return false;
michael@0 370 if (!add(guard, ins))
michael@0 371 return false;
michael@0 372 return redefine(ins, ins->obj());
michael@0 373 }
michael@0 374
michael@0 375 bool
michael@0 376 LIRGeneratorMIPS::visitGuardObjectType(MGuardObjectType *ins)
michael@0 377 {
michael@0 378 MOZ_ASSERT(ins->obj()->type() == MIRType_Object);
michael@0 379
michael@0 380 LDefinition tempObj = temp(LDefinition::OBJECT);
michael@0 381 LGuardObjectType *guard = new(alloc()) LGuardObjectType(useRegister(ins->obj()), tempObj);
michael@0 382 if (!assignSnapshot(guard))
michael@0 383 return false;
michael@0 384 if (!add(guard, ins))
michael@0 385 return false;
michael@0 386 return redefine(ins, ins->obj());
michael@0 387 }
michael@0 388
michael@0 389 bool
michael@0 390 LIRGeneratorMIPS::lowerUrshD(MUrsh *mir)
michael@0 391 {
michael@0 392 MDefinition *lhs = mir->lhs();
michael@0 393 MDefinition *rhs = mir->rhs();
michael@0 394
michael@0 395 MOZ_ASSERT(lhs->type() == MIRType_Int32);
michael@0 396 MOZ_ASSERT(rhs->type() == MIRType_Int32);
michael@0 397
michael@0 398 LUrshD *lir = new(alloc()) LUrshD(useRegister(lhs), useRegisterOrConstant(rhs), temp());
michael@0 399 return define(lir, mir);
michael@0 400 }
michael@0 401
michael@0 402 bool
michael@0 403 LIRGeneratorMIPS::visitAsmJSNeg(MAsmJSNeg *ins)
michael@0 404 {
michael@0 405 if (ins->type() == MIRType_Int32)
michael@0 406 return define(new(alloc()) LNegI(useRegisterAtStart(ins->input())), ins);
michael@0 407
michael@0 408 if (ins->type() == MIRType_Float32)
michael@0 409 return define(new(alloc()) LNegF(useRegisterAtStart(ins->input())), ins);
michael@0 410
michael@0 411 MOZ_ASSERT(ins->type() == MIRType_Double);
michael@0 412 return define(new(alloc()) LNegD(useRegisterAtStart(ins->input())), ins);
michael@0 413 }
michael@0 414
michael@0 415 bool
michael@0 416 LIRGeneratorMIPS::lowerUDiv(MDiv *div)
michael@0 417 {
michael@0 418 MDefinition *lhs = div->getOperand(0);
michael@0 419 MDefinition *rhs = div->getOperand(1);
michael@0 420
michael@0 421 LUDiv *lir = new(alloc()) LUDiv;
michael@0 422 lir->setOperand(0, useRegister(lhs));
michael@0 423 lir->setOperand(1, useRegister(rhs));
michael@0 424 if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 425 return false;
michael@0 426
michael@0 427 return define(lir, div);
michael@0 428 }
michael@0 429
michael@0 430 bool
michael@0 431 LIRGeneratorMIPS::lowerUMod(MMod *mod)
michael@0 432 {
michael@0 433 MDefinition *lhs = mod->getOperand(0);
michael@0 434 MDefinition *rhs = mod->getOperand(1);
michael@0 435
michael@0 436 LUMod *lir = new(alloc()) LUMod;
michael@0 437 lir->setOperand(0, useRegister(lhs));
michael@0 438 lir->setOperand(1, useRegister(rhs));
michael@0 439 if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
michael@0 440 return false;
michael@0 441
michael@0 442 return define(lir, mod);
michael@0 443 }
michael@0 444
michael@0 445 bool
michael@0 446 LIRGeneratorMIPS::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins)
michael@0 447 {
michael@0 448 MOZ_ASSERT(ins->input()->type() == MIRType_Int32);
michael@0 449 LAsmJSUInt32ToDouble *lir = new(alloc()) LAsmJSUInt32ToDouble(useRegisterAtStart(ins->input()));
michael@0 450 return define(lir, ins);
michael@0 451 }
michael@0 452
michael@0 453 bool
michael@0 454 LIRGeneratorMIPS::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins)
michael@0 455 {
michael@0 456 MOZ_ASSERT(ins->input()->type() == MIRType_Int32);
michael@0 457 LAsmJSUInt32ToFloat32 *lir = new(alloc()) LAsmJSUInt32ToFloat32(useRegisterAtStart(ins->input()));
michael@0 458 return define(lir, ins);
michael@0 459 }
michael@0 460
michael@0 461 bool
michael@0 462 LIRGeneratorMIPS::visitAsmJSLoadHeap(MAsmJSLoadHeap *ins)
michael@0 463 {
michael@0 464 MDefinition *ptr = ins->ptr();
michael@0 465 MOZ_ASSERT(ptr->type() == MIRType_Int32);
michael@0 466 LAllocation ptrAlloc;
michael@0 467
michael@0 468 // For MIPS it is best to keep the 'ptr' in a register if a bounds check
michael@0 469 // is needed.
michael@0 470 if (ptr->isConstant() && ins->skipBoundsCheck()) {
michael@0 471 int32_t ptrValue = ptr->toConstant()->value().toInt32();
michael@0 472 // A bounds check is only skipped for a positive index.
michael@0 473 MOZ_ASSERT(ptrValue >= 0);
michael@0 474 ptrAlloc = LAllocation(ptr->toConstant()->vp());
michael@0 475 } else
michael@0 476 ptrAlloc = useRegisterAtStart(ptr);
michael@0 477
michael@0 478 return define(new(alloc()) LAsmJSLoadHeap(ptrAlloc), ins);
michael@0 479 }
michael@0 480
michael@0 481 bool
michael@0 482 LIRGeneratorMIPS::visitAsmJSStoreHeap(MAsmJSStoreHeap *ins)
michael@0 483 {
michael@0 484 MDefinition *ptr = ins->ptr();
michael@0 485 MOZ_ASSERT(ptr->type() == MIRType_Int32);
michael@0 486 LAllocation ptrAlloc;
michael@0 487
michael@0 488 if (ptr->isConstant() && ins->skipBoundsCheck()) {
michael@0 489 MOZ_ASSERT(ptr->toConstant()->value().toInt32() >= 0);
michael@0 490 ptrAlloc = LAllocation(ptr->toConstant()->vp());
michael@0 491 } else
michael@0 492 ptrAlloc = useRegisterAtStart(ptr);
michael@0 493
michael@0 494 return add(new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterAtStart(ins->value())), ins);
michael@0 495 }
michael@0 496
michael@0 497 bool
michael@0 498 LIRGeneratorMIPS::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins)
michael@0 499 {
michael@0 500 return define(new(alloc()) LAsmJSLoadFuncPtr(useRegister(ins->index()), temp()), ins);
michael@0 501 }
michael@0 502
michael@0 503 bool
michael@0 504 LIRGeneratorMIPS::lowerTruncateDToInt32(MTruncateToInt32 *ins)
michael@0 505 {
michael@0 506 MDefinition *opd = ins->input();
michael@0 507 MOZ_ASSERT(opd->type() == MIRType_Double);
michael@0 508
michael@0 509 return define(new(alloc()) LTruncateDToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
michael@0 510 }
michael@0 511
michael@0 512 bool
michael@0 513 LIRGeneratorMIPS::lowerTruncateFToInt32(MTruncateToInt32 *ins)
michael@0 514 {
michael@0 515 MDefinition *opd = ins->input();
michael@0 516 MOZ_ASSERT(opd->type() == MIRType_Float32);
michael@0 517
michael@0 518 return define(new(alloc()) LTruncateFToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
michael@0 519 }
michael@0 520
michael@0 521 bool
michael@0 522 LIRGeneratorMIPS::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins)
michael@0 523 {
michael@0 524 MOZ_ASSUME_UNREACHABLE("NYI");
michael@0 525 }
michael@0 526
michael@0 527 bool
michael@0 528 LIRGeneratorMIPS::visitForkJoinGetSlice(MForkJoinGetSlice *ins)
michael@0 529 {
michael@0 530 MOZ_ASSUME_UNREACHABLE("NYI");
michael@0 531 }

mercurial