OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 | 51 |
52 | 52 |
53 void MacroAssembler::LogicalMacro(const Register& rd, | 53 void MacroAssembler::LogicalMacro(const Register& rd, |
54 const Register& rn, | 54 const Register& rn, |
55 const Operand& operand, | 55 const Operand& operand, |
56 LogicalOp op) { | 56 LogicalOp op) { |
57 UseScratchRegisterScope temps(this); | 57 UseScratchRegisterScope temps(this); |
58 | 58 |
59 if (operand.NeedsRelocation(this)) { | 59 if (operand.NeedsRelocation(this)) { |
60 Register temp = temps.AcquireX(); | 60 Register temp = temps.AcquireX(); |
61 LoadRelocated(temp, operand); | 61 Ldr(temp, operand.immediate()); |
62 Logical(rd, rn, temp, op); | 62 Logical(rd, rn, temp, op); |
63 | 63 |
64 } else if (operand.IsImmediate()) { | 64 } else if (operand.IsImmediate()) { |
65 int64_t immediate = operand.immediate(); | 65 int64_t immediate = operand.ImmediateValue(); |
66 unsigned reg_size = rd.SizeInBits(); | 66 unsigned reg_size = rd.SizeInBits(); |
67 ASSERT(rd.Is64Bits() || is_uint32(immediate)); | 67 ASSERT(rd.Is64Bits() || is_uint32(immediate)); |
68 | 68 |
69 // If the operation is NOT, invert the operation and immediate. | 69 // If the operation is NOT, invert the operation and immediate. |
70 if ((op & NOT) == NOT) { | 70 if ((op & NOT) == NOT) { |
71 op = static_cast<LogicalOp>(op & ~NOT); | 71 op = static_cast<LogicalOp>(op & ~NOT); |
72 immediate = ~immediate; | 72 immediate = ~immediate; |
73 if (rd.Is32Bits()) { | 73 if (rd.Is32Bits()) { |
74 immediate &= kWRegMask; | 74 immediate &= kWRegMask; |
75 } | 75 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 DiscardMoveMode discard_mode) { | 243 DiscardMoveMode discard_mode) { |
244 ASSERT(allow_macro_instructions_); | 244 ASSERT(allow_macro_instructions_); |
245 ASSERT(!rd.IsZero()); | 245 ASSERT(!rd.IsZero()); |
246 | 246 |
247 // Provide a swap register for instructions that need to write into the | 247 // Provide a swap register for instructions that need to write into the |
248 // system stack pointer (and can't do this inherently). | 248 // system stack pointer (and can't do this inherently). |
249 UseScratchRegisterScope temps(this); | 249 UseScratchRegisterScope temps(this); |
250 Register dst = (rd.IsSP()) ? temps.AcquireSameSizeAs(rd) : rd; | 250 Register dst = (rd.IsSP()) ? temps.AcquireSameSizeAs(rd) : rd; |
251 | 251 |
252 if (operand.NeedsRelocation(this)) { | 252 if (operand.NeedsRelocation(this)) { |
253 LoadRelocated(dst, operand); | 253 Ldr(dst, operand.immediate()); |
254 | 254 |
255 } else if (operand.IsImmediate()) { | 255 } else if (operand.IsImmediate()) { |
256 // Call the macro assembler for generic immediates. | 256 // Call the macro assembler for generic immediates. |
257 Mov(dst, operand.immediate()); | 257 Mov(dst, operand.ImmediateValue()); |
258 | 258 |
259 } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) { | 259 } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) { |
260 // Emit a shift instruction if moving a shifted register. This operation | 260 // Emit a shift instruction if moving a shifted register. This operation |
261 // could also be achieved using an orr instruction (like orn used by Mvn), | 261 // could also be achieved using an orr instruction (like orn used by Mvn), |
262 // but using a shift instruction makes the disassembly clearer. | 262 // but using a shift instruction makes the disassembly clearer. |
263 EmitShift(dst, operand.reg(), operand.shift(), operand.shift_amount()); | 263 EmitShift(dst, operand.reg(), operand.shift(), operand.shift_amount()); |
264 | 264 |
265 } else if (operand.IsExtendedRegister()) { | 265 } else if (operand.IsExtendedRegister()) { |
266 // Emit an extend instruction if moving an extended register. This handles | 266 // Emit an extend instruction if moving an extended register. This handles |
267 // extend with post-shift operations, too. | 267 // extend with post-shift operations, too. |
(...skipping 23 matching lines...) Expand all Loading... |
291 ASSERT(rd.IsSP()); | 291 ASSERT(rd.IsSP()); |
292 Assembler::mov(rd, dst); | 292 Assembler::mov(rd, dst); |
293 } | 293 } |
294 } | 294 } |
295 | 295 |
296 | 296 |
297 void MacroAssembler::Mvn(const Register& rd, const Operand& operand) { | 297 void MacroAssembler::Mvn(const Register& rd, const Operand& operand) { |
298 ASSERT(allow_macro_instructions_); | 298 ASSERT(allow_macro_instructions_); |
299 | 299 |
300 if (operand.NeedsRelocation(this)) { | 300 if (operand.NeedsRelocation(this)) { |
301 LoadRelocated(rd, operand); | 301 Ldr(rd, operand.immediate()); |
302 mvn(rd, rd); | 302 mvn(rd, rd); |
303 | 303 |
304 } else if (operand.IsImmediate()) { | 304 } else if (operand.IsImmediate()) { |
305 // Call the macro assembler for generic immediates. | 305 // Call the macro assembler for generic immediates. |
306 Mov(rd, ~operand.immediate()); | 306 Mov(rd, ~operand.ImmediateValue()); |
307 | 307 |
308 } else if (operand.IsExtendedRegister()) { | 308 } else if (operand.IsExtendedRegister()) { |
309 // Emit two instructions for the extend case. This differs from Mov, as | 309 // Emit two instructions for the extend case. This differs from Mov, as |
310 // the extend and invert can't be achieved in one instruction. | 310 // the extend and invert can't be achieved in one instruction. |
311 EmitExtendShift(rd, operand.reg(), operand.extend(), | 311 EmitExtendShift(rd, operand.reg(), operand.extend(), |
312 operand.shift_amount()); | 312 operand.shift_amount()); |
313 mvn(rd, rd); | 313 mvn(rd, rd); |
314 | 314 |
315 } else { | 315 } else { |
316 mvn(rd, operand); | 316 mvn(rd, operand); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 | 348 |
349 void MacroAssembler::ConditionalCompareMacro(const Register& rn, | 349 void MacroAssembler::ConditionalCompareMacro(const Register& rn, |
350 const Operand& operand, | 350 const Operand& operand, |
351 StatusFlags nzcv, | 351 StatusFlags nzcv, |
352 Condition cond, | 352 Condition cond, |
353 ConditionalCompareOp op) { | 353 ConditionalCompareOp op) { |
354 ASSERT((cond != al) && (cond != nv)); | 354 ASSERT((cond != al) && (cond != nv)); |
355 if (operand.NeedsRelocation(this)) { | 355 if (operand.NeedsRelocation(this)) { |
356 UseScratchRegisterScope temps(this); | 356 UseScratchRegisterScope temps(this); |
357 Register temp = temps.AcquireX(); | 357 Register temp = temps.AcquireX(); |
358 LoadRelocated(temp, operand); | 358 Ldr(temp, operand.immediate()); |
359 ConditionalCompareMacro(rn, temp, nzcv, cond, op); | 359 ConditionalCompareMacro(rn, temp, nzcv, cond, op); |
360 | 360 |
361 } else if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) || | 361 } else if ((operand.IsShiftedRegister() && (operand.shift_amount() == 0)) || |
362 (operand.IsImmediate() && IsImmConditionalCompare(operand.immediate()))) { | 362 (operand.IsImmediate() && |
| 363 IsImmConditionalCompare(operand.ImmediateValue()))) { |
363 // The immediate can be encoded in the instruction, or the operand is an | 364 // The immediate can be encoded in the instruction, or the operand is an |
364 // unshifted register: call the assembler. | 365 // unshifted register: call the assembler. |
365 ConditionalCompare(rn, operand, nzcv, cond, op); | 366 ConditionalCompare(rn, operand, nzcv, cond, op); |
366 | 367 |
367 } else { | 368 } else { |
368 // The operand isn't directly supported by the instruction: perform the | 369 // The operand isn't directly supported by the instruction: perform the |
369 // operation on a temporary register. | 370 // operation on a temporary register. |
370 UseScratchRegisterScope temps(this); | 371 UseScratchRegisterScope temps(this); |
371 Register temp = temps.AcquireSameSizeAs(rn); | 372 Register temp = temps.AcquireSameSizeAs(rn); |
372 Mov(temp, operand); | 373 Mov(temp, operand); |
373 ConditionalCompare(rn, temp, nzcv, cond, op); | 374 ConditionalCompare(rn, temp, nzcv, cond, op); |
374 } | 375 } |
375 } | 376 } |
376 | 377 |
377 | 378 |
378 void MacroAssembler::Csel(const Register& rd, | 379 void MacroAssembler::Csel(const Register& rd, |
379 const Register& rn, | 380 const Register& rn, |
380 const Operand& operand, | 381 const Operand& operand, |
381 Condition cond) { | 382 Condition cond) { |
382 ASSERT(allow_macro_instructions_); | 383 ASSERT(allow_macro_instructions_); |
383 ASSERT(!rd.IsZero()); | 384 ASSERT(!rd.IsZero()); |
384 ASSERT((cond != al) && (cond != nv)); | 385 ASSERT((cond != al) && (cond != nv)); |
385 if (operand.IsImmediate()) { | 386 if (operand.IsImmediate()) { |
386 // Immediate argument. Handle special cases of 0, 1 and -1 using zero | 387 // Immediate argument. Handle special cases of 0, 1 and -1 using zero |
387 // register. | 388 // register. |
388 int64_t imm = operand.immediate(); | 389 int64_t imm = operand.ImmediateValue(); |
389 Register zr = AppropriateZeroRegFor(rn); | 390 Register zr = AppropriateZeroRegFor(rn); |
390 if (imm == 0) { | 391 if (imm == 0) { |
391 csel(rd, rn, zr, cond); | 392 csel(rd, rn, zr, cond); |
392 } else if (imm == 1) { | 393 } else if (imm == 1) { |
393 csinc(rd, rn, zr, cond); | 394 csinc(rd, rn, zr, cond); |
394 } else if (imm == -1) { | 395 } else if (imm == -1) { |
395 csinv(rd, rn, zr, cond); | 396 csinv(rd, rn, zr, cond); |
396 } else { | 397 } else { |
397 UseScratchRegisterScope temps(this); | 398 UseScratchRegisterScope temps(this); |
398 Register temp = temps.AcquireSameSizeAs(rn); | 399 Register temp = temps.AcquireSameSizeAs(rn); |
399 Mov(temp, operand.immediate()); | 400 Mov(temp, imm); |
400 csel(rd, rn, temp, cond); | 401 csel(rd, rn, temp, cond); |
401 } | 402 } |
402 } else if (operand.IsShiftedRegister() && (operand.shift_amount() == 0)) { | 403 } else if (operand.IsShiftedRegister() && (operand.shift_amount() == 0)) { |
403 // Unshifted register argument. | 404 // Unshifted register argument. |
404 csel(rd, rn, operand.reg(), cond); | 405 csel(rd, rn, operand.reg(), cond); |
405 } else { | 406 } else { |
406 // All other arguments. | 407 // All other arguments. |
407 UseScratchRegisterScope temps(this); | 408 UseScratchRegisterScope temps(this); |
408 Register temp = temps.AcquireSameSizeAs(rn); | 409 Register temp = temps.AcquireSameSizeAs(rn); |
409 Mov(temp, operand); | 410 Mov(temp, operand); |
410 csel(rd, rn, temp, cond); | 411 csel(rd, rn, temp, cond); |
411 } | 412 } |
412 } | 413 } |
413 | 414 |
414 | 415 |
415 void MacroAssembler::AddSubMacro(const Register& rd, | 416 void MacroAssembler::AddSubMacro(const Register& rd, |
416 const Register& rn, | 417 const Register& rn, |
417 const Operand& operand, | 418 const Operand& operand, |
418 FlagsUpdate S, | 419 FlagsUpdate S, |
419 AddSubOp op) { | 420 AddSubOp op) { |
420 if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() && | 421 if (operand.IsZero() && rd.Is(rn) && rd.Is64Bits() && rn.Is64Bits() && |
421 !operand.NeedsRelocation(this) && (S == LeaveFlags)) { | 422 !operand.NeedsRelocation(this) && (S == LeaveFlags)) { |
422 // The instruction would be a nop. Avoid generating useless code. | 423 // The instruction would be a nop. Avoid generating useless code. |
423 return; | 424 return; |
424 } | 425 } |
425 | 426 |
426 if (operand.NeedsRelocation(this)) { | 427 if (operand.NeedsRelocation(this)) { |
427 UseScratchRegisterScope temps(this); | 428 UseScratchRegisterScope temps(this); |
428 Register temp = temps.AcquireX(); | 429 Register temp = temps.AcquireX(); |
429 LoadRelocated(temp, operand); | 430 Ldr(temp, operand.immediate()); |
430 AddSubMacro(rd, rn, temp, S, op); | 431 AddSubMacro(rd, rn, temp, S, op); |
431 } else if ((operand.IsImmediate() && !IsImmAddSub(operand.immediate())) || | 432 } else if ((operand.IsImmediate() && |
432 (rn.IsZero() && !operand.IsShiftedRegister()) || | 433 !IsImmAddSub(operand.ImmediateValue())) || |
| 434 (rn.IsZero() && !operand.IsShiftedRegister()) || |
433 (operand.IsShiftedRegister() && (operand.shift() == ROR))) { | 435 (operand.IsShiftedRegister() && (operand.shift() == ROR))) { |
434 UseScratchRegisterScope temps(this); | 436 UseScratchRegisterScope temps(this); |
435 Register temp = temps.AcquireSameSizeAs(rn); | 437 Register temp = temps.AcquireSameSizeAs(rn); |
436 Mov(temp, operand); | 438 Mov(temp, operand); |
437 AddSub(rd, rn, temp, S, op); | 439 AddSub(rd, rn, temp, S, op); |
438 } else { | 440 } else { |
439 AddSub(rd, rn, operand, S, op); | 441 AddSub(rd, rn, operand, S, op); |
440 } | 442 } |
441 } | 443 } |
442 | 444 |
443 | 445 |
444 void MacroAssembler::AddSubWithCarryMacro(const Register& rd, | 446 void MacroAssembler::AddSubWithCarryMacro(const Register& rd, |
445 const Register& rn, | 447 const Register& rn, |
446 const Operand& operand, | 448 const Operand& operand, |
447 FlagsUpdate S, | 449 FlagsUpdate S, |
448 AddSubWithCarryOp op) { | 450 AddSubWithCarryOp op) { |
449 ASSERT(rd.SizeInBits() == rn.SizeInBits()); | 451 ASSERT(rd.SizeInBits() == rn.SizeInBits()); |
450 UseScratchRegisterScope temps(this); | 452 UseScratchRegisterScope temps(this); |
451 | 453 |
452 if (operand.NeedsRelocation(this)) { | 454 if (operand.NeedsRelocation(this)) { |
453 Register temp = temps.AcquireX(); | 455 Register temp = temps.AcquireX(); |
454 LoadRelocated(temp, operand); | 456 Ldr(temp, operand.immediate()); |
455 AddSubWithCarryMacro(rd, rn, temp, S, op); | 457 AddSubWithCarryMacro(rd, rn, temp, S, op); |
456 | 458 |
457 } else if (operand.IsImmediate() || | 459 } else if (operand.IsImmediate() || |
458 (operand.IsShiftedRegister() && (operand.shift() == ROR))) { | 460 (operand.IsShiftedRegister() && (operand.shift() == ROR))) { |
459 // Add/sub with carry (immediate or ROR shifted register.) | 461 // Add/sub with carry (immediate or ROR shifted register.) |
460 Register temp = temps.AcquireSameSizeAs(rn); | 462 Register temp = temps.AcquireSameSizeAs(rn); |
461 Mov(temp, operand); | 463 Mov(temp, operand); |
462 AddSubWithCarry(rd, rn, temp, S, op); | 464 AddSubWithCarry(rd, rn, temp, S, op); |
463 | 465 |
464 } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) { | 466 } else if (operand.IsShiftedRegister() && (operand.shift_amount() != 0)) { |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1064 } | 1066 } |
1065 } | 1067 } |
1066 | 1068 |
1067 | 1069 |
1068 void MacroAssembler::PushPreamble(Operand total_size) { | 1070 void MacroAssembler::PushPreamble(Operand total_size) { |
1069 if (csp.Is(StackPointer())) { | 1071 if (csp.Is(StackPointer())) { |
1070 // If the current stack pointer is csp, then it must be aligned to 16 bytes | 1072 // If the current stack pointer is csp, then it must be aligned to 16 bytes |
1071 // on entry and the total size of the specified registers must also be a | 1073 // on entry and the total size of the specified registers must also be a |
1072 // multiple of 16 bytes. | 1074 // multiple of 16 bytes. |
1073 if (total_size.IsImmediate()) { | 1075 if (total_size.IsImmediate()) { |
1074 ASSERT((total_size.immediate() % 16) == 0); | 1076 ASSERT((total_size.ImmediateValue() % 16) == 0); |
1075 } | 1077 } |
1076 | 1078 |
1077 // Don't check access size for non-immediate sizes. It's difficult to do | 1079 // Don't check access size for non-immediate sizes. It's difficult to do |
1078 // well, and it will be caught by hardware (or the simulator) anyway. | 1080 // well, and it will be caught by hardware (or the simulator) anyway. |
1079 } else { | 1081 } else { |
1080 // Even if the current stack pointer is not the system stack pointer (csp), | 1082 // Even if the current stack pointer is not the system stack pointer (csp), |
1081 // the system stack pointer will still be modified in order to comply with | 1083 // the system stack pointer will still be modified in order to comply with |
1082 // ABI rules about accessing memory below the system stack pointer. | 1084 // ABI rules about accessing memory below the system stack pointer. |
1083 BumpSystemStackPointer(total_size); | 1085 BumpSystemStackPointer(total_size); |
1084 } | 1086 } |
1085 } | 1087 } |
1086 | 1088 |
1087 | 1089 |
1088 void MacroAssembler::PopPostamble(Operand total_size) { | 1090 void MacroAssembler::PopPostamble(Operand total_size) { |
1089 if (csp.Is(StackPointer())) { | 1091 if (csp.Is(StackPointer())) { |
1090 // If the current stack pointer is csp, then it must be aligned to 16 bytes | 1092 // If the current stack pointer is csp, then it must be aligned to 16 bytes |
1091 // on entry and the total size of the specified registers must also be a | 1093 // on entry and the total size of the specified registers must also be a |
1092 // multiple of 16 bytes. | 1094 // multiple of 16 bytes. |
1093 if (total_size.IsImmediate()) { | 1095 if (total_size.IsImmediate()) { |
1094 ASSERT((total_size.immediate() % 16) == 0); | 1096 ASSERT((total_size.ImmediateValue() % 16) == 0); |
1095 } | 1097 } |
1096 | 1098 |
1097 // Don't check access size for non-immediate sizes. It's difficult to do | 1099 // Don't check access size for non-immediate sizes. It's difficult to do |
1098 // well, and it will be caught by hardware (or the simulator) anyway. | 1100 // well, and it will be caught by hardware (or the simulator) anyway. |
1099 } else if (emit_debug_code()) { | 1101 } else if (emit_debug_code()) { |
1100 // It is safe to leave csp where it is when unwinding the JavaScript stack, | 1102 // It is safe to leave csp where it is when unwinding the JavaScript stack, |
1101 // but if we keep it matching StackPointer, the simulator can detect memory | 1103 // but if we keep it matching StackPointer, the simulator can detect memory |
1102 // accesses in the now-free part of the stack. | 1104 // accesses in the now-free part of the stack. |
1103 SyncSystemStackPointer(); | 1105 SyncSystemStackPointer(); |
1104 } | 1106 } |
1105 } | 1107 } |
1106 | 1108 |
1107 | 1109 |
1108 void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) { | 1110 void MacroAssembler::Poke(const CPURegister& src, const Operand& offset) { |
1109 if (offset.IsImmediate()) { | 1111 if (offset.IsImmediate()) { |
1110 ASSERT(offset.immediate() >= 0); | 1112 ASSERT(offset.ImmediateValue() >= 0); |
1111 } else if (emit_debug_code()) { | 1113 } else if (emit_debug_code()) { |
1112 Cmp(xzr, offset); | 1114 Cmp(xzr, offset); |
1113 Check(le, kStackAccessBelowStackPointer); | 1115 Check(le, kStackAccessBelowStackPointer); |
1114 } | 1116 } |
1115 | 1117 |
1116 Str(src, MemOperand(StackPointer(), offset)); | 1118 Str(src, MemOperand(StackPointer(), offset)); |
1117 } | 1119 } |
1118 | 1120 |
1119 | 1121 |
1120 void MacroAssembler::Peek(const CPURegister& dst, const Operand& offset) { | 1122 void MacroAssembler::Peek(const CPURegister& dst, const Operand& offset) { |
1121 if (offset.IsImmediate()) { | 1123 if (offset.IsImmediate()) { |
1122 ASSERT(offset.immediate() >= 0); | 1124 ASSERT(offset.ImmediateValue() >= 0); |
1123 } else if (emit_debug_code()) { | 1125 } else if (emit_debug_code()) { |
1124 Cmp(xzr, offset); | 1126 Cmp(xzr, offset); |
1125 Check(le, kStackAccessBelowStackPointer); | 1127 Check(le, kStackAccessBelowStackPointer); |
1126 } | 1128 } |
1127 | 1129 |
1128 Ldr(dst, MemOperand(StackPointer(), offset)); | 1130 Ldr(dst, MemOperand(StackPointer(), offset)); |
1129 } | 1131 } |
1130 | 1132 |
1131 | 1133 |
1132 void MacroAssembler::PokePair(const CPURegister& src1, | 1134 void MacroAssembler::PokePair(const CPURegister& src1, |
(...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2062 | 2064 |
2063 if (rmode == RelocInfo::NONE64) { | 2065 if (rmode == RelocInfo::NONE64) { |
2064 // Addresses are 48 bits so we never need to load the upper 16 bits. | 2066 // Addresses are 48 bits so we never need to load the upper 16 bits. |
2065 uint64_t imm = reinterpret_cast<uint64_t>(target); | 2067 uint64_t imm = reinterpret_cast<uint64_t>(target); |
2066 // If we don't use ARM tagged addresses, the 16 higher bits must be 0. | 2068 // If we don't use ARM tagged addresses, the 16 higher bits must be 0. |
2067 ASSERT(((imm >> 48) & 0xffff) == 0); | 2069 ASSERT(((imm >> 48) & 0xffff) == 0); |
2068 movz(temp, (imm >> 0) & 0xffff, 0); | 2070 movz(temp, (imm >> 0) & 0xffff, 0); |
2069 movk(temp, (imm >> 16) & 0xffff, 16); | 2071 movk(temp, (imm >> 16) & 0xffff, 16); |
2070 movk(temp, (imm >> 32) & 0xffff, 32); | 2072 movk(temp, (imm >> 32) & 0xffff, 32); |
2071 } else { | 2073 } else { |
2072 LoadRelocated(temp, Operand(reinterpret_cast<intptr_t>(target), rmode)); | 2074 Ldr(temp, Immediate(reinterpret_cast<intptr_t>(target), rmode)); |
2073 } | 2075 } |
2074 Blr(temp); | 2076 Blr(temp); |
2075 #ifdef DEBUG | 2077 #ifdef DEBUG |
2076 AssertSizeOfCodeGeneratedSince(&start_call, CallSize(target, rmode)); | 2078 AssertSizeOfCodeGeneratedSince(&start_call, CallSize(target, rmode)); |
2077 #endif | 2079 #endif |
2078 } | 2080 } |
2079 | 2081 |
2080 | 2082 |
2081 void MacroAssembler::Call(Handle<Code> code, | 2083 void MacroAssembler::Call(Handle<Code> code, |
2082 RelocInfo::Mode rmode, | 2084 RelocInfo::Mode rmode, |
(...skipping 3083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5166 Code * stub) { | 5168 Code * stub) { |
5167 Label start; | 5169 Label start; |
5168 __ bind(&start); | 5170 __ bind(&start); |
5169 // When the stub is called, the sequence is replaced with the young sequence | 5171 // When the stub is called, the sequence is replaced with the young sequence |
5170 // (as in EmitFrameSetupForCodeAgePatching). After the code is replaced, the | 5172 // (as in EmitFrameSetupForCodeAgePatching). After the code is replaced, the |
5171 // stub jumps to &start, stored in x0. The young sequence does not call the | 5173 // stub jumps to &start, stored in x0. The young sequence does not call the |
5172 // stub so there is no infinite loop here. | 5174 // stub so there is no infinite loop here. |
5173 // | 5175 // |
5174 // A branch (br) is used rather than a call (blr) because this code replaces | 5176 // A branch (br) is used rather than a call (blr) because this code replaces |
5175 // the frame setup code that would normally preserve lr. | 5177 // the frame setup code that would normally preserve lr. |
5176 __ LoadLiteral(ip0, kCodeAgeStubEntryOffset); | 5178 __ ldr_pcrel(ip0, kCodeAgeStubEntryOffset >> kLoadLiteralScaleLog2); |
5177 __ adr(x0, &start); | 5179 __ adr(x0, &start); |
5178 __ br(ip0); | 5180 __ br(ip0); |
5179 // IsCodeAgeSequence in codegen-arm64.cc assumes that the code generated up | 5181 // IsCodeAgeSequence in codegen-arm64.cc assumes that the code generated up |
5180 // until now (kCodeAgeStubEntryOffset) is the same for all code age sequences. | 5182 // until now (kCodeAgeStubEntryOffset) is the same for all code age sequences. |
5181 __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeStubEntryOffset); | 5183 __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeStubEntryOffset); |
5182 if (stub) { | 5184 if (stub) { |
5183 __ dc64(reinterpret_cast<uint64_t>(stub->instruction_start())); | 5185 __ dc64(reinterpret_cast<uint64_t>(stub->instruction_start())); |
5184 __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength); | 5186 __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength); |
5185 } | 5187 } |
5186 } | 5188 } |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5292 } | 5294 } |
5293 } | 5295 } |
5294 | 5296 |
5295 | 5297 |
5296 #undef __ | 5298 #undef __ |
5297 | 5299 |
5298 | 5300 |
5299 } } // namespace v8::internal | 5301 } } // namespace v8::internal |
5300 | 5302 |
5301 #endif // V8_TARGET_ARCH_ARM64 | 5303 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |