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 | 6 |
7 #include "src/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
11 #include "src/compiler/node-properties-inl.h" | 11 #include "src/compiler/node-properties-inl.h" |
12 #include "src/scopes.h" | 12 #include "src/scopes.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 #define __ masm()-> | 18 #define __ masm()-> |
19 | 19 |
20 | 20 |
21 #define kScratchReg r9 | 21 #define kScratchReg r9 |
22 | 22 |
23 | 23 |
24 // Adds Arm-specific methods to convert InstructionOperands. | 24 // Adds Arm-specific methods to convert InstructionOperands. |
25 class ArmOperandConverter : public InstructionOperandConverter { | 25 class ArmOperandConverter FINAL : public InstructionOperandConverter { |
26 public: | 26 public: |
27 ArmOperandConverter(CodeGenerator* gen, Instruction* instr) | 27 ArmOperandConverter(CodeGenerator* gen, Instruction* instr) |
28 : InstructionOperandConverter(gen, instr) {} | 28 : InstructionOperandConverter(gen, instr) {} |
29 | 29 |
| 30 SwVfpRegister OutputFloat32Register(int index = 0) { |
| 31 return ToFloat32Register(instr_->OutputAt(index)); |
| 32 } |
| 33 |
| 34 SwVfpRegister InputFloat32Register(int index) { |
| 35 return ToFloat32Register(instr_->InputAt(index)); |
| 36 } |
| 37 |
| 38 SwVfpRegister ToFloat32Register(InstructionOperand* op) { |
| 39 return ToFloat64Register(op).low(); |
| 40 } |
| 41 |
| 42 LowDwVfpRegister OutputFloat64Register(int index = 0) { |
| 43 return ToFloat64Register(instr_->OutputAt(index)); |
| 44 } |
| 45 |
| 46 LowDwVfpRegister InputFloat64Register(int index) { |
| 47 return ToFloat64Register(instr_->InputAt(index)); |
| 48 } |
| 49 |
| 50 LowDwVfpRegister ToFloat64Register(InstructionOperand* op) { |
| 51 return LowDwVfpRegister::from_code(ToDoubleRegister(op).code()); |
| 52 } |
| 53 |
30 SBit OutputSBit() const { | 54 SBit OutputSBit() const { |
31 switch (instr_->flags_mode()) { | 55 switch (instr_->flags_mode()) { |
32 case kFlags_branch: | 56 case kFlags_branch: |
33 case kFlags_set: | 57 case kFlags_set: |
34 return SetCC; | 58 return SetCC; |
35 case kFlags_none: | 59 case kFlags_none: |
36 return LeaveCC; | 60 return LeaveCC; |
37 } | 61 } |
38 UNREACHABLE(); | 62 UNREACHABLE(); |
39 return LeaveCC; | 63 return LeaveCC; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
171 break; | 195 break; |
172 case kArchNop: | 196 case kArchNop: |
173 // don't emit code for nops. | 197 // don't emit code for nops. |
174 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 198 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
175 break; | 199 break; |
176 case kArchRet: | 200 case kArchRet: |
177 AssembleReturn(); | 201 AssembleReturn(); |
178 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 202 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
179 break; | 203 break; |
180 case kArchTruncateDoubleToI: | 204 case kArchTruncateDoubleToI: |
181 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); | 205 __ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0)); |
182 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 206 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
183 break; | 207 break; |
184 case kArmAdd: | 208 case kArmAdd: |
185 __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), | 209 __ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), |
186 i.OutputSBit()); | 210 i.OutputSBit()); |
187 break; | 211 break; |
188 case kArmAnd: | 212 case kArmAnd: |
189 __ and_(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), | 213 __ and_(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1), |
190 i.OutputSBit()); | 214 i.OutputSBit()); |
191 break; | 215 break; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 break; | 289 break; |
266 case kArmTst: | 290 case kArmTst: |
267 __ tst(i.InputRegister(0), i.InputOperand2(1)); | 291 __ tst(i.InputRegister(0), i.InputOperand2(1)); |
268 DCHECK_EQ(SetCC, i.OutputSBit()); | 292 DCHECK_EQ(SetCC, i.OutputSBit()); |
269 break; | 293 break; |
270 case kArmTeq: | 294 case kArmTeq: |
271 __ teq(i.InputRegister(0), i.InputOperand2(1)); | 295 __ teq(i.InputRegister(0), i.InputOperand2(1)); |
272 DCHECK_EQ(SetCC, i.OutputSBit()); | 296 DCHECK_EQ(SetCC, i.OutputSBit()); |
273 break; | 297 break; |
274 case kArmVcmpF64: | 298 case kArmVcmpF64: |
275 __ VFPCompareAndSetFlags(i.InputDoubleRegister(0), | 299 __ VFPCompareAndSetFlags(i.InputFloat64Register(0), |
276 i.InputDoubleRegister(1)); | 300 i.InputFloat64Register(1)); |
277 DCHECK_EQ(SetCC, i.OutputSBit()); | 301 DCHECK_EQ(SetCC, i.OutputSBit()); |
278 break; | 302 break; |
279 case kArmVaddF64: | 303 case kArmVaddF64: |
280 __ vadd(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 304 __ vadd(i.OutputFloat64Register(), i.InputFloat64Register(0), |
281 i.InputDoubleRegister(1)); | 305 i.InputFloat64Register(1)); |
282 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 306 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
283 break; | 307 break; |
284 case kArmVsubF64: | 308 case kArmVsubF64: |
285 __ vsub(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 309 __ vsub(i.OutputFloat64Register(), i.InputFloat64Register(0), |
286 i.InputDoubleRegister(1)); | 310 i.InputFloat64Register(1)); |
287 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 311 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
288 break; | 312 break; |
289 case kArmVmulF64: | 313 case kArmVmulF64: |
290 __ vmul(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 314 __ vmul(i.OutputFloat64Register(), i.InputFloat64Register(0), |
291 i.InputDoubleRegister(1)); | 315 i.InputFloat64Register(1)); |
292 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 316 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
293 break; | 317 break; |
294 case kArmVmlaF64: | 318 case kArmVmlaF64: |
295 __ vmla(i.OutputDoubleRegister(), i.InputDoubleRegister(1), | 319 __ vmla(i.OutputFloat64Register(), i.InputFloat64Register(1), |
296 i.InputDoubleRegister(2)); | 320 i.InputFloat64Register(2)); |
297 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 321 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
298 break; | 322 break; |
299 case kArmVmlsF64: | 323 case kArmVmlsF64: |
300 __ vmls(i.OutputDoubleRegister(), i.InputDoubleRegister(1), | 324 __ vmls(i.OutputFloat64Register(), i.InputFloat64Register(1), |
301 i.InputDoubleRegister(2)); | 325 i.InputFloat64Register(2)); |
302 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 326 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
303 break; | 327 break; |
304 case kArmVdivF64: | 328 case kArmVdivF64: |
305 __ vdiv(i.OutputDoubleRegister(), i.InputDoubleRegister(0), | 329 __ vdiv(i.OutputFloat64Register(), i.InputFloat64Register(0), |
306 i.InputDoubleRegister(1)); | 330 i.InputFloat64Register(1)); |
307 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 331 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
308 break; | 332 break; |
309 case kArmVmodF64: { | 333 case kArmVmodF64: { |
310 // TODO(bmeurer): We should really get rid of this special instruction, | 334 // TODO(bmeurer): We should really get rid of this special instruction, |
311 // and generate a CallAddress instruction instead. | 335 // and generate a CallAddress instruction instead. |
312 FrameScope scope(masm(), StackFrame::MANUAL); | 336 FrameScope scope(masm(), StackFrame::MANUAL); |
313 __ PrepareCallCFunction(0, 2, kScratchReg); | 337 __ PrepareCallCFunction(0, 2, kScratchReg); |
314 __ MovToFloatParameters(i.InputDoubleRegister(0), | 338 __ MovToFloatParameters(i.InputFloat64Register(0), |
315 i.InputDoubleRegister(1)); | 339 i.InputFloat64Register(1)); |
316 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), | 340 __ CallCFunction(ExternalReference::mod_two_doubles_operation(isolate()), |
317 0, 2); | 341 0, 2); |
318 // Move the result in the double result register. | 342 // Move the result in the double result register. |
319 __ MovFromFloatResult(i.OutputDoubleRegister()); | 343 __ MovFromFloatResult(i.OutputFloat64Register()); |
320 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 344 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
321 break; | 345 break; |
322 } | 346 } |
| 347 case kArmVsqrtF64: |
| 348 __ vsqrt(i.OutputFloat64Register(), i.InputFloat64Register(0)); |
| 349 break; |
323 case kArmVnegF64: | 350 case kArmVnegF64: |
324 __ vneg(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 351 __ vneg(i.OutputFloat64Register(), i.InputFloat64Register(0)); |
325 break; | 352 break; |
326 case kArmVsqrtF64: | 353 case kArmVcvtF32F64: { |
327 __ vsqrt(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 354 __ vcvt_f32_f64(i.OutputFloat32Register(), i.InputFloat64Register(0)); |
| 355 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
328 break; | 356 break; |
| 357 } |
| 358 case kArmVcvtF64F32: { |
| 359 __ vcvt_f64_f32(i.OutputFloat64Register(), i.InputFloat32Register(0)); |
| 360 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 361 break; |
| 362 } |
329 case kArmVcvtF64S32: { | 363 case kArmVcvtF64S32: { |
330 SwVfpRegister scratch = kScratchDoubleReg.low(); | 364 SwVfpRegister scratch = kScratchDoubleReg.low(); |
331 __ vmov(scratch, i.InputRegister(0)); | 365 __ vmov(scratch, i.InputRegister(0)); |
332 __ vcvt_f64_s32(i.OutputDoubleRegister(), scratch); | 366 __ vcvt_f64_s32(i.OutputFloat64Register(), scratch); |
333 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 367 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
334 break; | 368 break; |
335 } | 369 } |
336 case kArmVcvtF64U32: { | 370 case kArmVcvtF64U32: { |
337 SwVfpRegister scratch = kScratchDoubleReg.low(); | 371 SwVfpRegister scratch = kScratchDoubleReg.low(); |
338 __ vmov(scratch, i.InputRegister(0)); | 372 __ vmov(scratch, i.InputRegister(0)); |
339 __ vcvt_f64_u32(i.OutputDoubleRegister(), scratch); | 373 __ vcvt_f64_u32(i.OutputFloat64Register(), scratch); |
340 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 374 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
341 break; | 375 break; |
342 } | 376 } |
343 case kArmVcvtS32F64: { | 377 case kArmVcvtS32F64: { |
344 SwVfpRegister scratch = kScratchDoubleReg.low(); | 378 SwVfpRegister scratch = kScratchDoubleReg.low(); |
345 __ vcvt_s32_f64(scratch, i.InputDoubleRegister(0)); | 379 __ vcvt_s32_f64(scratch, i.InputFloat64Register(0)); |
346 __ vmov(i.OutputRegister(), scratch); | 380 __ vmov(i.OutputRegister(), scratch); |
347 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 381 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
348 break; | 382 break; |
349 } | 383 } |
350 case kArmVcvtU32F64: { | 384 case kArmVcvtU32F64: { |
351 SwVfpRegister scratch = kScratchDoubleReg.low(); | 385 SwVfpRegister scratch = kScratchDoubleReg.low(); |
352 __ vcvt_u32_f64(scratch, i.InputDoubleRegister(0)); | 386 __ vcvt_u32_f64(scratch, i.InputFloat64Register(0)); |
353 __ vmov(i.OutputRegister(), scratch); | 387 __ vmov(i.OutputRegister(), scratch); |
354 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 388 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
355 break; | 389 break; |
356 } | 390 } |
357 case kArmLdrb: | 391 case kArmLdrb: |
358 __ ldrb(i.OutputRegister(), i.InputOffset()); | 392 __ ldrb(i.OutputRegister(), i.InputOffset()); |
359 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 393 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
360 break; | 394 break; |
361 case kArmLdrsb: | 395 case kArmLdrsb: |
362 __ ldrsb(i.OutputRegister(), i.InputOffset()); | 396 __ ldrsb(i.OutputRegister(), i.InputOffset()); |
(...skipping 22 matching lines...) Expand all Loading... |
385 case kArmLdr: | 419 case kArmLdr: |
386 __ ldr(i.OutputRegister(), i.InputOffset()); | 420 __ ldr(i.OutputRegister(), i.InputOffset()); |
387 break; | 421 break; |
388 case kArmStr: { | 422 case kArmStr: { |
389 int index = 0; | 423 int index = 0; |
390 MemOperand operand = i.InputOffset(&index); | 424 MemOperand operand = i.InputOffset(&index); |
391 __ str(i.InputRegister(index), operand); | 425 __ str(i.InputRegister(index), operand); |
392 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 426 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
393 break; | 427 break; |
394 } | 428 } |
395 case kArmVldr32: { | 429 case kArmVldrF32: { |
396 SwVfpRegister scratch = kScratchDoubleReg.low(); | 430 __ vldr(i.OutputFloat32Register(), i.InputOffset()); |
397 __ vldr(scratch, i.InputOffset()); | |
398 __ vcvt_f64_f32(i.OutputDoubleRegister(), scratch); | |
399 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 431 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
400 break; | 432 break; |
401 } | 433 } |
402 case kArmVstr32: { | 434 case kArmVstrF32: { |
403 int index = 0; | 435 int index = 0; |
404 SwVfpRegister scratch = kScratchDoubleReg.low(); | |
405 MemOperand operand = i.InputOffset(&index); | 436 MemOperand operand = i.InputOffset(&index); |
406 __ vcvt_f32_f64(scratch, i.InputDoubleRegister(index)); | 437 __ vstr(i.InputFloat32Register(index), operand); |
407 __ vstr(scratch, operand); | |
408 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 438 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
409 break; | 439 break; |
410 } | 440 } |
411 case kArmVldr64: | 441 case kArmVldrF64: |
412 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); | 442 __ vldr(i.OutputFloat64Register(), i.InputOffset()); |
413 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 443 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
414 break; | 444 break; |
415 case kArmVstr64: { | 445 case kArmVstrF64: { |
416 int index = 0; | 446 int index = 0; |
417 MemOperand operand = i.InputOffset(&index); | 447 MemOperand operand = i.InputOffset(&index); |
418 __ vstr(i.InputDoubleRegister(index), operand); | 448 __ vstr(i.InputFloat64Register(index), operand); |
419 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 449 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
420 break; | 450 break; |
421 } | 451 } |
422 case kArmPush: | 452 case kArmPush: |
423 __ Push(i.InputRegister(0)); | 453 __ Push(i.InputRegister(0)); |
424 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 454 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
425 break; | 455 break; |
426 case kArmStoreWriteBarrier: { | 456 case kArmStoreWriteBarrier: { |
427 Register object = i.InputRegister(0); | 457 Register object = i.InputRegister(0); |
428 Register index = i.InputRegister(1); | 458 Register index = i.InputRegister(1); |
(...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 } | 897 } |
868 } | 898 } |
869 MarkLazyDeoptSite(); | 899 MarkLazyDeoptSite(); |
870 } | 900 } |
871 | 901 |
872 #undef __ | 902 #undef __ |
873 | 903 |
874 } // namespace compiler | 904 } // namespace compiler |
875 } // namespace internal | 905 } // namespace internal |
876 } // namespace v8 | 906 } // namespace v8 |
OLD | NEW |