| 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 |