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 #include "jit/mips64/Lowering-mips64.h"
8
9 #include "jit/Lowering.h"
10 #include "jit/mips64/Assembler-mips64.h"
11 #include "jit/MIR.h"
12
13 #include "jit/shared/Lowering-shared-inl.h"
14
15 using namespace js;
16 using namespace js::jit;
17
defineInt64Phi(MPhi * phi,size_t lirIndex)18 void LIRGeneratorMIPS64::defineInt64Phi(MPhi* phi, size_t lirIndex) {
19 defineTypedPhi(phi, lirIndex);
20 }
21
lowerInt64PhiInput(MPhi * phi,uint32_t inputPosition,LBlock * block,size_t lirIndex)22 void LIRGeneratorMIPS64::lowerInt64PhiInput(MPhi* phi, uint32_t inputPosition,
23 LBlock* block, size_t lirIndex) {
24 lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
25 }
26
useBoxFixed(MDefinition * mir,Register reg1,Register reg2,bool useAtStart)27 LBoxAllocation LIRGeneratorMIPS64::useBoxFixed(MDefinition* mir, Register reg1,
28 Register reg2, bool useAtStart) {
29 MOZ_ASSERT(mir->type() == MIRType::Value);
30
31 ensureDefined(mir);
32 return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart));
33 }
34
lowerDivI64(MDiv * div)35 void LIRGeneratorMIPS64::lowerDivI64(MDiv* div) {
36 if (div->isUnsigned()) {
37 lowerUDivI64(div);
38 return;
39 }
40
41 LDivOrModI64* lir = new (alloc())
42 LDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs()), temp());
43 defineInt64(lir, div);
44 }
45
lowerWasmBuiltinDivI64(MWasmBuiltinDivI64 * div)46 void LIRGeneratorMIPS64::lowerWasmBuiltinDivI64(MWasmBuiltinDivI64* div) {
47 MOZ_CRASH("We don't use runtime div for this architecture");
48 }
49
lowerModI64(MMod * mod)50 void LIRGeneratorMIPS64::lowerModI64(MMod* mod) {
51 if (mod->isUnsigned()) {
52 lowerUModI64(mod);
53 return;
54 }
55
56 LDivOrModI64* lir = new (alloc())
57 LDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs()), temp());
58 defineInt64(lir, mod);
59 }
60
lowerWasmBuiltinModI64(MWasmBuiltinModI64 * mod)61 void LIRGeneratorMIPS64::lowerWasmBuiltinModI64(MWasmBuiltinModI64* mod) {
62 MOZ_CRASH("We don't use runtime mod for this architecture");
63 }
64
lowerUDivI64(MDiv * div)65 void LIRGeneratorMIPS64::lowerUDivI64(MDiv* div) {
66 LUDivOrModI64* lir = new (alloc())
67 LUDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs()), temp());
68 defineInt64(lir, div);
69 }
70
lowerUModI64(MMod * mod)71 void LIRGeneratorMIPS64::lowerUModI64(MMod* mod) {
72 LUDivOrModI64* lir = new (alloc())
73 LUDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs()), temp());
74 defineInt64(lir, mod);
75 }
76
lowerBigIntDiv(MBigIntDiv * ins)77 void LIRGeneratorMIPS64::lowerBigIntDiv(MBigIntDiv* ins) {
78 auto* lir = new (alloc()) LBigIntDiv(useRegister(ins->lhs()),
79 useRegister(ins->rhs()), temp(), temp());
80 define(lir, ins);
81 assignSafepoint(lir, ins);
82 }
83
lowerBigIntMod(MBigIntMod * ins)84 void LIRGeneratorMIPS64::lowerBigIntMod(MBigIntMod* ins) {
85 auto* lir = new (alloc()) LBigIntMod(useRegister(ins->lhs()),
86 useRegister(ins->rhs()), temp(), temp());
87 define(lir, ins);
88 assignSafepoint(lir, ins);
89 }
90
lowerAtomicLoad64(MLoadUnboxedScalar * ins)91 void LIRGeneratorMIPS64::lowerAtomicLoad64(MLoadUnboxedScalar* ins) {
92 const LUse elements = useRegister(ins->elements());
93 const LAllocation index =
94 useRegisterOrIndexConstant(ins->index(), ins->storageType());
95
96 auto* lir = new (alloc()) LAtomicLoad64(elements, index, temp(), tempInt64());
97 define(lir, ins);
98 assignSafepoint(lir, ins);
99 }
100
lowerAtomicStore64(MStoreUnboxedScalar * ins)101 void LIRGeneratorMIPS64::lowerAtomicStore64(MStoreUnboxedScalar* ins) {
102 LUse elements = useRegister(ins->elements());
103 LAllocation index =
104 useRegisterOrIndexConstant(ins->index(), ins->writeType());
105 LAllocation value = useRegister(ins->value());
106
107 add(new (alloc()) LAtomicStore64(elements, index, value, tempInt64()), ins);
108 }
109
visitBox(MBox * box)110 void LIRGenerator::visitBox(MBox* box) {
111 MDefinition* opd = box->getOperand(0);
112
113 // If the operand is a constant, emit near its uses.
114 if (opd->isConstant() && box->canEmitAtUses()) {
115 emitAtUses(box);
116 return;
117 }
118
119 if (opd->isConstant()) {
120 define(new (alloc()) LValue(opd->toConstant()->toJSValue()), box,
121 LDefinition(LDefinition::BOX));
122 } else {
123 LBox* ins = new (alloc()) LBox(useRegister(opd), opd->type());
124 define(ins, box, LDefinition(LDefinition::BOX));
125 }
126 }
127
visitUnbox(MUnbox * unbox)128 void LIRGenerator::visitUnbox(MUnbox* unbox) {
129 MDefinition* box = unbox->getOperand(0);
130 MOZ_ASSERT(box->type() == MIRType::Value);
131
132 LUnbox* lir;
133 if (IsFloatingPointType(unbox->type())) {
134 lir = new (alloc())
135 LUnboxFloatingPoint(useRegisterAtStart(box), unbox->type());
136 } else if (unbox->fallible()) {
137 // If the unbox is fallible, load the Value in a register first to
138 // avoid multiple loads.
139 lir = new (alloc()) LUnbox(useRegisterAtStart(box));
140 } else {
141 lir = new (alloc()) LUnbox(useAtStart(box));
142 }
143
144 if (unbox->fallible()) {
145 assignSnapshot(lir, unbox->bailoutKind());
146 }
147
148 define(lir, unbox);
149 }
150
visitReturnImpl(MDefinition * opd,bool isGenerator)151 void LIRGenerator::visitReturnImpl(MDefinition* opd, bool isGenerator) {
152 MOZ_ASSERT(opd->type() == MIRType::Value);
153
154 LReturn* ins = new (alloc()) LReturn(isGenerator);
155 ins->setOperand(0, useFixed(opd, JSReturnReg));
156 add(ins);
157 }
158
lowerUntypedPhiInput(MPhi * phi,uint32_t inputPosition,LBlock * block,size_t lirIndex)159 void LIRGeneratorMIPS64::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
160 LBlock* block, size_t lirIndex) {
161 lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
162 }
163
lowerTruncateDToInt32(MTruncateToInt32 * ins)164 void LIRGeneratorMIPS64::lowerTruncateDToInt32(MTruncateToInt32* ins) {
165 MDefinition* opd = ins->input();
166 MOZ_ASSERT(opd->type() == MIRType::Double);
167
168 define(new (alloc()) LTruncateDToInt32(useRegister(opd), tempDouble()), ins);
169 }
170
lowerTruncateFToInt32(MTruncateToInt32 * ins)171 void LIRGeneratorMIPS64::lowerTruncateFToInt32(MTruncateToInt32* ins) {
172 MDefinition* opd = ins->input();
173 MOZ_ASSERT(opd->type() == MIRType::Float32);
174
175 define(new (alloc()) LTruncateFToInt32(useRegister(opd), tempFloat32()), ins);
176 }
177
visitWasmTruncateToInt64(MWasmTruncateToInt64 * ins)178 void LIRGenerator::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins) {
179 MDefinition* opd = ins->input();
180 MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
181
182 defineInt64(new (alloc()) LWasmTruncateToInt64(useRegister(opd)), ins);
183 }
184
lowerWasmBuiltinTruncateToInt64(MWasmBuiltinTruncateToInt64 * ins)185 void LIRGeneratorMIPS64::lowerWasmBuiltinTruncateToInt64(
186 MWasmBuiltinTruncateToInt64* ins) {
187 MOZ_CRASH("We don't use it for this architecture");
188 }
189
visitInt64ToFloatingPoint(MInt64ToFloatingPoint * ins)190 void LIRGenerator::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins) {
191 MDefinition* opd = ins->input();
192 MOZ_ASSERT(opd->type() == MIRType::Int64);
193 MOZ_ASSERT(IsFloatingPointType(ins->type()));
194
195 define(new (alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
196 }
197
lowerBuiltinInt64ToFloatingPoint(MBuiltinInt64ToFloatingPoint * ins)198 void LIRGeneratorMIPS64::lowerBuiltinInt64ToFloatingPoint(
199 MBuiltinInt64ToFloatingPoint* ins) {
200 MOZ_CRASH("We don't use it for this architecture");
201 }
202