OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
10 #include "src/mips/macro-assembler-mips.h" | 10 #include "src/mips/macro-assembler-mips.h" |
11 #include "src/scopes.h" | 11 #include "src/scopes.h" |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 namespace compiler { | 15 namespace compiler { |
16 | 16 |
17 #define __ masm()-> | 17 #define __ masm()-> |
18 | 18 |
19 | 19 |
20 // TODO(plind): Possibly avoid using these lithium names. | 20 // TODO(plind): Possibly avoid using these lithium names. |
21 #define kScratchReg kLithiumScratchReg | 21 #define kScratchReg kLithiumScratchReg |
22 #define kCompareReg kLithiumScratchReg2 | 22 #define kScratchReg2 kLithiumScratchReg2 |
23 #define kScratchDoubleReg kLithiumScratchDouble | 23 #define kScratchDoubleReg kLithiumScratchDouble |
24 | 24 |
25 | 25 |
26 // TODO(plind): consider renaming these macros. | 26 // TODO(plind): consider renaming these macros. |
27 #define TRACE_MSG(msg) \ | 27 #define TRACE_MSG(msg) \ |
28 PrintF("code_gen: \'%s\' in function %s at line %d\n", msg, __FUNCTION__, \ | 28 PrintF("code_gen: \'%s\' in function %s at line %d\n", msg, __FUNCTION__, \ |
29 __LINE__) | 29 __LINE__) |
30 | 30 |
31 #define TRACE_UNIMPL() \ | 31 #define TRACE_UNIMPL() \ |
32 PrintF("UNIMPLEMENTED code_generator_mips: %s at line %d\n", __FUNCTION__, \ | 32 PrintF("UNIMPLEMENTED code_generator_mips: %s at line %d\n", __FUNCTION__, \ |
(...skipping 18 matching lines...) Expand all Loading... |
51 // Single (Float) and Double register namespace is same on MIPS, | 51 // Single (Float) and Double register namespace is same on MIPS, |
52 // both are typedefs of FPURegister. | 52 // both are typedefs of FPURegister. |
53 return ToDoubleRegister(op); | 53 return ToDoubleRegister(op); |
54 } | 54 } |
55 | 55 |
56 Operand InputImmediate(int index) { | 56 Operand InputImmediate(int index) { |
57 Constant constant = ToConstant(instr_->InputAt(index)); | 57 Constant constant = ToConstant(instr_->InputAt(index)); |
58 switch (constant.type()) { | 58 switch (constant.type()) { |
59 case Constant::kInt32: | 59 case Constant::kInt32: |
60 return Operand(constant.ToInt32()); | 60 return Operand(constant.ToInt32()); |
| 61 case Constant::kInt64: |
| 62 return Operand(constant.ToInt64()); |
61 case Constant::kFloat32: | 63 case Constant::kFloat32: |
62 return Operand( | 64 return Operand( |
63 isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED)); | 65 isolate()->factory()->NewNumber(constant.ToFloat32(), TENURED)); |
64 case Constant::kFloat64: | 66 case Constant::kFloat64: |
65 return Operand( | 67 return Operand( |
66 isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED)); | 68 isolate()->factory()->NewNumber(constant.ToFloat64(), TENURED)); |
67 case Constant::kInt64: | |
68 case Constant::kExternalReference: | 69 case Constant::kExternalReference: |
69 case Constant::kHeapObject: | 70 case Constant::kHeapObject: |
70 // TODO(plind): Maybe we should handle ExtRef & HeapObj here? | 71 // TODO(plind): Maybe we should handle ExtRef & HeapObj here? |
71 // maybe not done on arm due to const pool ?? | 72 // maybe not done on arm due to const pool ?? |
72 break; | 73 break; |
73 } | 74 } |
74 UNREACHABLE(); | 75 UNREACHABLE(); |
75 return Operand(zero_reg); | 76 return Operand(zero_reg); |
76 } | 77 } |
77 | 78 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 MipsOperandConverter i(this, instr); | 127 MipsOperandConverter i(this, instr); |
127 InstructionCode opcode = instr->opcode(); | 128 InstructionCode opcode = instr->opcode(); |
128 | 129 |
129 switch (ArchOpcodeField::decode(opcode)) { | 130 switch (ArchOpcodeField::decode(opcode)) { |
130 case kArchCallCodeObject: { | 131 case kArchCallCodeObject: { |
131 EnsureSpaceForLazyDeopt(); | 132 EnsureSpaceForLazyDeopt(); |
132 if (instr->InputAt(0)->IsImmediate()) { | 133 if (instr->InputAt(0)->IsImmediate()) { |
133 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 134 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
134 RelocInfo::CODE_TARGET); | 135 RelocInfo::CODE_TARGET); |
135 } else { | 136 } else { |
136 __ addiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 137 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
137 __ Call(at); | 138 __ Call(at); |
138 } | 139 } |
139 AddSafepointAndDeopt(instr); | 140 AddSafepointAndDeopt(instr); |
140 break; | 141 break; |
141 } | 142 } |
142 case kArchCallJSFunction: { | 143 case kArchCallJSFunction: { |
143 EnsureSpaceForLazyDeopt(); | 144 EnsureSpaceForLazyDeopt(); |
144 Register func = i.InputRegister(0); | 145 Register func = i.InputRegister(0); |
145 if (FLAG_debug_code) { | 146 if (FLAG_debug_code) { |
146 // Check the function's context matches the context argument. | 147 // Check the function's context matches the context argument. |
147 __ lw(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 148 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
148 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 149 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
149 } | 150 } |
150 | 151 |
151 __ lw(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 152 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
152 __ Call(at); | 153 __ Call(at); |
153 AddSafepointAndDeopt(instr); | 154 AddSafepointAndDeopt(instr); |
154 break; | 155 break; |
155 } | 156 } |
156 case kArchJmp: | 157 case kArchJmp: |
157 __ Branch(GetLabel(i.InputRpo(0))); | 158 __ Branch(GetLabel(i.InputRpo(0))); |
158 break; | 159 break; |
159 case kArchNop: | 160 case kArchNop: |
160 // don't emit code for nops. | 161 // don't emit code for nops. |
161 break; | 162 break; |
162 case kArchRet: | 163 case kArchRet: |
163 AssembleReturn(); | 164 AssembleReturn(); |
164 break; | 165 break; |
165 case kArchStackPointer: | 166 case kArchStackPointer: |
166 __ mov(i.OutputRegister(), sp); | 167 __ mov(i.OutputRegister(), sp); |
167 break; | 168 break; |
168 case kArchTruncateDoubleToI: | 169 case kArchTruncateDoubleToI: |
169 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 170 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); |
170 break; | 171 break; |
171 case kMipsAdd: | 172 case kMips64Add: |
172 __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 173 __ Addu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
173 break; | 174 break; |
174 case kMipsAddOvf: | 175 case kMips64Dadd: |
175 __ AdduAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), | 176 __ Daddu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
176 i.InputOperand(1), kCompareReg, kScratchReg); | |
177 break; | 177 break; |
178 case kMipsSub: | 178 case kMips64Sub: |
179 __ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 179 __ Subu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
180 break; | 180 break; |
181 case kMipsSubOvf: | 181 case kMips64Dsub: |
182 __ SubuAndCheckForOverflow(i.OutputRegister(), i.InputRegister(0), | 182 __ Dsubu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
183 i.InputOperand(1), kCompareReg, kScratchReg); | |
184 break; | 183 break; |
185 case kMipsMul: | 184 case kMips64Mul: |
186 __ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 185 __ Mul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
187 break; | 186 break; |
188 case kMipsMulHigh: | 187 case kMips64MulHigh: |
189 __ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 188 __ Mulh(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
190 break; | 189 break; |
191 case kMipsMulHighU: | 190 case kMips64MulHighU: |
192 __ Mulhu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 191 __ Mulhu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
193 break; | 192 break; |
194 case kMipsDiv: | 193 case kMips64Div: |
195 __ Div(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 194 __ Div(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
196 break; | 195 break; |
197 case kMipsDivU: | 196 case kMips64DivU: |
198 __ Divu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 197 __ Divu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
199 break; | 198 break; |
200 case kMipsMod: | 199 case kMips64Mod: |
201 __ Mod(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 200 __ Mod(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
202 break; | 201 break; |
203 case kMipsModU: | 202 case kMips64ModU: |
204 __ Modu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 203 __ Modu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
205 break; | 204 break; |
206 case kMipsAnd: | 205 case kMips64Dmul: |
| 206 __ Dmul(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
| 207 break; |
| 208 case kMips64Ddiv: |
| 209 __ Ddiv(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
| 210 break; |
| 211 case kMips64DdivU: |
| 212 __ Ddivu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
| 213 break; |
| 214 case kMips64Dmod: |
| 215 __ Dmod(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
| 216 break; |
| 217 case kMips64DmodU: |
| 218 __ Dmodu(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
| 219 break; |
207 __ And(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 220 __ And(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
208 break; | 221 break; |
209 case kMipsOr: | 222 case kMips64And: |
| 223 __ And(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
| 224 break; |
| 225 case kMips64Or: |
210 __ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 226 __ Or(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
211 break; | 227 break; |
212 case kMipsXor: | 228 case kMips64Xor: |
213 __ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 229 __ Xor(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
214 break; | 230 break; |
215 case kMipsShl: | 231 case kMips64Shl: |
216 if (instr->InputAt(1)->IsRegister()) { | 232 if (instr->InputAt(1)->IsRegister()) { |
217 __ sllv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 233 __ sllv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
218 } else { | 234 } else { |
219 int32_t imm = i.InputOperand(1).immediate(); | 235 int32_t imm = i.InputOperand(1).immediate(); |
220 __ sll(i.OutputRegister(), i.InputRegister(0), imm); | 236 __ sll(i.OutputRegister(), i.InputRegister(0), imm); |
221 } | 237 } |
222 break; | 238 break; |
223 case kMipsShr: | 239 case kMips64Shr: |
224 if (instr->InputAt(1)->IsRegister()) { | 240 if (instr->InputAt(1)->IsRegister()) { |
225 __ srlv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 241 __ srlv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
226 } else { | 242 } else { |
227 int32_t imm = i.InputOperand(1).immediate(); | 243 int32_t imm = i.InputOperand(1).immediate(); |
228 __ srl(i.OutputRegister(), i.InputRegister(0), imm); | 244 __ srl(i.OutputRegister(), i.InputRegister(0), imm); |
229 } | 245 } |
230 break; | 246 break; |
231 case kMipsSar: | 247 case kMips64Sar: |
232 if (instr->InputAt(1)->IsRegister()) { | 248 if (instr->InputAt(1)->IsRegister()) { |
233 __ srav(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); | 249 __ srav(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
234 } else { | 250 } else { |
235 int32_t imm = i.InputOperand(1).immediate(); | 251 int32_t imm = i.InputOperand(1).immediate(); |
236 __ sra(i.OutputRegister(), i.InputRegister(0), imm); | 252 __ sra(i.OutputRegister(), i.InputRegister(0), imm); |
237 } | 253 } |
238 break; | 254 break; |
239 case kMipsRor: | 255 case kMips64Ext: |
| 256 __ Ext(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1), |
| 257 i.InputInt8(2)); |
| 258 break; |
| 259 case kMips64Dext: |
| 260 __ Dext(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1), |
| 261 i.InputInt8(2)); |
| 262 break; |
| 263 case kMips64Dshl: |
| 264 if (instr->InputAt(1)->IsRegister()) { |
| 265 __ dsllv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
| 266 } else { |
| 267 int32_t imm = i.InputOperand(1).immediate(); |
| 268 if (imm < 32) { |
| 269 __ dsll(i.OutputRegister(), i.InputRegister(0), imm); |
| 270 } else { |
| 271 __ dsll32(i.OutputRegister(), i.InputRegister(0), imm - 32); |
| 272 } |
| 273 } |
| 274 break; |
| 275 case kMips64Dshr: |
| 276 if (instr->InputAt(1)->IsRegister()) { |
| 277 __ dsrlv(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
| 278 } else { |
| 279 int32_t imm = i.InputOperand(1).immediate(); |
| 280 if (imm < 32) { |
| 281 __ dsrl(i.OutputRegister(), i.InputRegister(0), imm); |
| 282 } else { |
| 283 __ dsrl32(i.OutputRegister(), i.InputRegister(0), imm - 32); |
| 284 } |
| 285 } |
| 286 break; |
| 287 case kMips64Dsar: |
| 288 if (instr->InputAt(1)->IsRegister()) { |
| 289 __ dsrav(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1)); |
| 290 } else { |
| 291 int32_t imm = i.InputOperand(1).immediate(); |
| 292 if (imm < 32) { |
| 293 __ dsra(i.OutputRegister(), i.InputRegister(0), imm); |
| 294 } else { |
| 295 __ dsra32(i.OutputRegister(), i.InputRegister(0), imm - 32); |
| 296 } |
| 297 } |
| 298 break; |
| 299 case kMips64Ror: |
240 __ Ror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); | 300 __ Ror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
241 break; | 301 break; |
242 case kMipsTst: | 302 case kMips64Dror: |
243 // Pseudo-instruction used for tst/branch. No opcode emitted here. | 303 __ Dror(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1)); |
244 break; | 304 break; |
245 case kMipsCmp: | 305 case kMips64Tst: |
| 306 case kMips64Tst32: |
246 // Pseudo-instruction used for cmp/branch. No opcode emitted here. | 307 // Pseudo-instruction used for cmp/branch. No opcode emitted here. |
247 break; | 308 break; |
248 case kMipsMov: | 309 case kMips64Cmp: |
| 310 case kMips64Cmp32: |
| 311 // Pseudo-instruction used for cmp/branch. No opcode emitted here. |
| 312 break; |
| 313 case kMips64Mov: |
249 // TODO(plind): Should we combine mov/li like this, or use separate instr? | 314 // TODO(plind): Should we combine mov/li like this, or use separate instr? |
250 // - Also see x64 ASSEMBLE_BINOP & RegisterOrOperandType | 315 // - Also see x64 ASSEMBLE_BINOP & RegisterOrOperandType |
251 if (HasRegisterInput(instr, 0)) { | 316 if (HasRegisterInput(instr, 0)) { |
252 __ mov(i.OutputRegister(), i.InputRegister(0)); | 317 __ mov(i.OutputRegister(), i.InputRegister(0)); |
253 } else { | 318 } else { |
254 __ li(i.OutputRegister(), i.InputOperand(0)); | 319 __ li(i.OutputRegister(), i.InputOperand(0)); |
255 } | 320 } |
256 break; | 321 break; |
257 | 322 |
258 case kMipsCmpD: | 323 case kMips64CmpD: |
259 // Psuedo-instruction used for FP cmp/branch. No opcode emitted here. | 324 // Psuedo-instruction used for FP cmp/branch. No opcode emitted here. |
260 break; | 325 break; |
261 case kMipsAddD: | 326 case kMips64AddD: |
262 // TODO(plind): add special case: combine mult & add. | 327 // TODO(plind): add special case: combine mult & add. |
263 __ add_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 328 __ add_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
264 i.InputDoubleRegister(1)); | 329 i.InputDoubleRegister(1)); |
265 break; | 330 break; |
266 case kMipsSubD: | 331 case kMips64SubD: |
267 __ sub_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 332 __ sub_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
268 i.InputDoubleRegister(1)); | 333 i.InputDoubleRegister(1)); |
269 break; | 334 break; |
270 case kMipsMulD: | 335 case kMips64MulD: |
271 // TODO(plind): add special case: right op is -1.0, see arm port. | 336 // TODO(plind): add special case: right op is -1.0, see arm port. |
272 __ mul_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 337 __ mul_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
273 i.InputDoubleRegister(1)); | 338 i.InputDoubleRegister(1)); |
274 break; | 339 break; |
275 case kMipsDivD: | 340 case kMips64DivD: |
276 __ div_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 341 __ div_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0), |
277 i.InputDoubleRegister(1)); | 342 i.InputDoubleRegister(1)); |
278 break; | 343 break; |
279 case kMipsModD: { | 344 case kMips64ModD: { |
280 // TODO(bmeurer): We should really get rid of this special instruction, | 345 // TODO(bmeurer): We should really get rid of this special instruction, |
281 // and generate a CallAddress instruction instead. | 346 // and generate a CallAddress instruction instead. |
282 FrameScope scope(masm(), StackFrame::MANUAL); | 347 FrameScope scope(masm(), StackFrame::MANUAL); |
283 __ PrepareCallCFunction(0, 2, kScratchReg); | 348 __ PrepareCallCFunction(0, 2, kScratchReg); |
284 __ MovToFloatParameters(i.InputDoubleRegister(0), | 349 __ MovToFloatParameters(i.InputDoubleRegister(0), |
285 i.InputDoubleRegister(1)); | 350 i.InputDoubleRegister(1)); |
286 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), | 351 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), |
287 0, 2); | 352 0, 2); |
288 // Move the result in the double result register. | 353 // Move the result in the double result register. |
289 __ MovFromFloatResult(i.OutputDoubleRegister()); | 354 __ MovFromFloatResult(i.OutputDoubleRegister()); |
290 break; | 355 break; |
291 } | 356 } |
292 case kMipsSqrtD: { | 357 case kMips64FloorD: { |
| 358 __ floor_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 359 __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
| 360 break; |
| 361 } |
| 362 case kMips64CeilD: { |
| 363 __ ceil_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 364 __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
| 365 break; |
| 366 } |
| 367 case kMips64RoundTruncateD: { |
| 368 __ trunc_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
| 369 __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); |
| 370 break; |
| 371 } |
| 372 case kMips64SqrtD: { |
293 __ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 373 __ sqrt_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); |
294 break; | 374 break; |
295 } | 375 } |
296 case kMipsCvtSD: { | 376 case kMips64CvtSD: { |
297 __ cvt_s_d(i.OutputSingleRegister(), i.InputDoubleRegister(0)); | 377 __ cvt_s_d(i.OutputSingleRegister(), i.InputDoubleRegister(0)); |
298 break; | 378 break; |
299 } | 379 } |
300 case kMipsCvtDS: { | 380 case kMips64CvtDS: { |
301 __ cvt_d_s(i.OutputDoubleRegister(), i.InputSingleRegister(0)); | 381 __ cvt_d_s(i.OutputDoubleRegister(), i.InputSingleRegister(0)); |
302 break; | 382 break; |
303 } | 383 } |
304 case kMipsCvtDW: { | 384 case kMips64CvtDW: { |
305 FPURegister scratch = kScratchDoubleReg; | 385 FPURegister scratch = kScratchDoubleReg; |
306 __ mtc1(i.InputRegister(0), scratch); | 386 __ mtc1(i.InputRegister(0), scratch); |
307 __ cvt_d_w(i.OutputDoubleRegister(), scratch); | 387 __ cvt_d_w(i.OutputDoubleRegister(), scratch); |
308 break; | 388 break; |
309 } | 389 } |
310 case kMipsCvtDUw: { | 390 case kMips64CvtDUw: { |
311 FPURegister scratch = kScratchDoubleReg; | 391 FPURegister scratch = kScratchDoubleReg; |
312 __ Cvt_d_uw(i.OutputDoubleRegister(), i.InputRegister(0), scratch); | 392 __ Cvt_d_uw(i.OutputDoubleRegister(), i.InputRegister(0), scratch); |
313 break; | 393 break; |
314 } | 394 } |
315 case kMipsTruncWD: { | 395 case kMips64TruncWD: { |
316 FPURegister scratch = kScratchDoubleReg; | 396 FPURegister scratch = kScratchDoubleReg; |
317 // Other arches use round to zero here, so we follow. | 397 // Other arches use round to zero here, so we follow. |
318 __ trunc_w_d(scratch, i.InputDoubleRegister(0)); | 398 __ trunc_w_d(scratch, i.InputDoubleRegister(0)); |
319 __ mfc1(i.OutputRegister(), scratch); | 399 __ mfc1(i.OutputRegister(), scratch); |
320 break; | 400 break; |
321 } | 401 } |
322 case kMipsTruncUwD: { | 402 case kMips64TruncUwD: { |
323 FPURegister scratch = kScratchDoubleReg; | 403 FPURegister scratch = kScratchDoubleReg; |
324 // TODO(plind): Fix wrong param order of Trunc_uw_d() macro-asm function. | 404 // TODO(plind): Fix wrong param order of Trunc_uw_d() macro-asm function. |
325 __ Trunc_uw_d(i.InputDoubleRegister(0), i.OutputRegister(), scratch); | 405 __ Trunc_uw_d(i.InputDoubleRegister(0), i.OutputRegister(), scratch); |
326 break; | 406 break; |
327 } | 407 } |
328 // ... more basic instructions ... | 408 // ... more basic instructions ... |
329 | 409 |
330 case kMipsLbu: | 410 case kMips64Lbu: |
331 __ lbu(i.OutputRegister(), i.MemoryOperand()); | 411 __ lbu(i.OutputRegister(), i.MemoryOperand()); |
332 break; | 412 break; |
333 case kMipsLb: | 413 case kMips64Lb: |
334 __ lb(i.OutputRegister(), i.MemoryOperand()); | 414 __ lb(i.OutputRegister(), i.MemoryOperand()); |
335 break; | 415 break; |
336 case kMipsSb: | 416 case kMips64Sb: |
337 __ sb(i.InputRegister(2), i.MemoryOperand()); | 417 __ sb(i.InputRegister(2), i.MemoryOperand()); |
338 break; | 418 break; |
339 case kMipsLhu: | 419 case kMips64Lhu: |
340 __ lhu(i.OutputRegister(), i.MemoryOperand()); | 420 __ lhu(i.OutputRegister(), i.MemoryOperand()); |
341 break; | 421 break; |
342 case kMipsLh: | 422 case kMips64Lh: |
343 __ lh(i.OutputRegister(), i.MemoryOperand()); | 423 __ lh(i.OutputRegister(), i.MemoryOperand()); |
344 break; | 424 break; |
345 case kMipsSh: | 425 case kMips64Sh: |
346 __ sh(i.InputRegister(2), i.MemoryOperand()); | 426 __ sh(i.InputRegister(2), i.MemoryOperand()); |
347 break; | 427 break; |
348 case kMipsLw: | 428 case kMips64Lw: |
349 __ lw(i.OutputRegister(), i.MemoryOperand()); | 429 __ lw(i.OutputRegister(), i.MemoryOperand()); |
350 break; | 430 break; |
351 case kMipsSw: | 431 case kMips64Ld: |
| 432 __ ld(i.OutputRegister(), i.MemoryOperand()); |
| 433 break; |
| 434 case kMips64Sw: |
352 __ sw(i.InputRegister(2), i.MemoryOperand()); | 435 __ sw(i.InputRegister(2), i.MemoryOperand()); |
353 break; | 436 break; |
354 case kMipsLwc1: { | 437 case kMips64Sd: |
| 438 __ sd(i.InputRegister(2), i.MemoryOperand()); |
| 439 break; |
| 440 case kMips64Lwc1: { |
355 __ lwc1(i.OutputSingleRegister(), i.MemoryOperand()); | 441 __ lwc1(i.OutputSingleRegister(), i.MemoryOperand()); |
356 break; | 442 break; |
357 } | 443 } |
358 case kMipsSwc1: { | 444 case kMips64Swc1: { |
359 int index = 0; | 445 int index = 0; |
360 MemOperand operand = i.MemoryOperand(&index); | 446 MemOperand operand = i.MemoryOperand(&index); |
361 __ swc1(i.InputSingleRegister(index), operand); | 447 __ swc1(i.InputSingleRegister(index), operand); |
362 break; | 448 break; |
363 } | 449 } |
364 case kMipsLdc1: | 450 case kMips64Ldc1: |
365 __ ldc1(i.OutputDoubleRegister(), i.MemoryOperand()); | 451 __ ldc1(i.OutputDoubleRegister(), i.MemoryOperand()); |
366 break; | 452 break; |
367 case kMipsSdc1: | 453 case kMips64Sdc1: |
368 __ sdc1(i.InputDoubleRegister(2), i.MemoryOperand()); | 454 __ sdc1(i.InputDoubleRegister(2), i.MemoryOperand()); |
369 break; | 455 break; |
370 case kMipsPush: | 456 case kMips64Push: |
371 __ Push(i.InputRegister(0)); | 457 __ Push(i.InputRegister(0)); |
372 break; | 458 break; |
373 case kMipsStoreWriteBarrier: | 459 case kMips64StoreWriteBarrier: |
374 Register object = i.InputRegister(0); | 460 Register object = i.InputRegister(0); |
375 Register index = i.InputRegister(1); | 461 Register index = i.InputRegister(1); |
376 Register value = i.InputRegister(2); | 462 Register value = i.InputRegister(2); |
377 __ addu(index, object, index); | 463 __ daddu(index, object, index); |
378 __ sw(value, MemOperand(index)); | 464 __ sd(value, MemOperand(index)); |
379 SaveFPRegsMode mode = | 465 SaveFPRegsMode mode = |
380 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 466 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
381 RAStatus ra_status = kRAHasNotBeenSaved; | 467 RAStatus ra_status = kRAHasNotBeenSaved; |
382 __ RecordWrite(object, index, value, ra_status, mode); | 468 __ RecordWrite(object, index, value, ra_status, mode); |
383 break; | 469 break; |
384 } | 470 } |
385 } | 471 } |
386 | 472 |
387 | 473 |
388 #define UNSUPPORTED_COND(opcode, condition) \ | 474 #define UNSUPPORTED_COND(opcode, condition) \ |
(...skipping 20 matching lines...) Expand all Loading... |
409 | 495 |
410 // MIPS does not have condition code flags, so compare and branch are | 496 // MIPS does not have condition code flags, so compare and branch are |
411 // implemented differently than on the other arch's. The compare operations | 497 // implemented differently than on the other arch's. The compare operations |
412 // emit mips psuedo-instructions, which are handled here by branch | 498 // emit mips psuedo-instructions, which are handled here by branch |
413 // instructions that do the actual comparison. Essential that the input | 499 // instructions that do the actual comparison. Essential that the input |
414 // registers to compare psuedo-op are not modified before this branch op, as | 500 // registers to compare psuedo-op are not modified before this branch op, as |
415 // they are tested here. | 501 // they are tested here. |
416 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 502 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were |
417 // not separated by other instructions. | 503 // not separated by other instructions. |
418 | 504 |
419 if (instr->arch_opcode() == kMipsTst) { | 505 if (instr->arch_opcode() == kMips64Tst) { |
420 switch (condition) { | 506 switch (condition) { |
421 case kNotEqual: | 507 case kNotEqual: |
422 cc = ne; | 508 cc = ne; |
423 break; | 509 break; |
424 case kEqual: | 510 case kEqual: |
425 cc = eq; | 511 cc = eq; |
426 break; | 512 break; |
427 default: | 513 default: |
428 UNSUPPORTED_COND(kMipsTst, condition); | 514 UNSUPPORTED_COND(kMips64Tst, condition); |
429 break; | 515 break; |
430 } | 516 } |
431 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 517 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
432 __ Branch(tlabel, cc, at, Operand(zero_reg)); | 518 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
433 | 519 } else if (instr->arch_opcode() == kMips64Tst32) { |
434 } else if (instr->arch_opcode() == kMipsAddOvf || | 520 switch (condition) { |
435 instr->arch_opcode() == kMipsSubOvf) { | 521 case kNotEqual: |
436 // kMipsAddOvf, SubOvf emit negative result to 'kCompareReg' on overflow. | 522 cc = ne; |
| 523 break; |
| 524 case kEqual: |
| 525 cc = eq; |
| 526 break; |
| 527 default: |
| 528 UNSUPPORTED_COND(kMips64Tst32, condition); |
| 529 break; |
| 530 } |
| 531 // Zero-extend registers on MIPS64 only 64-bit operand |
| 532 // branch and compare op. is available. |
| 533 // This is a disadvantage to perform 32-bit operation on MIPS64. |
| 534 // Try to force globally in front-end Word64 representation to be preferred |
| 535 // for MIPS64 even for Word32. |
| 536 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 537 __ Dext(at, at, 0, 32); |
| 538 __ Branch(tlabel, cc, at, Operand(zero_reg)); |
| 539 } else if (instr->arch_opcode() == kMips64Dadd || |
| 540 instr->arch_opcode() == kMips64Dsub) { |
437 switch (condition) { | 541 switch (condition) { |
438 case kOverflow: | 542 case kOverflow: |
439 cc = lt; | 543 cc = ne; |
440 break; | 544 break; |
441 case kNotOverflow: | 545 case kNotOverflow: |
442 cc = ge; | 546 cc = eq; |
443 break; | 547 break; |
444 default: | 548 default: |
445 UNSUPPORTED_COND(kMipsAddOvf, condition); | 549 UNSUPPORTED_COND(kMips64Dadd, condition); |
446 break; | 550 break; |
447 } | 551 } |
448 __ Branch(tlabel, cc, kCompareReg, Operand(zero_reg)); | |
449 | 552 |
450 } else if (instr->arch_opcode() == kMipsCmp) { | 553 __ dsra32(kScratchReg, i.OutputRegister(), 0); |
| 554 __ sra(at, i.OutputRegister(), 31); |
| 555 __ Branch(tlabel, cc, at, Operand(kScratchReg)); |
| 556 } else if (instr->arch_opcode() == kMips64Cmp) { |
451 switch (condition) { | 557 switch (condition) { |
452 case kEqual: | 558 case kEqual: |
453 cc = eq; | 559 cc = eq; |
454 break; | 560 break; |
455 case kNotEqual: | 561 case kNotEqual: |
456 cc = ne; | 562 cc = ne; |
457 break; | 563 break; |
458 case kSignedLessThan: | 564 case kSignedLessThan: |
459 cc = lt; | 565 cc = lt; |
460 break; | 566 break; |
(...skipping 12 matching lines...) Expand all Loading... |
473 case kUnsignedGreaterThanOrEqual: | 579 case kUnsignedGreaterThanOrEqual: |
474 cc = hs; | 580 cc = hs; |
475 break; | 581 break; |
476 case kUnsignedLessThanOrEqual: | 582 case kUnsignedLessThanOrEqual: |
477 cc = ls; | 583 cc = ls; |
478 break; | 584 break; |
479 case kUnsignedGreaterThan: | 585 case kUnsignedGreaterThan: |
480 cc = hi; | 586 cc = hi; |
481 break; | 587 break; |
482 default: | 588 default: |
483 UNSUPPORTED_COND(kMipsCmp, condition); | 589 UNSUPPORTED_COND(kMips64Cmp, condition); |
484 break; | 590 break; |
485 } | 591 } |
486 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); | 592 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
487 | 593 |
488 if (!fallthru) __ Branch(flabel); // no fallthru to flabel. | 594 if (!fallthru) __ Branch(flabel); // no fallthru to flabel. |
489 __ bind(&done); | 595 __ bind(&done); |
490 | 596 |
491 } else if (instr->arch_opcode() == kMipsCmpD) { | 597 } else if (instr->arch_opcode() == kMips64Cmp32) { |
| 598 switch (condition) { |
| 599 case kEqual: |
| 600 cc = eq; |
| 601 break; |
| 602 case kNotEqual: |
| 603 cc = ne; |
| 604 break; |
| 605 case kSignedLessThan: |
| 606 cc = lt; |
| 607 break; |
| 608 case kSignedGreaterThanOrEqual: |
| 609 cc = ge; |
| 610 break; |
| 611 case kSignedLessThanOrEqual: |
| 612 cc = le; |
| 613 break; |
| 614 case kSignedGreaterThan: |
| 615 cc = gt; |
| 616 break; |
| 617 case kUnsignedLessThan: |
| 618 cc = lo; |
| 619 break; |
| 620 case kUnsignedGreaterThanOrEqual: |
| 621 cc = hs; |
| 622 break; |
| 623 case kUnsignedLessThanOrEqual: |
| 624 cc = ls; |
| 625 break; |
| 626 case kUnsignedGreaterThan: |
| 627 cc = hi; |
| 628 break; |
| 629 default: |
| 630 UNSUPPORTED_COND(kMips64Cmp32, condition); |
| 631 break; |
| 632 } |
| 633 |
| 634 switch (condition) { |
| 635 case kEqual: |
| 636 case kNotEqual: |
| 637 case kSignedLessThan: |
| 638 case kSignedGreaterThanOrEqual: |
| 639 case kSignedLessThanOrEqual: |
| 640 case kSignedGreaterThan: |
| 641 // Sign-extend registers on MIPS64 only 64-bit operand |
| 642 // branch and compare op. is available. |
| 643 __ sll(i.InputRegister(0), i.InputRegister(0), 0); |
| 644 if (instr->InputAt(1)->IsRegister()) { |
| 645 __ sll(i.InputRegister(1), i.InputRegister(1), 0); |
| 646 } |
| 647 break; |
| 648 case kUnsignedLessThan: |
| 649 case kUnsignedGreaterThanOrEqual: |
| 650 case kUnsignedLessThanOrEqual: |
| 651 case kUnsignedGreaterThan: |
| 652 // Zero-extend registers on MIPS64 only 64-bit operand |
| 653 // branch and compare op. is available. |
| 654 __ Dext(i.InputRegister(0), i.InputRegister(0), 0, 32); |
| 655 if (instr->InputAt(1)->IsRegister()) { |
| 656 __ Dext(i.InputRegister(1), i.InputRegister(1), 0, 32); |
| 657 } |
| 658 break; |
| 659 default: |
| 660 UNSUPPORTED_COND(kMips64Cmp, condition); |
| 661 break; |
| 662 } |
| 663 __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1)); |
| 664 |
| 665 if (!fallthru) __ Branch(flabel); // no fallthru to flabel. |
| 666 __ bind(&done); |
| 667 } else if (instr->arch_opcode() == kMips64CmpD) { |
492 // TODO(dusmil) optimize unordered checks to use less instructions | 668 // TODO(dusmil) optimize unordered checks to use less instructions |
493 // even if we have to unfold BranchF macro. | 669 // even if we have to unfold BranchF macro. |
494 Label* nan = flabel; | 670 Label* nan = flabel; |
495 switch (condition) { | 671 switch (condition) { |
496 case kUnorderedEqual: | 672 case kUnorderedEqual: |
497 cc = eq; | 673 cc = eq; |
498 break; | 674 break; |
499 case kUnorderedNotEqual: | 675 case kUnorderedNotEqual: |
500 cc = ne; | 676 cc = ne; |
501 nan = tlabel; | 677 nan = tlabel; |
502 break; | 678 break; |
503 case kUnorderedLessThan: | 679 case kUnorderedLessThan: |
504 cc = lt; | 680 cc = lt; |
505 break; | 681 break; |
506 case kUnorderedGreaterThanOrEqual: | 682 case kUnorderedGreaterThanOrEqual: |
507 cc = ge; | 683 cc = ge; |
508 nan = tlabel; | 684 nan = tlabel; |
509 break; | 685 break; |
510 case kUnorderedLessThanOrEqual: | 686 case kUnorderedLessThanOrEqual: |
511 cc = le; | 687 cc = le; |
512 break; | 688 break; |
513 case kUnorderedGreaterThan: | 689 case kUnorderedGreaterThan: |
514 cc = gt; | 690 cc = gt; |
515 nan = tlabel; | 691 nan = tlabel; |
516 break; | 692 break; |
517 default: | 693 default: |
518 UNSUPPORTED_COND(kMipsCmpD, condition); | 694 UNSUPPORTED_COND(kMips64CmpD, condition); |
519 break; | 695 break; |
520 } | 696 } |
521 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), | 697 __ BranchF(tlabel, nan, cc, i.InputDoubleRegister(0), |
522 i.InputDoubleRegister(1)); | 698 i.InputDoubleRegister(1)); |
523 | 699 |
524 if (!fallthru) __ Branch(flabel); // no fallthru to flabel. | 700 if (!fallthru) __ Branch(flabel); // no fallthru to flabel. |
525 __ bind(&done); | 701 __ bind(&done); |
526 | 702 |
527 } else { | 703 } else { |
528 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", | 704 PrintF("AssembleArchBranch Unimplemented arch_opcode: %d\n", |
(...skipping 11 matching lines...) Expand all Loading... |
540 | 716 |
541 // Materialize a full 32-bit 1 or 0 value. The result register is always the | 717 // Materialize a full 32-bit 1 or 0 value. The result register is always the |
542 // last output of the instruction. | 718 // last output of the instruction. |
543 Label false_value; | 719 Label false_value; |
544 DCHECK_NE(0, instr->OutputCount()); | 720 DCHECK_NE(0, instr->OutputCount()); |
545 Register result = i.OutputRegister(instr->OutputCount() - 1); | 721 Register result = i.OutputRegister(instr->OutputCount() - 1); |
546 Condition cc = kNoCondition; | 722 Condition cc = kNoCondition; |
547 | 723 |
548 // MIPS does not have condition code flags, so compare and branch are | 724 // MIPS does not have condition code flags, so compare and branch are |
549 // implemented differently than on the other arch's. The compare operations | 725 // implemented differently than on the other arch's. The compare operations |
550 // emit mips psuedo-instructions, which are checked and handled here. | 726 // emit mips pseudo-instructions, which are checked and handled here. |
551 | 727 |
552 // For materializations, we use delay slot to set the result true, and | 728 // For materializations, we use delay slot to set the result true, and |
553 // in the false case, where we fall thru the branch, we reset the result | 729 // in the false case, where we fall through the branch, we reset the result |
554 // false. | 730 // false. |
555 | 731 |
556 // TODO(plind): Add CHECK() to ensure that test/cmp and this branch were | 732 if (instr->arch_opcode() == kMips64Tst) { |
557 // not separated by other instructions. | |
558 if (instr->arch_opcode() == kMipsTst) { | |
559 switch (condition) { | 733 switch (condition) { |
560 case kNotEqual: | 734 case kNotEqual: |
561 cc = ne; | 735 cc = ne; |
562 break; | 736 break; |
563 case kEqual: | 737 case kEqual: |
564 cc = eq; | 738 cc = eq; |
565 break; | 739 break; |
566 default: | 740 default: |
567 UNSUPPORTED_COND(kMipsTst, condition); | 741 UNSUPPORTED_COND(kMips64Tst, condition); |
568 break; | 742 break; |
569 } | 743 } |
570 __ And(at, i.InputRegister(0), i.InputOperand(1)); | 744 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
571 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); | 745 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); |
572 __ li(result, Operand(1)); // In delay slot. | 746 __ li(result, Operand(1)); // In delay slot. |
573 | 747 } else if (instr->arch_opcode() == kMips64Tst32) { |
574 } else if (instr->arch_opcode() == kMipsAddOvf || | 748 switch (condition) { |
575 instr->arch_opcode() == kMipsSubOvf) { | 749 case kNotEqual: |
576 // kMipsAddOvf, SubOvf emits negative result to 'kCompareReg' on overflow. | 750 cc = ne; |
| 751 break; |
| 752 case kEqual: |
| 753 cc = eq; |
| 754 break; |
| 755 default: |
| 756 UNSUPPORTED_COND(kMips64Tst, condition); |
| 757 break; |
| 758 } |
| 759 // Zero-extend register on MIPS64 only 64-bit operand |
| 760 // branch and compare op. is available. |
| 761 __ And(at, i.InputRegister(0), i.InputOperand(1)); |
| 762 __ Dext(at, at, 0, 32); |
| 763 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(zero_reg)); |
| 764 __ li(result, Operand(1)); // In delay slot. |
| 765 } else if (instr->arch_opcode() == kMips64Dadd || |
| 766 instr->arch_opcode() == kMips64Dsub) { |
577 switch (condition) { | 767 switch (condition) { |
578 case kOverflow: | 768 case kOverflow: |
579 cc = lt; | 769 cc = ne; |
580 break; | 770 break; |
581 case kNotOverflow: | 771 case kNotOverflow: |
582 cc = ge; | 772 cc = eq; |
583 break; | 773 break; |
584 default: | 774 default: |
585 UNSUPPORTED_COND(kMipsAddOvf, condition); | 775 UNSUPPORTED_COND(kMips64DAdd, condition); |
586 break; | 776 break; |
587 } | 777 } |
588 __ Branch(USE_DELAY_SLOT, &done, cc, kCompareReg, Operand(zero_reg)); | 778 __ dsra32(kScratchReg, i.OutputRegister(), 0); |
| 779 __ sra(at, i.OutputRegister(), 31); |
| 780 __ Branch(USE_DELAY_SLOT, &done, cc, at, Operand(kScratchReg)); |
589 __ li(result, Operand(1)); // In delay slot. | 781 __ li(result, Operand(1)); // In delay slot. |
590 | 782 } else if (instr->arch_opcode() == kMips64Cmp) { |
591 | |
592 } else if (instr->arch_opcode() == kMipsCmp) { | |
593 Register left = i.InputRegister(0); | 783 Register left = i.InputRegister(0); |
594 Operand right = i.InputOperand(1); | 784 Operand right = i.InputOperand(1); |
595 switch (condition) { | 785 switch (condition) { |
596 case kEqual: | 786 case kEqual: |
597 cc = eq; | 787 cc = eq; |
598 break; | 788 break; |
599 case kNotEqual: | 789 case kNotEqual: |
600 cc = ne; | 790 cc = ne; |
601 break; | 791 break; |
602 case kSignedLessThan: | 792 case kSignedLessThan: |
(...skipping 14 matching lines...) Expand all Loading... |
617 case kUnsignedGreaterThanOrEqual: | 807 case kUnsignedGreaterThanOrEqual: |
618 cc = hs; | 808 cc = hs; |
619 break; | 809 break; |
620 case kUnsignedLessThanOrEqual: | 810 case kUnsignedLessThanOrEqual: |
621 cc = ls; | 811 cc = ls; |
622 break; | 812 break; |
623 case kUnsignedGreaterThan: | 813 case kUnsignedGreaterThan: |
624 cc = hi; | 814 cc = hi; |
625 break; | 815 break; |
626 default: | 816 default: |
627 UNSUPPORTED_COND(kMipsCmp, condition); | 817 UNSUPPORTED_COND(kMips64Cmp, condition); |
628 break; | 818 break; |
629 } | 819 } |
630 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); | 820 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); |
631 __ li(result, Operand(1)); // In delay slot. | 821 __ li(result, Operand(1)); // In delay slot. |
| 822 } else if (instr->arch_opcode() == kMips64Cmp32) { |
| 823 Register left = i.InputRegister(0); |
| 824 Operand right = i.InputOperand(1); |
| 825 switch (condition) { |
| 826 case kEqual: |
| 827 cc = eq; |
| 828 break; |
| 829 case kNotEqual: |
| 830 cc = ne; |
| 831 break; |
| 832 case kSignedLessThan: |
| 833 cc = lt; |
| 834 break; |
| 835 case kSignedGreaterThanOrEqual: |
| 836 cc = ge; |
| 837 break; |
| 838 case kSignedLessThanOrEqual: |
| 839 cc = le; |
| 840 break; |
| 841 case kSignedGreaterThan: |
| 842 cc = gt; |
| 843 break; |
| 844 case kUnsignedLessThan: |
| 845 cc = lo; |
| 846 break; |
| 847 case kUnsignedGreaterThanOrEqual: |
| 848 cc = hs; |
| 849 break; |
| 850 case kUnsignedLessThanOrEqual: |
| 851 cc = ls; |
| 852 break; |
| 853 case kUnsignedGreaterThan: |
| 854 cc = hi; |
| 855 break; |
| 856 default: |
| 857 UNSUPPORTED_COND(kMips64Cmp, condition); |
| 858 break; |
| 859 } |
632 | 860 |
633 } else if (instr->arch_opcode() == kMipsCmpD) { | 861 switch (condition) { |
| 862 case kEqual: |
| 863 case kNotEqual: |
| 864 case kSignedLessThan: |
| 865 case kSignedGreaterThanOrEqual: |
| 866 case kSignedLessThanOrEqual: |
| 867 case kSignedGreaterThan: |
| 868 // Sign-extend registers on MIPS64 only 64-bit operand |
| 869 // branch and compare op. is available. |
| 870 __ sll(left, left, 0); |
| 871 if (instr->InputAt(1)->IsRegister()) { |
| 872 __ sll(i.InputRegister(1), i.InputRegister(1), 0); |
| 873 } |
| 874 break; |
| 875 case kUnsignedLessThan: |
| 876 case kUnsignedGreaterThanOrEqual: |
| 877 case kUnsignedLessThanOrEqual: |
| 878 case kUnsignedGreaterThan: |
| 879 // Zero-extend registers on MIPS64 only 64-bit operand |
| 880 // branch and compare op. is available. |
| 881 __ Dext(left, left, 0, 32); |
| 882 if (instr->InputAt(1)->IsRegister()) { |
| 883 __ Dext(i.InputRegister(1), i.InputRegister(1), 0, 32); |
| 884 } |
| 885 break; |
| 886 default: |
| 887 UNSUPPORTED_COND(kMips64Cmp32, condition); |
| 888 break; |
| 889 } |
| 890 __ Branch(USE_DELAY_SLOT, &done, cc, left, right); |
| 891 __ li(result, Operand(1)); // In delay slot. |
| 892 } else if (instr->arch_opcode() == kMips64CmpD) { |
634 FPURegister left = i.InputDoubleRegister(0); | 893 FPURegister left = i.InputDoubleRegister(0); |
635 FPURegister right = i.InputDoubleRegister(1); | 894 FPURegister right = i.InputDoubleRegister(1); |
636 // TODO(plind): Provide NaN-testing macro-asm function without need for | 895 // TODO(plind): Provide NaN-testing macro-asm function without need for |
637 // BranchF. | 896 // BranchF. |
638 FPURegister dummy1 = f0; | 897 FPURegister dummy1 = f0; |
639 FPURegister dummy2 = f2; | 898 FPURegister dummy2 = f2; |
640 switch (condition) { | 899 switch (condition) { |
641 case kUnorderedEqual: | 900 case kUnorderedEqual: |
642 // TODO(plind): improve the NaN testing throughout this function. | 901 // TODO(plind): improve the NaN testing throughout this function. |
643 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 902 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
(...skipping 16 matching lines...) Expand all Loading... |
660 case kUnorderedLessThanOrEqual: | 919 case kUnorderedLessThanOrEqual: |
661 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); | 920 __ BranchF(NULL, &false_value, kNoCondition, dummy1, dummy2); |
662 cc = le; | 921 cc = le; |
663 break; | 922 break; |
664 case kUnorderedGreaterThan: | 923 case kUnorderedGreaterThan: |
665 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); | 924 __ BranchF(USE_DELAY_SLOT, NULL, &done, kNoCondition, dummy1, dummy2); |
666 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. | 925 __ li(result, Operand(1)); // In delay slot - returns 1 on NaN. |
667 cc = gt; | 926 cc = gt; |
668 break; | 927 break; |
669 default: | 928 default: |
670 UNSUPPORTED_COND(kMipsCmp, condition); | 929 UNSUPPORTED_COND(kMips64Cmp, condition); |
671 break; | 930 break; |
672 } | 931 } |
673 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); | 932 __ BranchF(USE_DELAY_SLOT, &done, NULL, cc, left, right); |
674 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. | 933 __ li(result, Operand(1)); // In delay slot - branch taken returns 1. |
675 // Fall-thru (branch not taken) returns 0. | 934 // Fall-thru (branch not taken) returns 0. |
676 | 935 |
677 } else { | 936 } else { |
678 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", | 937 PrintF("AssembleArchBranch Unimplemented arch_opcode is : %d\n", |
679 instr->arch_opcode()); | 938 instr->arch_opcode()); |
680 TRACE_UNIMPL(); | 939 TRACE_UNIMPL(); |
681 UNIMPLEMENTED(); | 940 UNIMPLEMENTED(); |
682 } | 941 } |
683 // Fallthru case is the false materialization. | 942 // Fallthru case is the false materialization. |
684 __ bind(&false_value); | 943 __ bind(&false_value); |
685 __ li(result, Operand(0)); | 944 __ li(result, Operand(static_cast<int64_t>(0))); |
686 __ bind(&done); | 945 __ bind(&done); |
687 } | 946 } |
688 | 947 |
689 | 948 |
690 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { | 949 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { |
691 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 950 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
692 isolate(), deoptimization_id, Deoptimizer::LAZY); | 951 isolate(), deoptimization_id, Deoptimizer::LAZY); |
693 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 952 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
694 } | 953 } |
695 | 954 |
(...skipping 12 matching lines...) Expand all Loading... |
708 register_save_area_size += kPointerSize; | 967 register_save_area_size += kPointerSize; |
709 } | 968 } |
710 frame()->SetRegisterSaveAreaSize(register_save_area_size); | 969 frame()->SetRegisterSaveAreaSize(register_save_area_size); |
711 __ MultiPush(saves); | 970 __ MultiPush(saves); |
712 } | 971 } |
713 } else if (descriptor->IsJSFunctionCall()) { | 972 } else if (descriptor->IsJSFunctionCall()) { |
714 CompilationInfo* info = this->info(); | 973 CompilationInfo* info = this->info(); |
715 __ Prologue(info->IsCodePreAgingActive()); | 974 __ Prologue(info->IsCodePreAgingActive()); |
716 frame()->SetRegisterSaveAreaSize( | 975 frame()->SetRegisterSaveAreaSize( |
717 StandardFrameConstants::kFixedFrameSizeFromFp); | 976 StandardFrameConstants::kFixedFrameSizeFromFp); |
| 977 |
| 978 // Sloppy mode functions and builtins need to replace the receiver with the |
| 979 // global proxy when called as functions (without an explicit receiver |
| 980 // object). |
| 981 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
| 982 if (info->strict_mode() == SLOPPY && !info->is_native()) { |
| 983 Label ok; |
| 984 // +2 for return address and saved frame pointer. |
| 985 int receiver_slot = info->scope()->num_parameters() + 2; |
| 986 __ ld(a2, MemOperand(fp, receiver_slot * kPointerSize)); |
| 987 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 988 __ Branch(&ok, ne, a2, Operand(at)); |
| 989 |
| 990 __ ld(a2, GlobalObjectOperand()); |
| 991 __ ld(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset)); |
| 992 __ sd(a2, MemOperand(fp, receiver_slot * kPointerSize)); |
| 993 __ bind(&ok); |
| 994 } |
718 } else { | 995 } else { |
719 __ StubPrologue(); | 996 __ StubPrologue(); |
720 frame()->SetRegisterSaveAreaSize( | 997 frame()->SetRegisterSaveAreaSize( |
721 StandardFrameConstants::kFixedFrameSizeFromFp); | 998 StandardFrameConstants::kFixedFrameSizeFromFp); |
722 } | 999 } |
723 int stack_slots = frame()->GetSpillSlotCount(); | 1000 int stack_slots = frame()->GetSpillSlotCount(); |
724 if (stack_slots > 0) { | 1001 if (stack_slots > 0) { |
725 __ Subu(sp, sp, Operand(stack_slots * kPointerSize)); | 1002 __ Dsubu(sp, sp, Operand(stack_slots * kPointerSize)); |
726 } | 1003 } |
727 } | 1004 } |
728 | 1005 |
729 | 1006 |
730 void CodeGenerator::AssembleReturn() { | 1007 void CodeGenerator::AssembleReturn() { |
731 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1008 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
732 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1009 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
733 if (frame()->GetRegisterSaveAreaSize() > 0) { | 1010 if (frame()->GetRegisterSaveAreaSize() > 0) { |
734 // Remove this frame's spill slots first. | 1011 // Remove this frame's spill slots first. |
735 int stack_slots = frame()->GetSpillSlotCount(); | 1012 int stack_slots = frame()->GetSpillSlotCount(); |
736 if (stack_slots > 0) { | 1013 if (stack_slots > 0) { |
737 __ Addu(sp, sp, Operand(stack_slots * kPointerSize)); | 1014 __ Daddu(sp, sp, Operand(stack_slots * kPointerSize)); |
738 } | 1015 } |
739 // Restore registers. | 1016 // Restore registers. |
740 const RegList saves = descriptor->CalleeSavedRegisters(); | 1017 const RegList saves = descriptor->CalleeSavedRegisters(); |
741 if (saves != 0) { | 1018 if (saves != 0) { |
742 __ MultiPop(saves); | 1019 __ MultiPop(saves); |
743 } | 1020 } |
744 } | 1021 } |
745 __ mov(sp, fp); | 1022 __ mov(sp, fp); |
746 __ Pop(ra, fp); | 1023 __ Pop(ra, fp); |
747 __ Ret(); | 1024 __ Ret(); |
(...skipping 12 matching lines...) Expand all Loading... |
760 InstructionOperand* destination) { | 1037 InstructionOperand* destination) { |
761 MipsOperandConverter g(this, NULL); | 1038 MipsOperandConverter g(this, NULL); |
762 // Dispatch on the source and destination operand kinds. Not all | 1039 // Dispatch on the source and destination operand kinds. Not all |
763 // combinations are possible. | 1040 // combinations are possible. |
764 if (source->IsRegister()) { | 1041 if (source->IsRegister()) { |
765 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 1042 DCHECK(destination->IsRegister() || destination->IsStackSlot()); |
766 Register src = g.ToRegister(source); | 1043 Register src = g.ToRegister(source); |
767 if (destination->IsRegister()) { | 1044 if (destination->IsRegister()) { |
768 __ mov(g.ToRegister(destination), src); | 1045 __ mov(g.ToRegister(destination), src); |
769 } else { | 1046 } else { |
770 __ sw(src, g.ToMemOperand(destination)); | 1047 __ sd(src, g.ToMemOperand(destination)); |
771 } | 1048 } |
772 } else if (source->IsStackSlot()) { | 1049 } else if (source->IsStackSlot()) { |
773 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 1050 DCHECK(destination->IsRegister() || destination->IsStackSlot()); |
774 MemOperand src = g.ToMemOperand(source); | 1051 MemOperand src = g.ToMemOperand(source); |
775 if (destination->IsRegister()) { | 1052 if (destination->IsRegister()) { |
776 __ lw(g.ToRegister(destination), src); | 1053 __ ld(g.ToRegister(destination), src); |
777 } else { | 1054 } else { |
778 Register temp = kScratchReg; | 1055 Register temp = kScratchReg; |
779 __ lw(temp, src); | 1056 __ ld(temp, src); |
780 __ sw(temp, g.ToMemOperand(destination)); | 1057 __ sd(temp, g.ToMemOperand(destination)); |
781 } | 1058 } |
782 } else if (source->IsConstant()) { | 1059 } else if (source->IsConstant()) { |
783 Constant src = g.ToConstant(source); | 1060 Constant src = g.ToConstant(source); |
784 if (destination->IsRegister() || destination->IsStackSlot()) { | 1061 if (destination->IsRegister() || destination->IsStackSlot()) { |
785 Register dst = | 1062 Register dst = |
786 destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; | 1063 destination->IsRegister() ? g.ToRegister(destination) : kScratchReg; |
787 switch (src.type()) { | 1064 switch (src.type()) { |
788 case Constant::kInt32: | 1065 case Constant::kInt32: |
789 __ li(dst, Operand(src.ToInt32())); | 1066 __ li(dst, Operand(src.ToInt32())); |
790 break; | 1067 break; |
791 case Constant::kFloat32: | 1068 case Constant::kFloat32: |
792 __ li(dst, isolate()->factory()->NewNumber(src.ToFloat32(), TENURED)); | 1069 __ li(dst, isolate()->factory()->NewNumber(src.ToFloat32(), TENURED)); |
793 break; | 1070 break; |
794 case Constant::kInt64: | 1071 case Constant::kInt64: |
795 UNREACHABLE(); | 1072 __ li(dst, Operand(src.ToInt64())); |
796 break; | 1073 break; |
797 case Constant::kFloat64: | 1074 case Constant::kFloat64: |
798 __ li(dst, isolate()->factory()->NewNumber(src.ToFloat64(), TENURED)); | 1075 __ li(dst, isolate()->factory()->NewNumber(src.ToFloat64(), TENURED)); |
799 break; | 1076 break; |
800 case Constant::kExternalReference: | 1077 case Constant::kExternalReference: |
801 __ li(dst, Operand(src.ToExternalReference())); | 1078 __ li(dst, Operand(src.ToExternalReference())); |
802 break; | 1079 break; |
803 case Constant::kHeapObject: | 1080 case Constant::kHeapObject: |
804 __ li(dst, src.ToHeapObject()); | 1081 __ li(dst, src.ToHeapObject()); |
805 break; | 1082 break; |
806 } | 1083 } |
807 if (destination->IsStackSlot()) __ sw(dst, g.ToMemOperand(destination)); | 1084 if (destination->IsStackSlot()) __ sd(dst, g.ToMemOperand(destination)); |
808 } else if (src.type() == Constant::kFloat32) { | 1085 } else if (src.type() == Constant::kFloat32) { |
809 FPURegister dst = destination->IsDoubleRegister() | 1086 FPURegister dst = destination->IsDoubleRegister() |
810 ? g.ToDoubleRegister(destination) | 1087 ? g.ToDoubleRegister(destination) |
811 : kScratchDoubleReg.low(); | 1088 : kScratchDoubleReg.low(); |
812 // TODO(turbofan): Can we do better here? | 1089 // TODO(turbofan): Can we do better here? |
813 __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); | 1090 __ li(at, Operand(bit_cast<int32_t>(src.ToFloat32()))); |
814 __ mtc1(at, dst); | 1091 __ mtc1(at, dst); |
815 if (destination->IsDoubleStackSlot()) { | 1092 if (destination->IsDoubleStackSlot()) { |
816 __ swc1(dst, g.ToMemOperand(destination)); | 1093 __ swc1(dst, g.ToMemOperand(destination)); |
817 } | 1094 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
861 Register src = g.ToRegister(source); | 1138 Register src = g.ToRegister(source); |
862 if (destination->IsRegister()) { | 1139 if (destination->IsRegister()) { |
863 Register dst = g.ToRegister(destination); | 1140 Register dst = g.ToRegister(destination); |
864 __ Move(temp, src); | 1141 __ Move(temp, src); |
865 __ Move(src, dst); | 1142 __ Move(src, dst); |
866 __ Move(dst, temp); | 1143 __ Move(dst, temp); |
867 } else { | 1144 } else { |
868 DCHECK(destination->IsStackSlot()); | 1145 DCHECK(destination->IsStackSlot()); |
869 MemOperand dst = g.ToMemOperand(destination); | 1146 MemOperand dst = g.ToMemOperand(destination); |
870 __ mov(temp, src); | 1147 __ mov(temp, src); |
871 __ lw(src, dst); | 1148 __ ld(src, dst); |
872 __ sw(temp, dst); | 1149 __ sd(temp, dst); |
873 } | 1150 } |
874 } else if (source->IsStackSlot()) { | 1151 } else if (source->IsStackSlot()) { |
875 DCHECK(destination->IsStackSlot()); | 1152 DCHECK(destination->IsStackSlot()); |
876 Register temp_0 = kScratchReg; | 1153 Register temp_0 = kScratchReg; |
877 Register temp_1 = kCompareReg; | 1154 Register temp_1 = kScratchReg2; |
878 MemOperand src = g.ToMemOperand(source); | 1155 MemOperand src = g.ToMemOperand(source); |
879 MemOperand dst = g.ToMemOperand(destination); | 1156 MemOperand dst = g.ToMemOperand(destination); |
880 __ lw(temp_0, src); | 1157 __ ld(temp_0, src); |
881 __ lw(temp_1, dst); | 1158 __ ld(temp_1, dst); |
882 __ sw(temp_0, dst); | 1159 __ sd(temp_0, dst); |
883 __ sw(temp_1, src); | 1160 __ sd(temp_1, src); |
884 } else if (source->IsDoubleRegister()) { | 1161 } else if (source->IsDoubleRegister()) { |
885 FPURegister temp = kScratchDoubleReg; | 1162 FPURegister temp = kScratchDoubleReg; |
886 FPURegister src = g.ToDoubleRegister(source); | 1163 FPURegister src = g.ToDoubleRegister(source); |
887 if (destination->IsDoubleRegister()) { | 1164 if (destination->IsDoubleRegister()) { |
888 FPURegister dst = g.ToDoubleRegister(destination); | 1165 FPURegister dst = g.ToDoubleRegister(destination); |
889 __ Move(temp, src); | 1166 __ Move(temp, src); |
890 __ Move(src, dst); | 1167 __ Move(src, dst); |
891 __ Move(dst, temp); | 1168 __ Move(dst, temp); |
892 } else { | 1169 } else { |
893 DCHECK(destination->IsDoubleStackSlot()); | 1170 DCHECK(destination->IsDoubleStackSlot()); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 } | 1220 } |
944 } | 1221 } |
945 MarkLazyDeoptSite(); | 1222 MarkLazyDeoptSite(); |
946 } | 1223 } |
947 | 1224 |
948 #undef __ | 1225 #undef __ |
949 | 1226 |
950 } // namespace compiler | 1227 } // namespace compiler |
951 } // namespace internal | 1228 } // namespace internal |
952 } // namespace v8 | 1229 } // namespace v8 |
OLD | NEW |