| 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 } |
| 323 case kArmVnegF64: | 347 case kArmVnegF64: |
| 324 __ vneg(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); | 348 __ vneg(i.OutputFloat64Register(), i.InputFloat64Register(0)); |
| 325 break; | 349 break; |
| 350 case kArmVcvtF32F64: { |
| 351 __ vcvt_f32_f64(i.OutputFloat32Register(), i.InputFloat64Register(0)); |
| 352 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 353 break; |
| 354 } |
| 355 case kArmVcvtF64F32: { |
| 356 __ vcvt_f64_f32(i.OutputFloat64Register(), i.InputFloat32Register(0)); |
| 357 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 358 break; |
| 359 } |
| 326 case kArmVcvtF64S32: { | 360 case kArmVcvtF64S32: { |
| 327 SwVfpRegister scratch = kScratchDoubleReg.low(); | 361 SwVfpRegister scratch = kScratchDoubleReg.low(); |
| 328 __ vmov(scratch, i.InputRegister(0)); | 362 __ vmov(scratch, i.InputRegister(0)); |
| 329 __ vcvt_f64_s32(i.OutputDoubleRegister(), scratch); | 363 __ vcvt_f64_s32(i.OutputFloat64Register(), scratch); |
| 330 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 364 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 331 break; | 365 break; |
| 332 } | 366 } |
| 333 case kArmVcvtF64U32: { | 367 case kArmVcvtF64U32: { |
| 334 SwVfpRegister scratch = kScratchDoubleReg.low(); | 368 SwVfpRegister scratch = kScratchDoubleReg.low(); |
| 335 __ vmov(scratch, i.InputRegister(0)); | 369 __ vmov(scratch, i.InputRegister(0)); |
| 336 __ vcvt_f64_u32(i.OutputDoubleRegister(), scratch); | 370 __ vcvt_f64_u32(i.OutputFloat64Register(), scratch); |
| 337 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 371 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 338 break; | 372 break; |
| 339 } | 373 } |
| 340 case kArmVcvtS32F64: { | 374 case kArmVcvtS32F64: { |
| 341 SwVfpRegister scratch = kScratchDoubleReg.low(); | 375 SwVfpRegister scratch = kScratchDoubleReg.low(); |
| 342 __ vcvt_s32_f64(scratch, i.InputDoubleRegister(0)); | 376 __ vcvt_s32_f64(scratch, i.InputFloat64Register(0)); |
| 343 __ vmov(i.OutputRegister(), scratch); | 377 __ vmov(i.OutputRegister(), scratch); |
| 344 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 378 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 345 break; | 379 break; |
| 346 } | 380 } |
| 347 case kArmVcvtU32F64: { | 381 case kArmVcvtU32F64: { |
| 348 SwVfpRegister scratch = kScratchDoubleReg.low(); | 382 SwVfpRegister scratch = kScratchDoubleReg.low(); |
| 349 __ vcvt_u32_f64(scratch, i.InputDoubleRegister(0)); | 383 __ vcvt_u32_f64(scratch, i.InputFloat64Register(0)); |
| 350 __ vmov(i.OutputRegister(), scratch); | 384 __ vmov(i.OutputRegister(), scratch); |
| 351 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 385 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 352 break; | 386 break; |
| 353 } | 387 } |
| 354 case kArmLdrb: | 388 case kArmLdrb: |
| 355 __ ldrb(i.OutputRegister(), i.InputOffset()); | 389 __ ldrb(i.OutputRegister(), i.InputOffset()); |
| 356 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 390 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 357 break; | 391 break; |
| 358 case kArmLdrsb: | 392 case kArmLdrsb: |
| 359 __ ldrsb(i.OutputRegister(), i.InputOffset()); | 393 __ ldrsb(i.OutputRegister(), i.InputOffset()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 382 case kArmLdr: | 416 case kArmLdr: |
| 383 __ ldr(i.OutputRegister(), i.InputOffset()); | 417 __ ldr(i.OutputRegister(), i.InputOffset()); |
| 384 break; | 418 break; |
| 385 case kArmStr: { | 419 case kArmStr: { |
| 386 int index = 0; | 420 int index = 0; |
| 387 MemOperand operand = i.InputOffset(&index); | 421 MemOperand operand = i.InputOffset(&index); |
| 388 __ str(i.InputRegister(index), operand); | 422 __ str(i.InputRegister(index), operand); |
| 389 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 423 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 390 break; | 424 break; |
| 391 } | 425 } |
| 392 case kArmVldr32: { | 426 case kArmVldrF32: { |
| 393 SwVfpRegister scratch = kScratchDoubleReg.low(); | 427 __ vldr(i.OutputFloat32Register(), i.InputOffset()); |
| 394 __ vldr(scratch, i.InputOffset()); | |
| 395 __ vcvt_f64_f32(i.OutputDoubleRegister(), scratch); | |
| 396 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 428 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 397 break; | 429 break; |
| 398 } | 430 } |
| 399 case kArmVstr32: { | 431 case kArmVstrF32: { |
| 400 int index = 0; | 432 int index = 0; |
| 401 SwVfpRegister scratch = kScratchDoubleReg.low(); | |
| 402 MemOperand operand = i.InputOffset(&index); | 433 MemOperand operand = i.InputOffset(&index); |
| 403 __ vcvt_f32_f64(scratch, i.InputDoubleRegister(index)); | 434 __ vstr(i.InputFloat32Register(index), operand); |
| 404 __ vstr(scratch, operand); | |
| 405 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 435 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 406 break; | 436 break; |
| 407 } | 437 } |
| 408 case kArmVldr64: | 438 case kArmVldrF64: |
| 409 __ vldr(i.OutputDoubleRegister(), i.InputOffset()); | 439 __ vldr(i.OutputFloat64Register(), i.InputOffset()); |
| 410 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 440 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 411 break; | 441 break; |
| 412 case kArmVstr64: { | 442 case kArmVstrF64: { |
| 413 int index = 0; | 443 int index = 0; |
| 414 MemOperand operand = i.InputOffset(&index); | 444 MemOperand operand = i.InputOffset(&index); |
| 415 __ vstr(i.InputDoubleRegister(index), operand); | 445 __ vstr(i.InputFloat64Register(index), operand); |
| 416 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 446 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 417 break; | 447 break; |
| 418 } | 448 } |
| 419 case kArmPush: | 449 case kArmPush: |
| 420 __ Push(i.InputRegister(0)); | 450 __ Push(i.InputRegister(0)); |
| 421 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 451 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 422 break; | 452 break; |
| 423 case kArmStoreWriteBarrier: { | 453 case kArmStoreWriteBarrier: { |
| 424 Register object = i.InputRegister(0); | 454 Register object = i.InputRegister(0); |
| 425 Register index = i.InputRegister(1); | 455 Register index = i.InputRegister(1); |
| (...skipping 438 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 864 } | 894 } |
| 865 } | 895 } |
| 866 MarkLazyDeoptSite(); | 896 MarkLazyDeoptSite(); |
| 867 } | 897 } |
| 868 | 898 |
| 869 #undef __ | 899 #undef __ |
| 870 | 900 |
| 871 } // namespace compiler | 901 } // namespace compiler |
| 872 } // namespace internal | 902 } // namespace internal |
| 873 } // namespace v8 | 903 } // namespace v8 |
| OLD | NEW |