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 3// found in the LICENSE file. 4 5#ifndef INCLUDED_FROM_MACRO_ASSEMBLER_H 6#error This header must be included via macro-assembler.h 7#endif 8 9#ifndef V8_CODEGEN_S390_MACRO_ASSEMBLER_S390_H_ 10#define V8_CODEGEN_S390_MACRO_ASSEMBLER_S390_H_ 11 12#include "src/codegen/bailout-reason.h" 13#include "src/codegen/s390/assembler-s390.h" 14#include "src/common/globals.h" 15#include "src/objects/contexts.h" 16 17namespace v8 { 18namespace internal { 19 20enum class StackLimitKind { kInterruptStackLimit, kRealStackLimit }; 21 22// ---------------------------------------------------------------------------- 23// Static helper functions 24 25// Generate a MemOperand for loading a field from an object. 26inline MemOperand FieldMemOperand(Register object, int offset) { 27 return MemOperand(object, offset - kHeapObjectTag); 28} 29 30// Generate a MemOperand for loading a field from an object. 31inline MemOperand FieldMemOperand(Register object, Register index, int offset) { 32 return MemOperand(object, index, offset - kHeapObjectTag); 33} 34 35enum LinkRegisterStatus { kLRHasNotBeenSaved, kLRHasBeenSaved }; 36 37Register GetRegisterThatIsNotOneOf(Register reg1, Register reg2 = no_reg, 38 Register reg3 = no_reg, 39 Register reg4 = no_reg, 40 Register reg5 = no_reg, 41 Register reg6 = no_reg); 42 43class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase { 44 public: 45 using TurboAssemblerBase::TurboAssemblerBase; 46 47 void CallBuiltin(Builtin builtin); 48 void TailCallBuiltin(Builtin builtin); 49 void AtomicCmpExchangeHelper(Register addr, Register output, 50 Register old_value, Register new_value, 51 int start, int end, int shift_amount, int offset, 52 Register temp0, Register temp1); 53 void AtomicCmpExchangeU8(Register addr, Register output, Register old_value, 54 Register new_value, Register temp0, Register temp1); 55 void AtomicCmpExchangeU16(Register addr, Register output, Register old_value, 56 Register new_value, Register temp0, Register temp1); 57 void AtomicExchangeHelper(Register addr, Register value, Register output, 58 int start, int end, int shift_amount, int offset, 59 Register scratch); 60 void AtomicExchangeU8(Register addr, Register value, Register output, 61 Register scratch); 62 void AtomicExchangeU16(Register addr, Register value, Register output, 63 Register scratch); 64 65 void DoubleMax(DoubleRegister result_reg, DoubleRegister left_reg, 66 DoubleRegister right_reg); 67 void DoubleMin(DoubleRegister result_reg, DoubleRegister left_reg, 68 DoubleRegister right_reg); 69 void FloatMax(DoubleRegister result_reg, DoubleRegister left_reg, 70 DoubleRegister right_reg); 71 void FloatMin(DoubleRegister result_reg, DoubleRegister left_reg, 72 DoubleRegister right_reg); 73 void CeilF32(DoubleRegister dst, DoubleRegister src); 74 void CeilF64(DoubleRegister dst, DoubleRegister src); 75 void FloorF32(DoubleRegister dst, DoubleRegister src); 76 void FloorF64(DoubleRegister dst, DoubleRegister src); 77 void TruncF32(DoubleRegister dst, DoubleRegister src); 78 void TruncF64(DoubleRegister dst, DoubleRegister src); 79 void NearestIntF32(DoubleRegister dst, DoubleRegister src); 80 void NearestIntF64(DoubleRegister dst, DoubleRegister src); 81 82 void LoadFromConstantsTable(Register destination, int constant_index) final; 83 void LoadRootRegisterOffset(Register destination, intptr_t offset) final; 84 void LoadRootRelative(Register destination, int32_t offset) final; 85 86 // Jump, Call, and Ret pseudo instructions implementing inter-working. 87 void Jump(Register target, Condition cond = al); 88 void Jump(Address target, RelocInfo::Mode rmode, Condition cond = al); 89 void Jump(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al); 90 void Jump(const ExternalReference& reference); 91 // Jump the register contains a smi. 92 inline void JumpIfSmi(Register value, Label* smi_label) { 93 TestIfSmi(value); 94 beq(smi_label /*, cr0*/); // branch if SMI 95 } 96 void JumpIfEqual(Register x, int32_t y, Label* dest); 97 void JumpIfLessThan(Register x, int32_t y, Label* dest); 98 99 void LoadMap(Register destination, Register object); 100 101 void Call(Register target); 102 void Call(Address target, RelocInfo::Mode rmode, Condition cond = al); 103 void Call(Handle<Code> code, RelocInfo::Mode rmode = RelocInfo::CODE_TARGET, 104 Condition cond = al); 105 void Ret() { b(r14); } 106 void Ret(Condition cond) { b(cond, r14); } 107 108 void CallForDeoptimization(Builtin target, int deopt_id, Label* exit, 109 DeoptimizeKind kind, Label* ret, 110 Label* jump_deoptimization_entry_label); 111 112 // Emit code to discard a non-negative number of pointer-sized elements 113 // from the stack, clobbering only the sp register. 114 void Drop(int count); 115 void Drop(Register count, Register scratch = r0); 116 117 void Ret(int drop) { 118 Drop(drop); 119 Ret(); 120 } 121 122 void Call(Label* target); 123 124 // Load the builtin given by the Smi in |builtin_index| into the same 125 // register. 126 void LoadEntryFromBuiltinIndex(Register builtin_index); 127 void LoadEntryFromBuiltin(Builtin builtin, Register destination); 128 MemOperand EntryFromBuiltinAsOperand(Builtin builtin); 129 void LoadCodeObjectEntry(Register destination, Register code_object); 130 void CallCodeObject(Register code_object); 131 void JumpCodeObject(Register code_object, 132 JumpMode jump_mode = JumpMode::kJump); 133 134 void CallBuiltinByIndex(Register builtin_index); 135 136 // Register move. May do nothing if the registers are identical. 137 void Move(Register dst, Smi smi) { LoadSmiLiteral(dst, smi); } 138 void Move(Register dst, Handle<HeapObject> source, 139 RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT); 140 void Move(Register dst, ExternalReference reference); 141 void Move(Register dst, const MemOperand& src); 142 void Move(Register dst, Register src, Condition cond = al); 143 void Move(DoubleRegister dst, DoubleRegister src); 144 145 void MoveChar(const MemOperand& opnd1, const MemOperand& opnd2, 146 const Operand& length); 147 148 void CompareLogicalChar(const MemOperand& opnd1, const MemOperand& opnd2, 149 const Operand& length); 150 151 void ExclusiveOrChar(const MemOperand& opnd1, const MemOperand& opnd2, 152 const Operand& length); 153 154 void RotateInsertSelectBits(Register dst, Register src, 155 const Operand& startBit, const Operand& endBit, 156 const Operand& shiftAmt, bool zeroBits); 157 158 void BranchRelativeOnIdxHighP(Register dst, Register inc, Label* L); 159 160 void MaybeSaveRegisters(RegList registers); 161 void MaybeRestoreRegisters(RegList registers); 162 163 void CallEphemeronKeyBarrier(Register object, Register slot_address, 164 SaveFPRegsMode fp_mode); 165 166 void CallRecordWriteStubSaveRegisters( 167 Register object, Register slot_address, 168 RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, 169 StubCallMode mode = StubCallMode::kCallBuiltinPointer); 170 void CallRecordWriteStub( 171 Register object, Register slot_address, 172 RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, 173 StubCallMode mode = StubCallMode::kCallBuiltinPointer); 174 175 void MultiPush(RegList regs, Register location = sp); 176 void MultiPop(RegList regs, Register location = sp); 177 178 void MultiPushDoubles(DoubleRegList dregs, Register location = sp); 179 void MultiPopDoubles(DoubleRegList dregs, Register location = sp); 180 181 void MultiPushV128(DoubleRegList dregs, Register scratch, 182 Register location = sp); 183 void MultiPopV128(DoubleRegList dregs, Register scratch, 184 Register location = sp); 185 186 void MultiPushF64OrV128(DoubleRegList dregs, Register scratch, 187 Register location = sp); 188 void MultiPopF64OrV128(DoubleRegList dregs, Register scratch, 189 Register location = sp); 190 191 // Calculate how much stack space (in bytes) are required to store caller 192 // registers excluding those specified in the arguments. 193 int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode, 194 Register exclusion1 = no_reg, 195 Register exclusion2 = no_reg, 196 Register exclusion3 = no_reg) const; 197 198 // Push caller saved registers on the stack, and return the number of bytes 199 // stack pointer is adjusted. 200 int PushCallerSaved(SaveFPRegsMode fp_mode, Register scratch, 201 Register exclusion1 = no_reg, 202 Register exclusion2 = no_reg, 203 Register exclusion3 = no_reg); 204 // Restore caller saved registers from the stack, and return the number of 205 // bytes stack pointer is adjusted. 206 int PopCallerSaved(SaveFPRegsMode fp_mode, Register scratch, 207 Register exclusion1 = no_reg, Register exclusion2 = no_reg, 208 Register exclusion3 = no_reg); 209 210 // Load an object from the root table. 211 void LoadRoot(Register destination, RootIndex index) override { 212 LoadRoot(destination, index, al); 213 } 214 void LoadRoot(Register destination, RootIndex index, Condition cond); 215 //-------------------------------------------------------------------------- 216 // S390 Macro Assemblers for Instructions 217 //-------------------------------------------------------------------------- 218 219 // Arithmetic Operations 220 221 // Add (Register - Immediate) 222 void AddS32(Register dst, const Operand& imm); 223 void AddS64(Register dst, const Operand& imm); 224 void AddS32(Register dst, Register src, const Operand& imm); 225 void AddS64(Register dst, Register src, const Operand& imm); 226 void AddS32(Register dst, Register src, int32_t imm); 227 void AddS64(Register dst, Register src, int32_t imm); 228 229 // Add (Register - Register) 230 void AddS32(Register dst, Register src); 231 void AddS64(Register dst, Register src); 232 void AddS32(Register dst, Register src1, Register src2); 233 void AddS64(Register dst, Register src1, Register src2); 234 235 // Add (Register - Mem) 236 void AddS32(Register dst, const MemOperand& opnd); 237 void AddS64(Register dst, const MemOperand& opnd); 238 239 // Add (Mem - Immediate) 240 void AddS32(const MemOperand& opnd, const Operand& imm); 241 void AddS64(const MemOperand& opnd, const Operand& imm); 242 243 // Add Logical (Register - Register) 244 void AddU32(Register dst, Register src1, Register src2); 245 246 // Add Logical (Register - Immediate) 247 void AddU32(Register dst, const Operand& imm); 248 void AddU64(Register dst, const Operand& imm); 249 void AddU64(Register dst, Register src1, Register src2); 250 251 // Add Logical (Register - Mem) 252 void AddU32(Register dst, const MemOperand& opnd); 253 void AddU64(Register dst, const MemOperand& opnd); 254 255 // Subtract (Register - Immediate) 256 void SubS32(Register dst, const Operand& imm); 257 void SubS64(Register dst, const Operand& imm); 258 void SubS32(Register dst, Register src, const Operand& imm); 259 void SubS64(Register dst, Register src, const Operand& imm); 260 void SubS32(Register dst, Register src, int32_t imm); 261 void SubS64(Register dst, Register src, int32_t imm); 262 263 // Subtract (Register - Register) 264 void SubS32(Register dst, Register src); 265 void SubS64(Register dst, Register src); 266 void SubS32(Register dst, Register src1, Register src2); 267 void SubS64(Register dst, Register src1, Register src2); 268 269 // Subtract (Register - Mem) 270 void SubS32(Register dst, const MemOperand& opnd); 271 void SubS64(Register dst, const MemOperand& opnd); 272 void LoadAndSub32(Register dst, Register src, const MemOperand& opnd); 273 void LoadAndSub64(Register dst, Register src, const MemOperand& opnd); 274 275 // Subtract Logical (Register - Mem) 276 void SubU32(Register dst, const MemOperand& opnd); 277 void SubU64(Register dst, const MemOperand& opnd); 278 // Subtract Logical 32-bit 279 void SubU32(Register dst, Register src1, Register src2); 280 281 // Multiply 282 void MulS64(Register dst, const Operand& opnd); 283 void MulS64(Register dst, Register src); 284 void MulS64(Register dst, const MemOperand& opnd); 285 void MulS64(Register dst, Register src1, Register src2) { 286 if (CpuFeatures::IsSupported(MISC_INSTR_EXT2)) { 287 msgrkc(dst, src1, src2); 288 } else { 289 if (dst == src2) { 290 MulS64(dst, src1); 291 } else if (dst == src1) { 292 MulS64(dst, src2); 293 } else { 294 mov(dst, src1); 295 MulS64(dst, src2); 296 } 297 } 298 } 299 300 void MulS32(Register dst, const MemOperand& src1); 301 void MulS32(Register dst, Register src1); 302 void MulS32(Register dst, const Operand& src1); 303 void MulS32(Register dst, Register src1, Register src2) { 304 if (CpuFeatures::IsSupported(MISC_INSTR_EXT2)) { 305 msrkc(dst, src1, src2); 306 } else { 307 if (dst == src2) { 308 MulS32(dst, src1); 309 } else if (dst == src1) { 310 MulS32(dst, src2); 311 } else { 312 mov(dst, src1); 313 MulS32(dst, src2); 314 } 315 } 316 } 317 318 void MulHighS32(Register dst, Register src1, const MemOperand& src2); 319 void MulHighS32(Register dst, Register src1, Register src2); 320 void MulHighS32(Register dst, Register src1, const Operand& src2); 321 void MulHighU32(Register dst, Register src1, const MemOperand& src2); 322 void MulHighU32(Register dst, Register src1, Register src2); 323 void MulHighU32(Register dst, Register src1, const Operand& src2); 324 void Mul32WithOverflowIfCCUnequal(Register dst, Register src1, 325 const MemOperand& src2); 326 void Mul32WithOverflowIfCCUnequal(Register dst, Register src1, Register src2); 327 void Mul32WithOverflowIfCCUnequal(Register dst, Register src1, 328 const Operand& src2); 329 // Divide 330 void DivS32(Register dst, Register src1, const MemOperand& src2); 331 void DivS32(Register dst, Register src1, Register src2); 332 void DivU32(Register dst, Register src1, const MemOperand& src2); 333 void DivU32(Register dst, Register src1, Register src2); 334 void DivS64(Register dst, Register src1, const MemOperand& src2); 335 void DivS64(Register dst, Register src1, Register src2); 336 void DivU64(Register dst, Register src1, const MemOperand& src2); 337 void DivU64(Register dst, Register src1, Register src2); 338 339 // Mod 340 void ModS32(Register dst, Register src1, const MemOperand& src2); 341 void ModS32(Register dst, Register src1, Register src2); 342 void ModU32(Register dst, Register src1, const MemOperand& src2); 343 void ModU32(Register dst, Register src1, Register src2); 344 void ModS64(Register dst, Register src1, const MemOperand& src2); 345 void ModS64(Register dst, Register src1, Register src2); 346 void ModU64(Register dst, Register src1, const MemOperand& src2); 347 void ModU64(Register dst, Register src1, Register src2); 348 349 // Square root 350 void Sqrt(DoubleRegister result, DoubleRegister input); 351 void Sqrt(DoubleRegister result, const MemOperand& input); 352 353 // Compare 354 void CmpS32(Register src1, Register src2); 355 void CmpS64(Register src1, Register src2); 356 void CmpS32(Register dst, const Operand& opnd); 357 void CmpS64(Register dst, const Operand& opnd); 358 void CmpS32(Register dst, const MemOperand& opnd); 359 void CmpS64(Register dst, const MemOperand& opnd); 360 void CmpAndSwap(Register old_val, Register new_val, const MemOperand& opnd); 361 void CmpAndSwap64(Register old_val, Register new_val, const MemOperand& opnd); 362 // TODO(john.yan): remove this 363 template <class T> 364 void CmpP(Register src1, T src2) { 365 CmpS64(src1, src2); 366 } 367 368 // Compare Logical 369 void CmpU32(Register src1, Register src2); 370 void CmpU64(Register src1, Register src2); 371 void CmpU32(Register src1, const Operand& opnd); 372 void CmpU64(Register src1, const Operand& opnd); 373 void CmpU32(Register dst, const MemOperand& opnd); 374 void CmpU64(Register dst, const MemOperand& opnd); 375 376 // Load 377 void LoadU64(Register dst, const MemOperand& mem, Register scratch = no_reg); 378 void LoadS32(Register dst, const MemOperand& opnd, Register scratch = no_reg); 379 void LoadS32(Register dst, Register src); 380 void LoadU32(Register dst, const MemOperand& opnd, Register scratch = no_reg); 381 void LoadU32(Register dst, Register src); 382 void LoadU16(Register dst, const MemOperand& opnd); 383 void LoadU16(Register dst, Register src); 384 void LoadS16(Register dst, Register src); 385 void LoadS16(Register dst, const MemOperand& mem, Register scratch = no_reg); 386 void LoadS8(Register dst, const MemOperand& opnd); 387 void LoadS8(Register dst, Register src); 388 void LoadU8(Register dst, const MemOperand& opnd); 389 void LoadU8(Register dst, Register src); 390 void LoadV128(Simd128Register dst, const MemOperand& mem, Register scratch); 391 void LoadF64(DoubleRegister dst, const MemOperand& opnd); 392 void LoadF32(DoubleRegister dst, const MemOperand& opnd); 393 // LE Load 394 void LoadU64LE(Register dst, const MemOperand& mem, 395 Register scratch = no_reg); 396 void LoadS32LE(Register dst, const MemOperand& opnd, 397 Register scratch = no_reg); 398 void LoadU32LE(Register dst, const MemOperand& opnd, 399 Register scratch = no_reg); 400 void LoadU16LE(Register dst, const MemOperand& opnd); 401 void LoadS16LE(Register dst, const MemOperand& opnd); 402 void LoadV128LE(DoubleRegister dst, const MemOperand& mem, Register scratch0, 403 Register scratch1); 404 void LoadF64LE(DoubleRegister dst, const MemOperand& opnd, Register scratch); 405 void LoadF32LE(DoubleRegister dst, const MemOperand& opnd, Register scratch); 406 // Vector LE Load and Transform instructions. 407 void LoadAndSplat64x2LE(Simd128Register dst, const MemOperand& mem, 408 Register scratch); 409 void LoadAndSplat32x4LE(Simd128Register dst, const MemOperand& mem, 410 Register scratch); 411 void LoadAndSplat16x8LE(Simd128Register dst, const MemOperand& me, 412 Register scratch); 413 void LoadAndSplat8x16LE(Simd128Register dst, const MemOperand& mem, 414 Register scratch); 415 void LoadAndExtend8x8ULE(Simd128Register dst, const MemOperand& mem, 416 Register scratch); 417 void LoadAndExtend8x8SLE(Simd128Register dst, const MemOperand& mem, 418 Register scratch); 419 void LoadAndExtend16x4ULE(Simd128Register dst, const MemOperand& mem, 420 Register scratch); 421 void LoadAndExtend16x4SLE(Simd128Register dst, const MemOperand& mem, 422 Register scratch); 423 void LoadAndExtend32x2ULE(Simd128Register dst, const MemOperand& mem, 424 Register scratch); 425 void LoadAndExtend32x2SLE(Simd128Register dst, const MemOperand& mem, 426 Register scratch); 427 void LoadV32ZeroLE(Simd128Register dst, const MemOperand& mem, 428 Register scratch); 429 void LoadV64ZeroLE(Simd128Register dst, const MemOperand& mem, 430 Register scratch); 431 void LoadLane8LE(Simd128Register dst, const MemOperand& mem, int lane, 432 Register scratch); 433 void LoadLane16LE(Simd128Register dst, const MemOperand& mem, int lane, 434 Register scratch); 435 void LoadLane32LE(Simd128Register dst, const MemOperand& mem, int lane, 436 Register scratch); 437 void LoadLane64LE(Simd128Register dst, const MemOperand& mem, int lane, 438 Register scratch); 439 void StoreLane8LE(Simd128Register src, const MemOperand& mem, int lane, 440 Register scratch); 441 void StoreLane16LE(Simd128Register src, const MemOperand& mem, int lane, 442 Register scratch); 443 void StoreLane32LE(Simd128Register src, const MemOperand& mem, int lane, 444 Register scratch); 445 void StoreLane64LE(Simd128Register src, const MemOperand& mem, int lane, 446 Register scratch); 447 448 // Load And Test 449 void LoadAndTest32(Register dst, Register src); 450 void LoadAndTestP(Register dst, Register src); 451 452 void LoadAndTest32(Register dst, const MemOperand& opnd); 453 void LoadAndTestP(Register dst, const MemOperand& opnd); 454 455 // Store 456 void StoreU64(const MemOperand& mem, const Operand& opnd, 457 Register scratch = no_reg); 458 void StoreU64(Register src, const MemOperand& mem, Register scratch = no_reg); 459 void StoreU32(Register src, const MemOperand& mem, Register scratch = no_reg); 460 461 void StoreU16(Register src, const MemOperand& mem, Register scratch = r0); 462 void StoreU8(Register src, const MemOperand& mem, Register scratch = r0); 463 void StoreF64(DoubleRegister dst, const MemOperand& opnd); 464 void StoreF32(DoubleRegister dst, const MemOperand& opnd); 465 void StoreV128(Simd128Register src, const MemOperand& mem, Register scratch); 466 467 // Store LE 468 void StoreU64LE(Register src, const MemOperand& mem, 469 Register scratch = no_reg); 470 void StoreU32LE(Register src, const MemOperand& mem, 471 Register scratch = no_reg); 472 473 void StoreU16LE(Register src, const MemOperand& mem, Register scratch = r0); 474 void StoreF64LE(DoubleRegister src, const MemOperand& opnd, Register scratch); 475 void StoreF32LE(DoubleRegister src, const MemOperand& opnd, Register scratch); 476 void StoreV128LE(Simd128Register src, const MemOperand& mem, 477 Register scratch1, Register scratch2); 478 479 void AddF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 480 void SubF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 481 void MulF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 482 void DivF32(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 483 484 void AddF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 485 void SubF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 486 void MulF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 487 void DivF64(DoubleRegister dst, DoubleRegister lhs, DoubleRegister rhs); 488 489 void AddFloat32(DoubleRegister dst, const MemOperand& opnd, 490 DoubleRegister scratch); 491 void AddFloat64(DoubleRegister dst, const MemOperand& opnd, 492 DoubleRegister scratch); 493 void SubFloat32(DoubleRegister dst, const MemOperand& opnd, 494 DoubleRegister scratch); 495 void SubFloat64(DoubleRegister dst, const MemOperand& opnd, 496 DoubleRegister scratch); 497 void MulFloat32(DoubleRegister dst, const MemOperand& opnd, 498 DoubleRegister scratch); 499 void MulFloat64(DoubleRegister dst, const MemOperand& opnd, 500 DoubleRegister scratch); 501 void DivFloat32(DoubleRegister dst, const MemOperand& opnd, 502 DoubleRegister scratch); 503 void DivFloat64(DoubleRegister dst, const MemOperand& opnd, 504 DoubleRegister scratch); 505 void LoadF32AsF64(DoubleRegister dst, const MemOperand& opnd, 506 DoubleRegister scratch); 507 508 // Load On Condition 509 void LoadOnConditionP(Condition cond, Register dst, Register src); 510 511 void LoadPositiveP(Register result, Register input); 512 void LoadPositive32(Register result, Register input); 513 514 void Branch(Condition c, const Operand& opnd); 515 void BranchOnCount(Register r1, Label* l); 516 517 // Shifts 518 void ShiftLeftU32(Register dst, Register src, Register val, 519 const Operand& val2 = Operand::Zero()); 520 void ShiftLeftU32(Register dst, Register src, const Operand& val); 521 void ShiftLeftU64(Register dst, Register src, Register val, 522 const Operand& val2 = Operand::Zero()); 523 void ShiftLeftU64(Register dst, Register src, const Operand& val); 524 void ShiftRightU32(Register dst, Register src, Register val, 525 const Operand& val2 = Operand::Zero()); 526 void ShiftRightU32(Register dst, Register src, const Operand& val); 527 void ShiftRightU64(Register dst, Register src, Register val, 528 const Operand& val2 = Operand::Zero()); 529 void ShiftRightU64(Register dst, Register src, const Operand& val); 530 void ShiftRightS32(Register dst, Register src, Register shift, 531 const Operand& val2 = Operand::Zero()); 532 void ShiftRightS32(Register dst, Register src, const Operand& val); 533 void ShiftRightS64(Register dst, Register src, Register shift, 534 const Operand& val2 = Operand::Zero()); 535 void ShiftRightS64(Register dst, Register src, const Operand& val); 536 537 void ClearRightImm(Register dst, Register src, const Operand& val); 538 539 // Bitwise operations 540 void And(Register dst, Register src); 541 void AndP(Register dst, Register src); 542 void And(Register dst, Register src1, Register src2); 543 void AndP(Register dst, Register src1, Register src2); 544 void And(Register dst, const MemOperand& opnd); 545 void AndP(Register dst, const MemOperand& opnd); 546 void And(Register dst, const Operand& opnd); 547 void AndP(Register dst, const Operand& opnd); 548 void And(Register dst, Register src, const Operand& opnd); 549 void AndP(Register dst, Register src, const Operand& opnd); 550 void Or(Register dst, Register src); 551 void OrP(Register dst, Register src); 552 void Or(Register dst, Register src1, Register src2); 553 void OrP(Register dst, Register src1, Register src2); 554 void Or(Register dst, const MemOperand& opnd); 555 void OrP(Register dst, const MemOperand& opnd); 556 void Or(Register dst, const Operand& opnd); 557 void OrP(Register dst, const Operand& opnd); 558 void Or(Register dst, Register src, const Operand& opnd); 559 void OrP(Register dst, Register src, const Operand& opnd); 560 void Xor(Register dst, Register src); 561 void XorP(Register dst, Register src); 562 void Xor(Register dst, Register src1, Register src2); 563 void XorP(Register dst, Register src1, Register src2); 564 void Xor(Register dst, const MemOperand& opnd); 565 void XorP(Register dst, const MemOperand& opnd); 566 void Xor(Register dst, const Operand& opnd); 567 void XorP(Register dst, const Operand& opnd); 568 void Xor(Register dst, Register src, const Operand& opnd); 569 void XorP(Register dst, Register src, const Operand& opnd); 570 void Popcnt32(Register dst, Register src); 571 void Not32(Register dst, Register src = no_reg); 572 void Not64(Register dst, Register src = no_reg); 573 void NotP(Register dst, Register src = no_reg); 574 575#ifdef V8_TARGET_ARCH_S390X 576 void Popcnt64(Register dst, Register src); 577#endif 578 579 void mov(Register dst, const Operand& src); 580 void mov(Register dst, Register src); 581 582 void CleanUInt32(Register x) { 583#ifdef V8_TARGET_ARCH_S390X 584 llgfr(x, x); 585#endif 586 } 587 588 void push(DoubleRegister src) { 589 lay(sp, MemOperand(sp, -kSystemPointerSize)); 590 StoreF64(src, MemOperand(sp)); 591 } 592 593 void push(Register src) { 594 lay(sp, MemOperand(sp, -kSystemPointerSize)); 595 StoreU64(src, MemOperand(sp)); 596 } 597 598 void pop(DoubleRegister dst) { 599 LoadF64(dst, MemOperand(sp)); 600 la(sp, MemOperand(sp, kSystemPointerSize)); 601 } 602 603 void pop(Register dst) { 604 LoadU64(dst, MemOperand(sp)); 605 la(sp, MemOperand(sp, kSystemPointerSize)); 606 } 607 608 void pop() { la(sp, MemOperand(sp, kSystemPointerSize)); } 609 610 void Push(Register src) { push(src); } 611 612 // Push a handle. 613 void Push(Handle<HeapObject> handle); 614 void Push(Smi smi); 615 616 // Push two registers. Pushes leftmost register first (to highest address). 617 void Push(Register src1, Register src2) { 618 lay(sp, MemOperand(sp, -kSystemPointerSize * 2)); 619 StoreU64(src1, MemOperand(sp, kSystemPointerSize)); 620 StoreU64(src2, MemOperand(sp, 0)); 621 } 622 623 // Push three registers. Pushes leftmost register first (to highest address). 624 void Push(Register src1, Register src2, Register src3) { 625 lay(sp, MemOperand(sp, -kSystemPointerSize * 3)); 626 StoreU64(src1, MemOperand(sp, kSystemPointerSize * 2)); 627 StoreU64(src2, MemOperand(sp, kSystemPointerSize)); 628 StoreU64(src3, MemOperand(sp, 0)); 629 } 630 631 // Push four registers. Pushes leftmost register first (to highest address). 632 void Push(Register src1, Register src2, Register src3, Register src4) { 633 lay(sp, MemOperand(sp, -kSystemPointerSize * 4)); 634 StoreU64(src1, MemOperand(sp, kSystemPointerSize * 3)); 635 StoreU64(src2, MemOperand(sp, kSystemPointerSize * 2)); 636 StoreU64(src3, MemOperand(sp, kSystemPointerSize)); 637 StoreU64(src4, MemOperand(sp, 0)); 638 } 639 640 // Push five registers. Pushes leftmost register first (to highest address). 641 void Push(Register src1, Register src2, Register src3, Register src4, 642 Register src5) { 643 DCHECK(src1 != src2); 644 DCHECK(src1 != src3); 645 DCHECK(src2 != src3); 646 DCHECK(src1 != src4); 647 DCHECK(src2 != src4); 648 DCHECK(src3 != src4); 649 DCHECK(src1 != src5); 650 DCHECK(src2 != src5); 651 DCHECK(src3 != src5); 652 DCHECK(src4 != src5); 653 654 lay(sp, MemOperand(sp, -kSystemPointerSize * 5)); 655 StoreU64(src1, MemOperand(sp, kSystemPointerSize * 4)); 656 StoreU64(src2, MemOperand(sp, kSystemPointerSize * 3)); 657 StoreU64(src3, MemOperand(sp, kSystemPointerSize * 2)); 658 StoreU64(src4, MemOperand(sp, kSystemPointerSize)); 659 StoreU64(src5, MemOperand(sp, 0)); 660 } 661 662 enum PushArrayOrder { kNormal, kReverse }; 663 void PushArray(Register array, Register size, Register scratch, 664 Register scratch2, PushArrayOrder order = kNormal); 665 666 void Pop(Register dst) { pop(dst); } 667 668 // Pop two registers. Pops rightmost register first (from lower address). 669 void Pop(Register src1, Register src2) { 670 LoadU64(src2, MemOperand(sp, 0)); 671 LoadU64(src1, MemOperand(sp, kSystemPointerSize)); 672 la(sp, MemOperand(sp, 2 * kSystemPointerSize)); 673 } 674 675 // Pop three registers. Pops rightmost register first (from lower address). 676 void Pop(Register src1, Register src2, Register src3) { 677 LoadU64(src3, MemOperand(sp, 0)); 678 LoadU64(src2, MemOperand(sp, kSystemPointerSize)); 679 LoadU64(src1, MemOperand(sp, 2 * kSystemPointerSize)); 680 la(sp, MemOperand(sp, 3 * kSystemPointerSize)); 681 } 682 683 // Pop four registers. Pops rightmost register first (from lower address). 684 void Pop(Register src1, Register src2, Register src3, Register src4) { 685 LoadU64(src4, MemOperand(sp, 0)); 686 LoadU64(src3, MemOperand(sp, kSystemPointerSize)); 687 LoadU64(src2, MemOperand(sp, 2 * kSystemPointerSize)); 688 LoadU64(src1, MemOperand(sp, 3 * kSystemPointerSize)); 689 la(sp, MemOperand(sp, 4 * kSystemPointerSize)); 690 } 691 692 // Pop five registers. Pops rightmost register first (from lower address). 693 void Pop(Register src1, Register src2, Register src3, Register src4, 694 Register src5) { 695 LoadU64(src5, MemOperand(sp, 0)); 696 LoadU64(src4, MemOperand(sp, kSystemPointerSize)); 697 LoadU64(src3, MemOperand(sp, 2 * kSystemPointerSize)); 698 LoadU64(src2, MemOperand(sp, 3 * kSystemPointerSize)); 699 LoadU64(src1, MemOperand(sp, 4 * kSystemPointerSize)); 700 la(sp, MemOperand(sp, 5 * kSystemPointerSize)); 701 } 702 703 // Push a fixed frame, consisting of lr, fp, constant pool. 704 void PushCommonFrame(Register marker_reg = no_reg); 705 706 // Push a standard frame, consisting of lr, fp, constant pool, 707 // context and JS function 708 void PushStandardFrame(Register function_reg); 709 710 void PopCommonFrame(Register marker_reg = no_reg); 711 712 // Restore caller's frame pointer and return address prior to being 713 // overwritten by tail call stack preparation. 714 void RestoreFrameStateForTailCall(); 715 716 void InitializeRootRegister() { 717 ExternalReference isolate_root = ExternalReference::isolate_root(isolate()); 718 mov(kRootRegister, Operand(isolate_root)); 719 } 720 721 // If the value is a NaN, canonicalize the value else, do nothing. 722 void CanonicalizeNaN(const DoubleRegister dst, const DoubleRegister src); 723 void CanonicalizeNaN(const DoubleRegister value) { 724 CanonicalizeNaN(value, value); 725 } 726 727 // Converts the integer (untagged smi) in |src| to a double, storing 728 // the result to |dst| 729 void ConvertIntToDouble(DoubleRegister dst, Register src); 730 731 // Converts the unsigned integer (untagged smi) in |src| to 732 // a double, storing the result to |dst| 733 void ConvertUnsignedIntToDouble(DoubleRegister dst, Register src); 734 735 // Converts the integer (untagged smi) in |src| to 736 // a float, storing the result in |dst| 737 void ConvertIntToFloat(DoubleRegister dst, Register src); 738 739 // Converts the unsigned integer (untagged smi) in |src| to 740 // a float, storing the result in |dst| 741 void ConvertUnsignedIntToFloat(DoubleRegister dst, Register src); 742 743 void ConvertInt64ToFloat(DoubleRegister double_dst, Register src); 744 void ConvertInt64ToDouble(DoubleRegister double_dst, Register src); 745 void ConvertUnsignedInt64ToFloat(DoubleRegister double_dst, Register src); 746 void ConvertUnsignedInt64ToDouble(DoubleRegister double_dst, Register src); 747 748 void MovIntToFloat(DoubleRegister dst, Register src); 749 void MovFloatToInt(Register dst, DoubleRegister src); 750 void MovDoubleToInt64(Register dst, DoubleRegister src); 751 void MovInt64ToDouble(DoubleRegister dst, Register src); 752 // Converts the double_input to an integer. Note that, upon return, 753 // the contents of double_dst will also hold the fixed point representation. 754 void ConvertFloat32ToInt64(const Register dst, 755 const DoubleRegister double_input, 756 FPRoundingMode rounding_mode = kRoundToZero); 757 758 // Converts the double_input to an integer. Note that, upon return, 759 // the contents of double_dst will also hold the fixed point representation. 760 void ConvertDoubleToInt64(const Register dst, 761 const DoubleRegister double_input, 762 FPRoundingMode rounding_mode = kRoundToZero); 763 void ConvertDoubleToInt32(const Register dst, 764 const DoubleRegister double_input, 765 FPRoundingMode rounding_mode = kRoundToZero); 766 767 void ConvertFloat32ToInt32(const Register result, 768 const DoubleRegister double_input, 769 FPRoundingMode rounding_mode); 770 void ConvertFloat32ToUnsignedInt32( 771 const Register result, const DoubleRegister double_input, 772 FPRoundingMode rounding_mode = kRoundToZero); 773 // Converts the double_input to an unsigned integer. Note that, upon return, 774 // the contents of double_dst will also hold the fixed point representation. 775 void ConvertDoubleToUnsignedInt64( 776 const Register dst, const DoubleRegister double_input, 777 FPRoundingMode rounding_mode = kRoundToZero); 778 void ConvertDoubleToUnsignedInt32( 779 const Register dst, const DoubleRegister double_input, 780 FPRoundingMode rounding_mode = kRoundToZero); 781 void ConvertFloat32ToUnsignedInt64( 782 const Register result, const DoubleRegister double_input, 783 FPRoundingMode rounding_mode = kRoundToZero); 784 785 // Generates function and stub prologue code. 786 void StubPrologue(StackFrame::Type type, Register base = no_reg, 787 int prologue_offset = 0); 788 void Prologue(Register base, int prologue_offset = 0); 789 790 enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver }; 791 enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes }; 792 void DropArguments(Register count, ArgumentsCountType type, 793 ArgumentsCountMode mode); 794 void DropArgumentsAndPushNewReceiver(Register argc, Register receiver, 795 ArgumentsCountType type, 796 ArgumentsCountMode mode); 797 798 // Get the actual activation frame alignment for target environment. 799 static int ActivationFrameAlignment(); 800 // ---------------------------------------------------------------- 801 // new S390 macro-assembler interfaces that are slightly higher level 802 // than assembler-s390 and may generate variable length sequences 803 804 // load an SMI value <value> to GPR <dst> 805 void LoadSmiLiteral(Register dst, Smi smi); 806 807 // load a literal double value <value> to FPR <result> 808 template <class T> 809 void LoadF64(DoubleRegister result, T value, Register scratch) { 810 static_assert(sizeof(T) == kDoubleSize, "Expect input size to be 8"); 811 uint64_t int_val = bit_cast<uint64_t, T>(value); 812 // Load the 64-bit value into a GPR, then transfer it to FPR via LDGR 813 uint32_t hi_32 = int_val >> 32; 814 uint32_t lo_32 = static_cast<uint32_t>(int_val); 815 816 if (int_val == 0) { 817 lzdr(result); 818 } else if (lo_32 == 0) { 819 llihf(scratch, Operand(hi_32)); 820 ldgr(result, scratch); 821 } else { 822 iihf(scratch, Operand(hi_32)); 823 iilf(scratch, Operand(lo_32)); 824 ldgr(result, scratch); 825 } 826 } 827 828 template <class T> 829 void LoadF32(DoubleRegister result, T value, Register scratch) { 830 static_assert(sizeof(T) == kFloatSize, "Expect input size to be 4"); 831 uint32_t int_val = bit_cast<uint32_t, T>(value); 832 LoadF64(result, static_cast<uint64_t>(int_val) << 32, scratch); 833 } 834 835 void CmpSmiLiteral(Register src1, Smi smi, Register scratch); 836 837 // Set new rounding mode RN to FPSCR 838 void SetRoundingMode(FPRoundingMode RN); 839 840 // reset rounding mode to default (kRoundToNearest) 841 void ResetRoundingMode(); 842 843 // These exist to provide portability between 32 and 64bit 844 void LoadMultipleP(Register dst1, Register dst2, const MemOperand& mem); 845 void StoreMultipleP(Register dst1, Register dst2, const MemOperand& mem); 846 void LoadMultipleW(Register dst1, Register dst2, const MemOperand& mem); 847 void StoreMultipleW(Register dst1, Register dst2, const MemOperand& mem); 848 849 void SwapP(Register src, Register dst, Register scratch); 850 void SwapP(Register src, MemOperand dst, Register scratch); 851 void SwapP(MemOperand src, MemOperand dst, Register scratch_0, 852 Register scratch_1); 853 void SwapFloat32(DoubleRegister src, DoubleRegister dst, 854 DoubleRegister scratch); 855 void SwapFloat32(DoubleRegister src, MemOperand dst, DoubleRegister scratch); 856 void SwapFloat32(MemOperand src, MemOperand dst, DoubleRegister scratch); 857 void SwapDouble(DoubleRegister src, DoubleRegister dst, 858 DoubleRegister scratch); 859 void SwapDouble(DoubleRegister src, MemOperand dst, DoubleRegister scratch); 860 void SwapDouble(MemOperand src, MemOperand dst, DoubleRegister scratch); 861 void SwapSimd128(Simd128Register src, Simd128Register dst, 862 Simd128Register scratch); 863 void SwapSimd128(Simd128Register src, MemOperand dst, 864 Simd128Register scratch); 865 void SwapSimd128(MemOperand src, MemOperand dst, Simd128Register scratch); 866 867 // Cleanse pointer address on 31bit by zero out top bit. 868 // This is a NOP on 64-bit. 869 void CleanseP(Register src) { 870#if (V8_HOST_ARCH_S390 && !(V8_TARGET_ARCH_S390X)) 871 nilh(src, Operand(0x7FFF)); 872#endif 873 } 874 875 // --------------------------------------------------------------------------- 876 // Runtime calls 877 878 // Before calling a C-function from generated code, align arguments on stack. 879 // After aligning the frame, non-register arguments must be stored in 880 // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments 881 // are word sized. If double arguments are used, this function assumes that 882 // all double arguments are stored before core registers; otherwise the 883 // correct alignment of the double values is not guaranteed. 884 // Some compilers/platforms require the stack to be aligned when calling 885 // C++ code. 886 // Needs a scratch register to do some arithmetic. This register will be 887 // trashed. 888 void PrepareCallCFunction(int num_reg_arguments, int num_double_registers, 889 Register scratch); 890 void PrepareCallCFunction(int num_reg_arguments, Register scratch); 891 892 // There are two ways of passing double arguments on ARM, depending on 893 // whether soft or hard floating point ABI is used. These functions 894 // abstract parameter passing for the three different ways we call 895 // C functions from generated code. 896 void MovToFloatParameter(DoubleRegister src); 897 void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2); 898 void MovToFloatResult(DoubleRegister src); 899 900 // Calls a C function and cleans up the space for arguments allocated 901 // by PrepareCallCFunction. The called function is not allowed to trigger a 902 // garbage collection, since that might move the code and invalidate the 903 // return address (unless this is somehow accounted for by the called 904 // function). 905 void CallCFunction(ExternalReference function, int num_arguments); 906 void CallCFunction(Register function, int num_arguments); 907 void CallCFunction(ExternalReference function, int num_reg_arguments, 908 int num_double_arguments); 909 void CallCFunction(Register function, int num_reg_arguments, 910 int num_double_arguments); 911 912 void MovFromFloatParameter(DoubleRegister dst); 913 void MovFromFloatResult(DoubleRegister dst); 914 915 void Trap(); 916 void DebugBreak(); 917 918 // Emit code for a truncating division by a constant. The dividend register is 919 // unchanged and ip gets clobbered. Dividend and result must be different. 920 void TruncateDoubleToI(Isolate* isolate, Zone* zone, Register result, 921 DoubleRegister double_input, StubCallMode stub_mode); 922 void TryInlineTruncateDoubleToI(Register result, DoubleRegister double_input, 923 Label* done); 924 925 // --------------------------------------------------------------------------- 926 // Debugging 927 928 // Calls Abort(msg) if the condition cond is not satisfied. 929 // Use --debug_code to enable. 930 void Assert(Condition cond, AbortReason reason, CRegister cr = cr7); 931 932 // Like Assert(), but without condition. 933 // Use --debug-code to enable. 934 void AssertUnreachable(AbortReason reason); 935 936 // Like Assert(), but always enabled. 937 void Check(Condition cond, AbortReason reason, CRegister cr = cr7); 938 939 // Print a message to stdout and abort execution. 940 void Abort(AbortReason reason); 941 942 // --------------------------------------------------------------------------- 943 // Bit testing/extraction 944 // 945 // Bit numbering is such that the least significant bit is bit 0 946 // (for consistency between 32/64-bit). 947 948 // Extract consecutive bits (defined by rangeStart - rangeEnd) from src 949 // and place them into the least significant bits of dst. 950 inline void ExtractBitRange(Register dst, Register src, int rangeStart, 951 int rangeEnd) { 952 DCHECK(rangeStart >= rangeEnd && rangeStart < kBitsPerSystemPointer); 953 954 // Try to use RISBG if possible. 955 if (CpuFeatures::IsSupported(GENERAL_INSTR_EXT)) { 956 int shiftAmount = (64 - rangeEnd) % 64; // Convert to shift left. 957 int endBit = 63; // End is always LSB after shifting. 958 int startBit = 63 - rangeStart + rangeEnd; 959 RotateInsertSelectBits(dst, src, Operand(startBit), Operand(endBit), 960 Operand(shiftAmount), true); 961 } else { 962 if (rangeEnd > 0) // Don't need to shift if rangeEnd is zero. 963 ShiftRightU64(dst, src, Operand(rangeEnd)); 964 else if (dst != src) // If we didn't shift, we might need to copy 965 mov(dst, src); 966 int width = rangeStart - rangeEnd + 1; 967#if V8_TARGET_ARCH_S390X 968 uint64_t mask = (static_cast<uint64_t>(1) << width) - 1; 969 nihf(dst, Operand(mask >> 32)); 970 nilf(dst, Operand(mask & 0xFFFFFFFF)); 971 ltgr(dst, dst); 972#else 973 uint32_t mask = (1 << width) - 1; 974 AndP(dst, Operand(mask)); 975#endif 976 } 977 } 978 979 inline void ExtractBit(Register dst, Register src, uint32_t bitNumber) { 980 ExtractBitRange(dst, src, bitNumber, bitNumber); 981 } 982 983 // Extract consecutive bits (defined by mask) from src and place them 984 // into the least significant bits of dst. 985 inline void ExtractBitMask(Register dst, Register src, uintptr_t mask, 986 RCBit rc = LeaveRC) { 987 int start = kBitsPerSystemPointer - 1; 988 int end; 989 uintptr_t bit = (1L << start); 990 991 while (bit && (mask & bit) == 0) { 992 start--; 993 bit >>= 1; 994 } 995 end = start; 996 bit >>= 1; 997 998 while (bit && (mask & bit)) { 999 end--; 1000 bit >>= 1; 1001 } 1002 1003 // 1-bits in mask must be contiguous 1004 DCHECK(bit == 0 || (mask & ((bit << 1) - 1)) == 0); 1005 1006 ExtractBitRange(dst, src, start, end); 1007 } 1008 1009 // Test single bit in value. 1010 inline void TestBit(Register value, int bitNumber, Register scratch = r0) { 1011 ExtractBitRange(scratch, value, bitNumber, bitNumber); 1012 } 1013 1014 // Test consecutive bit range in value. Range is defined by 1015 // rangeStart - rangeEnd. 1016 inline void TestBitRange(Register value, int rangeStart, int rangeEnd, 1017 Register scratch = r0) { 1018 ExtractBitRange(scratch, value, rangeStart, rangeEnd); 1019 } 1020 1021 // Test consecutive bit range in value. Range is defined by mask. 1022 inline void TestBitMask(Register value, uintptr_t mask, 1023 Register scratch = r0) { 1024 ExtractBitMask(scratch, value, mask, SetRC); 1025 } 1026 inline void TestIfSmi(Register value) { tmll(value, Operand(1)); } 1027 1028 inline void TestIfSmi(MemOperand value) { 1029 if (is_uint12(value.offset())) { 1030 tm(value, Operand(1)); 1031 } else if (is_int20(value.offset())) { 1032 tmy(value, Operand(1)); 1033 } else { 1034 LoadS8(r0, value); 1035 tmll(r0, Operand(1)); 1036 } 1037 } 1038 1039 inline void TestIfInt32(Register value) { 1040 // High bits must be identical to fit into an 32-bit integer 1041 cgfr(value, value); 1042 } 1043 void SmiUntag(Register reg) { SmiUntag(reg, reg); } 1044 1045 void SmiUntag(Register dst, const MemOperand& src); 1046 void SmiUntag(Register dst, Register src) { 1047 if (SmiValuesAre31Bits()) { 1048 ShiftRightS32(dst, src, Operand(kSmiShift)); 1049 } else { 1050 ShiftRightS64(dst, src, Operand(kSmiShift)); 1051 } 1052 lgfr(dst, dst); 1053 } 1054 void SmiToInt32(Register smi) { 1055 if (FLAG_enable_slow_asserts) { 1056 AssertSmi(smi); 1057 } 1058 DCHECK(SmiValuesAre32Bits() || SmiValuesAre31Bits()); 1059 SmiUntag(smi); 1060 } 1061 1062 // Shift left by kSmiShift 1063 void SmiTag(Register reg) { SmiTag(reg, reg); } 1064 void SmiTag(Register dst, Register src) { 1065 ShiftLeftU64(dst, src, Operand(kSmiShift)); 1066 } 1067 1068 // Abort execution if argument is a smi, enabled via --debug-code. 1069 void AssertNotSmi(Register object); 1070 void AssertSmi(Register object); 1071 1072 // Activation support. 1073 void EnterFrame(StackFrame::Type type, 1074 bool load_constant_pool_pointer_reg = false); 1075 // Returns the pc offset at which the frame ends. 1076 int LeaveFrame(StackFrame::Type type, int stack_adjustment = 0); 1077 1078 void AllocateStackSpace(int bytes) { 1079 DCHECK_GE(bytes, 0); 1080 if (bytes == 0) return; 1081 lay(sp, MemOperand(sp, -bytes)); 1082 } 1083 1084 void AllocateStackSpace(Register bytes) { SubS64(sp, sp, bytes); } 1085 1086 void CheckPageFlag(Register object, Register scratch, int mask, Condition cc, 1087 Label* condition_met); 1088 1089 void ComputeCodeStartAddress(Register dst); 1090 void LoadPC(Register dst); 1091 1092 // Control-flow integrity: 1093 1094 // Define a function entrypoint. This doesn't emit any code for this 1095 // architecture, as control-flow integrity is not supported for it. 1096 void CodeEntry() {} 1097 // Define an exception handler. 1098 void ExceptionHandler() {} 1099 // Define an exception handler and bind a label. 1100 void BindExceptionHandler(Label* label) { bind(label); } 1101 1102 // Generates an instruction sequence s.t. the return address points to the 1103 // instruction following the call. 1104 // The return address on the stack is used by frame iteration. 1105 void StoreReturnAddressAndCall(Register target); 1106 1107 // --------------------------------------------------------------------------- 1108 // Simd Support. 1109 void F64x2Splat(Simd128Register dst, Simd128Register src); 1110 void F32x4Splat(Simd128Register dst, Simd128Register src); 1111 void I64x2Splat(Simd128Register dst, Register src); 1112 void I32x4Splat(Simd128Register dst, Register src); 1113 void I16x8Splat(Simd128Register dst, Register src); 1114 void I8x16Splat(Simd128Register dst, Register src); 1115 void F64x2ExtractLane(DoubleRegister dst, Simd128Register src, 1116 uint8_t imm_lane_idx, Register = r0); 1117 void F32x4ExtractLane(DoubleRegister dst, Simd128Register src, 1118 uint8_t imm_lane_idx, Register = r0); 1119 void I64x2ExtractLane(Register dst, Simd128Register src, uint8_t imm_lane_idx, 1120 Register = r0); 1121 void I32x4ExtractLane(Register dst, Simd128Register src, uint8_t imm_lane_idx, 1122 Register = r0); 1123 void I16x8ExtractLaneU(Register dst, Simd128Register src, 1124 uint8_t imm_lane_idx, Register = r0); 1125 void I16x8ExtractLaneS(Register dst, Simd128Register src, 1126 uint8_t imm_lane_idx, Register scratch); 1127 void I8x16ExtractLaneU(Register dst, Simd128Register src, 1128 uint8_t imm_lane_idx, Register = r0); 1129 void I8x16ExtractLaneS(Register dst, Simd128Register src, 1130 uint8_t imm_lane_idx, Register scratch); 1131 void F64x2ReplaceLane(Simd128Register dst, Simd128Register src1, 1132 DoubleRegister src2, uint8_t imm_lane_idx, 1133 Register scratch); 1134 void F32x4ReplaceLane(Simd128Register dst, Simd128Register src1, 1135 DoubleRegister src2, uint8_t imm_lane_idx, 1136 Register scratch); 1137 void I64x2ReplaceLane(Simd128Register dst, Simd128Register src1, 1138 Register src2, uint8_t imm_lane_idx, Register = r0); 1139 void I32x4ReplaceLane(Simd128Register dst, Simd128Register src1, 1140 Register src2, uint8_t imm_lane_idx, Register = r0); 1141 void I16x8ReplaceLane(Simd128Register dst, Simd128Register src1, 1142 Register src2, uint8_t imm_lane_idx, Register = r0); 1143 void I8x16ReplaceLane(Simd128Register dst, Simd128Register src1, 1144 Register src2, uint8_t imm_lane_idx, Register = r0); 1145 void I64x2Mul(Simd128Register dst, Simd128Register src1, Simd128Register src2, 1146 Register scratch1, Register scratch2, Register scratch3); 1147 void I32x4GeU(Simd128Register dst, Simd128Register src1, Simd128Register src2, 1148 Simd128Register scratch); 1149 void I16x8GeU(Simd128Register dst, Simd128Register src1, Simd128Register src2, 1150 Simd128Register scratch); 1151 void I8x16GeU(Simd128Register dst, Simd128Register src1, Simd128Register src2, 1152 Simd128Register scratch); 1153 void I64x2BitMask(Register dst, Simd128Register src, Register scratch1, 1154 Simd128Register scratch2); 1155 void I32x4BitMask(Register dst, Simd128Register src, Register scratch1, 1156 Simd128Register scratch2); 1157 void I16x8BitMask(Register dst, Simd128Register src, Register scratch1, 1158 Simd128Register scratch2); 1159 void I8x16BitMask(Register dst, Simd128Register src, Register scratch1, 1160 Register scratch2, Simd128Register scratch3); 1161 void V128AnyTrue(Register dst, Simd128Register src, Register scratch); 1162 void I32x4SConvertF32x4(Simd128Register dst, Simd128Register src, 1163 Simd128Register scratch1, Register scratch2); 1164 void I32x4UConvertF32x4(Simd128Register dst, Simd128Register src, 1165 Simd128Register scratch1, Register scratch2); 1166 void F32x4SConvertI32x4(Simd128Register dst, Simd128Register src, 1167 Simd128Register scratch1, Register scratch2); 1168 void F32x4UConvertI32x4(Simd128Register dst, Simd128Register src, 1169 Simd128Register scratch1, Register scratch2); 1170 void I16x8SConvertI32x4(Simd128Register dst, Simd128Register src1, 1171 Simd128Register src2); 1172 void I8x16SConvertI16x8(Simd128Register dst, Simd128Register src1, 1173 Simd128Register src2); 1174 void I16x8UConvertI32x4(Simd128Register dst, Simd128Register src1, 1175 Simd128Register src2, Simd128Register scratch); 1176 void I8x16UConvertI16x8(Simd128Register dst, Simd128Register src1, 1177 Simd128Register src2, Simd128Register scratch); 1178 void F64x2PromoteLowF32x4(Simd128Register dst, Simd128Register src, 1179 Simd128Register scratch1, Register scratch2, 1180 Register scratch3, Register scratch4); 1181 void F32x4DemoteF64x2Zero(Simd128Register dst, Simd128Register src, 1182 Simd128Register scratch1, Register scratch2, 1183 Register scratch3, Register scratch4); 1184 void I32x4TruncSatF64x2SZero(Simd128Register dst, Simd128Register src, 1185 Simd128Register scratch); 1186 void I32x4TruncSatF64x2UZero(Simd128Register dst, Simd128Register src, 1187 Simd128Register scratch); 1188 void I8x16Swizzle(Simd128Register dst, Simd128Register src1, 1189 Simd128Register src2, Register scratch1, Register scratch2, 1190 Simd128Register scratch3, Simd128Register scratch4); 1191 void S128Const(Simd128Register dst, uint64_t high, uint64_t low, 1192 Register scratch1, Register scratch2); 1193 void I8x16Shuffle(Simd128Register dst, Simd128Register src1, 1194 Simd128Register src2, uint64_t high, uint64_t low, 1195 Register scratch1, Register scratch2, 1196 Simd128Register scratch3); 1197 void I32x4DotI16x8S(Simd128Register dst, Simd128Register src1, 1198 Simd128Register src2, Simd128Register scratch); 1199 void I16x8Q15MulRSatS(Simd128Register dst, Simd128Register src1, 1200 Simd128Register src2, Simd128Register scratch1, 1201 Simd128Register scratch2, Simd128Register scratch3); 1202 void S128Select(Simd128Register dst, Simd128Register src1, 1203 Simd128Register src2, Simd128Register mask); 1204 1205#define SIMD_SHIFT_LIST(V) \ 1206 V(I64x2Shl) \ 1207 V(I64x2ShrS) \ 1208 V(I64x2ShrU) \ 1209 V(I32x4Shl) \ 1210 V(I32x4ShrS) \ 1211 V(I32x4ShrU) \ 1212 V(I16x8Shl) \ 1213 V(I16x8ShrS) \ 1214 V(I16x8ShrU) \ 1215 V(I8x16Shl) \ 1216 V(I8x16ShrS) \ 1217 V(I8x16ShrU) 1218 1219#define PROTOTYPE_SIMD_SHIFT(name) \ 1220 void name(Simd128Register dst, Simd128Register src1, Register src2, \ 1221 Simd128Register scratch); \ 1222 void name(Simd128Register dst, Simd128Register src1, const Operand& src2, \ 1223 Register scratch1, Simd128Register scratch2); 1224 SIMD_SHIFT_LIST(PROTOTYPE_SIMD_SHIFT) 1225#undef PROTOTYPE_SIMD_SHIFT 1226#undef SIMD_SHIFT_LIST 1227 1228#define SIMD_UNOP_LIST(V) \ 1229 V(F64x2Abs) \ 1230 V(F64x2Neg) \ 1231 V(F64x2Sqrt) \ 1232 V(F64x2Ceil) \ 1233 V(F64x2Floor) \ 1234 V(F64x2Trunc) \ 1235 V(F64x2NearestInt) \ 1236 V(F64x2ConvertLowI32x4S) \ 1237 V(F64x2ConvertLowI32x4U) \ 1238 V(F32x4Abs) \ 1239 V(F32x4Neg) \ 1240 V(F32x4Sqrt) \ 1241 V(F32x4Ceil) \ 1242 V(F32x4Floor) \ 1243 V(F32x4Trunc) \ 1244 V(F32x4NearestInt) \ 1245 V(I64x2Abs) \ 1246 V(I64x2SConvertI32x4Low) \ 1247 V(I64x2SConvertI32x4High) \ 1248 V(I64x2UConvertI32x4Low) \ 1249 V(I64x2UConvertI32x4High) \ 1250 V(I64x2Neg) \ 1251 V(I32x4Abs) \ 1252 V(I32x4Neg) \ 1253 V(I32x4SConvertI16x8Low) \ 1254 V(I32x4SConvertI16x8High) \ 1255 V(I32x4UConvertI16x8Low) \ 1256 V(I32x4UConvertI16x8High) \ 1257 V(I16x8Abs) \ 1258 V(I16x8Neg) \ 1259 V(I16x8SConvertI8x16Low) \ 1260 V(I16x8SConvertI8x16High) \ 1261 V(I16x8UConvertI8x16Low) \ 1262 V(I16x8UConvertI8x16High) \ 1263 V(I8x16Abs) \ 1264 V(I8x16Neg) \ 1265 V(I8x16Popcnt) \ 1266 V(S128Not) \ 1267 V(S128Zero) \ 1268 V(S128AllOnes) 1269 1270#define PROTOTYPE_SIMD_UNOP(name) \ 1271 void name(Simd128Register dst, Simd128Register src); 1272 SIMD_UNOP_LIST(PROTOTYPE_SIMD_UNOP) 1273#undef PROTOTYPE_SIMD_UNOP 1274#undef SIMD_UNOP_LIST 1275 1276#define SIMD_BINOP_LIST(V) \ 1277 V(F64x2Add) \ 1278 V(F64x2Sub) \ 1279 V(F64x2Mul) \ 1280 V(F64x2Div) \ 1281 V(F64x2Min) \ 1282 V(F64x2Max) \ 1283 V(F64x2Eq) \ 1284 V(F64x2Ne) \ 1285 V(F64x2Lt) \ 1286 V(F64x2Le) \ 1287 V(F64x2Pmin) \ 1288 V(F64x2Pmax) \ 1289 V(F32x4Add) \ 1290 V(F32x4Sub) \ 1291 V(F32x4Mul) \ 1292 V(F32x4Div) \ 1293 V(F32x4Min) \ 1294 V(F32x4Max) \ 1295 V(F32x4Eq) \ 1296 V(F32x4Ne) \ 1297 V(F32x4Lt) \ 1298 V(F32x4Le) \ 1299 V(F32x4Pmin) \ 1300 V(F32x4Pmax) \ 1301 V(I64x2Add) \ 1302 V(I64x2Sub) \ 1303 V(I64x2Eq) \ 1304 V(I64x2Ne) \ 1305 V(I64x2GtS) \ 1306 V(I64x2GeS) \ 1307 V(I32x4Add) \ 1308 V(I32x4Sub) \ 1309 V(I32x4Mul) \ 1310 V(I32x4Eq) \ 1311 V(I32x4Ne) \ 1312 V(I32x4GtS) \ 1313 V(I32x4GeS) \ 1314 V(I32x4GtU) \ 1315 V(I32x4MinS) \ 1316 V(I32x4MinU) \ 1317 V(I32x4MaxS) \ 1318 V(I32x4MaxU) \ 1319 V(I16x8Add) \ 1320 V(I16x8Sub) \ 1321 V(I16x8Mul) \ 1322 V(I16x8Eq) \ 1323 V(I16x8Ne) \ 1324 V(I16x8GtS) \ 1325 V(I16x8GeS) \ 1326 V(I16x8GtU) \ 1327 V(I16x8MinS) \ 1328 V(I16x8MinU) \ 1329 V(I16x8MaxS) \ 1330 V(I16x8MaxU) \ 1331 V(I16x8RoundingAverageU) \ 1332 V(I8x16Add) \ 1333 V(I8x16Sub) \ 1334 V(I8x16Eq) \ 1335 V(I8x16Ne) \ 1336 V(I8x16GtS) \ 1337 V(I8x16GeS) \ 1338 V(I8x16GtU) \ 1339 V(I8x16MinS) \ 1340 V(I8x16MinU) \ 1341 V(I8x16MaxS) \ 1342 V(I8x16MaxU) \ 1343 V(I8x16RoundingAverageU) \ 1344 V(S128And) \ 1345 V(S128Or) \ 1346 V(S128Xor) \ 1347 V(S128AndNot) 1348 1349#define PROTOTYPE_SIMD_BINOP(name) \ 1350 void name(Simd128Register dst, Simd128Register src1, Simd128Register src2); 1351 SIMD_BINOP_LIST(PROTOTYPE_SIMD_BINOP) 1352#undef PROTOTYPE_SIMD_BINOP 1353#undef SIMD_BINOP_LIST 1354 1355#define SIMD_EXT_MUL_LIST(V) \ 1356 V(I64x2ExtMulLowI32x4S) \ 1357 V(I64x2ExtMulHighI32x4S) \ 1358 V(I64x2ExtMulLowI32x4U) \ 1359 V(I64x2ExtMulHighI32x4U) \ 1360 V(I32x4ExtMulLowI16x8S) \ 1361 V(I32x4ExtMulHighI16x8S) \ 1362 V(I32x4ExtMulLowI16x8U) \ 1363 V(I32x4ExtMulHighI16x8U) \ 1364 V(I16x8ExtMulLowI8x16S) \ 1365 V(I16x8ExtMulHighI8x16S) \ 1366 V(I16x8ExtMulLowI8x16U) \ 1367 V(I16x8ExtMulHighI8x16U) 1368 1369#define PROTOTYPE_SIMD_EXT_MUL(name) \ 1370 void name(Simd128Register dst, Simd128Register src1, Simd128Register src2, \ 1371 Simd128Register scratch); 1372 SIMD_EXT_MUL_LIST(PROTOTYPE_SIMD_EXT_MUL) 1373#undef PROTOTYPE_SIMD_EXT_MUL 1374#undef SIMD_EXT_MUL_LIST 1375 1376#define SIMD_ALL_TRUE_LIST(V) \ 1377 V(I64x2AllTrue) \ 1378 V(I32x4AllTrue) \ 1379 V(I16x8AllTrue) \ 1380 V(I8x16AllTrue) 1381 1382#define PROTOTYPE_SIMD_ALL_TRUE(name) \ 1383 void name(Register dst, Simd128Register src, Register scratch1, \ 1384 Simd128Register scratch2); 1385 SIMD_ALL_TRUE_LIST(PROTOTYPE_SIMD_ALL_TRUE) 1386#undef PROTOTYPE_SIMD_ALL_TRUE 1387#undef SIMD_ALL_TRUE_LIST 1388 1389#define SIMD_QFM_LIST(V) \ 1390 V(F64x2Qfma) \ 1391 V(F64x2Qfms) \ 1392 V(F32x4Qfma) \ 1393 V(F32x4Qfms) 1394 1395#define PROTOTYPE_SIMD_QFM(name) \ 1396 void name(Simd128Register dst, Simd128Register src1, Simd128Register src2, \ 1397 Simd128Register src3); 1398 SIMD_QFM_LIST(PROTOTYPE_SIMD_QFM) 1399#undef PROTOTYPE_SIMD_QFM 1400#undef SIMD_QFM_LIST 1401 1402#define SIMD_ADD_SUB_SAT_LIST(V) \ 1403 V(I16x8AddSatS) \ 1404 V(I16x8SubSatS) \ 1405 V(I16x8AddSatU) \ 1406 V(I16x8SubSatU) \ 1407 V(I8x16AddSatS) \ 1408 V(I8x16SubSatS) \ 1409 V(I8x16AddSatU) \ 1410 V(I8x16SubSatU) 1411 1412#define PROTOTYPE_SIMD_ADD_SUB_SAT(name) \ 1413 void name(Simd128Register dst, Simd128Register src1, Simd128Register src2, \ 1414 Simd128Register scratch1, Simd128Register scratch2); 1415 SIMD_ADD_SUB_SAT_LIST(PROTOTYPE_SIMD_ADD_SUB_SAT) 1416#undef PROTOTYPE_SIMD_ADD_SUB_SAT 1417#undef SIMD_ADD_SUB_SAT_LIST 1418 1419#define SIMD_EXT_ADD_PAIRWISE_LIST(V) \ 1420 V(I32x4ExtAddPairwiseI16x8S) \ 1421 V(I32x4ExtAddPairwiseI16x8U) \ 1422 V(I16x8ExtAddPairwiseI8x16S) \ 1423 V(I16x8ExtAddPairwiseI8x16U) 1424 1425#define PROTOTYPE_SIMD_EXT_ADD_PAIRWISE(name) \ 1426 void name(Simd128Register dst, Simd128Register src, \ 1427 Simd128Register scratch1, Simd128Register scratch2); 1428 SIMD_EXT_ADD_PAIRWISE_LIST(PROTOTYPE_SIMD_EXT_ADD_PAIRWISE) 1429#undef PROTOTYPE_SIMD_EXT_ADD_PAIRWISE 1430#undef SIMD_EXT_ADD_PAIRWISE_LIST 1431 1432 // --------------------------------------------------------------------------- 1433 // Pointer compression Support 1434 1435 void SmiToPtrArrayOffset(Register dst, Register src) { 1436#if defined(V8_COMPRESS_POINTERS) || defined(V8_31BIT_SMIS_ON_64BIT_ARCH) 1437 STATIC_ASSERT(kSmiTag == 0 && kSmiShift < kSystemPointerSizeLog2); 1438 ShiftLeftU64(dst, src, Operand(kSystemPointerSizeLog2 - kSmiShift)); 1439#else 1440 STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kSystemPointerSizeLog2); 1441 ShiftRightS64(dst, src, Operand(kSmiShift - kSystemPointerSizeLog2)); 1442#endif 1443 } 1444 1445 // Loads a field containing a HeapObject and decompresses it if pointer 1446 // compression is enabled. 1447 void LoadTaggedPointerField(const Register& destination, 1448 const MemOperand& field_operand, 1449 const Register& scratch = no_reg); 1450 void LoadTaggedSignedField(Register destination, MemOperand field_operand); 1451 1452 // Loads a field containing any tagged value and decompresses it if necessary. 1453 void LoadAnyTaggedField(const Register& destination, 1454 const MemOperand& field_operand, 1455 const Register& scratch = no_reg); 1456 1457 // Loads a field containing smi value and untags it. 1458 void SmiUntagField(Register dst, const MemOperand& src); 1459 1460 // Compresses and stores tagged value to given on-heap location. 1461 void StoreTaggedField(const Register& value, 1462 const MemOperand& dst_field_operand, 1463 const Register& scratch = no_reg); 1464 1465 void DecompressTaggedSigned(Register destination, MemOperand field_operand); 1466 void DecompressTaggedSigned(Register destination, Register src); 1467 void DecompressTaggedPointer(Register destination, MemOperand field_operand); 1468 void DecompressTaggedPointer(Register destination, Register source); 1469 void DecompressAnyTagged(Register destination, MemOperand field_operand); 1470 void DecompressAnyTagged(Register destination, Register source); 1471 1472 // CountLeadingZeros will corrupt the scratch register pair (eg. r0:r1) 1473 void CountLeadingZerosU32(Register dst, Register src, 1474 Register scratch_pair = r0); 1475 void CountLeadingZerosU64(Register dst, Register src, 1476 Register scratch_pair = r0); 1477 void CountTrailingZerosU32(Register dst, Register src, 1478 Register scratch_pair = r0); 1479 void CountTrailingZerosU64(Register dst, Register src, 1480 Register scratch_pair = r0); 1481 1482 private: 1483 static const int kSmiShift = kSmiTagSize + kSmiShiftSize; 1484 1485 void CallCFunctionHelper(Register function, int num_reg_arguments, 1486 int num_double_arguments); 1487 1488 void Jump(intptr_t target, RelocInfo::Mode rmode, Condition cond = al); 1489 int CalculateStackPassedWords(int num_reg_arguments, 1490 int num_double_arguments); 1491}; 1492 1493// MacroAssembler implements a collection of frequently used macros. 1494class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler { 1495 public: 1496 using TurboAssembler::TurboAssembler; 1497 1498 void LoadStackLimit(Register destination, StackLimitKind kind); 1499 // It assumes that the arguments are located below the stack pointer. 1500 // argc is the number of arguments not including the receiver. 1501 // TODO(victorgomes): Remove this function once we stick with the reversed 1502 // arguments order. 1503 void LoadReceiver(Register dest, Register argc) { 1504 LoadU64(dest, MemOperand(sp, 0)); 1505 } 1506 1507 void StoreReceiver(Register rec, Register argc, Register scratch) { 1508 StoreU64(rec, MemOperand(sp, 0)); 1509 } 1510 1511 void CallRuntime(const Runtime::Function* f, int num_arguments, 1512 SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore); 1513 void CallRuntimeSaveDoubles(Runtime::FunctionId fid) { 1514 const Runtime::Function* function = Runtime::FunctionForId(fid); 1515 CallRuntime(function, function->nargs, SaveFPRegsMode::kSave); 1516 } 1517 1518 // Convenience function: Same as above, but takes the fid instead. 1519 void CallRuntime(Runtime::FunctionId fid, 1520 SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) { 1521 const Runtime::Function* function = Runtime::FunctionForId(fid); 1522 CallRuntime(function, function->nargs, save_doubles); 1523 } 1524 1525 // Convenience function: Same as above, but takes the fid instead. 1526 void CallRuntime(Runtime::FunctionId fid, int num_arguments, 1527 SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) { 1528 CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles); 1529 } 1530 1531 // Convenience function: tail call a runtime routine (jump). 1532 void TailCallRuntime(Runtime::FunctionId fid); 1533 1534 // --------------------------------------------------------------------------- 1535 // Support functions. 1536 1537 // Compare object type for heap object. heap_object contains a non-Smi 1538 // whose object type should be compared with the given type. This both 1539 // sets the flags and leaves the object type in the type_reg register. 1540 // It leaves the map in the map register (unless the type_reg and map register 1541 // are the same register). It leaves the heap object in the heap_object 1542 // register unless the heap_object register is the same register as one of the 1543 // other registers. 1544 // Type_reg can be no_reg. In that case ip is used. 1545 void CompareObjectType(Register heap_object, Register map, Register type_reg, 1546 InstanceType type); 1547 1548 // Compare instance type in a map. map contains a valid map object whose 1549 // object type should be compared with the given type. This both 1550 // sets the flags and leaves the object type in the type_reg register. 1551 void CompareInstanceType(Register map, Register type_reg, InstanceType type); 1552 1553 // Compare instance type ranges for a map (lower_limit and higher_limit 1554 // inclusive). 1555 // 1556 // Always use unsigned comparisons: ls for a positive result. 1557 void CompareInstanceTypeRange(Register map, Register type_reg, 1558 InstanceType lower_limit, 1559 InstanceType higher_limit); 1560 1561 // Compare the object in a register to a value from the root list. 1562 // Uses the ip register as scratch. 1563 void CompareRoot(Register obj, RootIndex index); 1564 void PushRoot(RootIndex index) { 1565 LoadRoot(r0, index); 1566 Push(r0); 1567 } 1568 1569 template <class T> 1570 void CompareTagged(Register src1, T src2) { 1571 if (COMPRESS_POINTERS_BOOL) { 1572 CmpS32(src1, src2); 1573 } else { 1574 CmpS64(src1, src2); 1575 } 1576 } 1577 1578 // Jump to a runtime routine. 1579 void JumpToExternalReference(const ExternalReference& builtin, 1580 bool builtin_exit_frame = false); 1581 1582 // Generates a trampoline to jump to the off-heap instruction stream. 1583 void JumpToOffHeapInstructionStream(Address entry); 1584 1585 // Compare the object in a register to a value and jump if they are equal. 1586 void JumpIfRoot(Register with, RootIndex index, Label* if_equal) { 1587 CompareRoot(with, index); 1588 beq(if_equal); 1589 } 1590 1591 // Compare the object in a register to a value and jump if they are not equal. 1592 void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal) { 1593 CompareRoot(with, index); 1594 bne(if_not_equal); 1595 } 1596 1597 // Checks if value is in range [lower_limit, higher_limit] using a single 1598 // comparison. 1599 void CompareRange(Register value, unsigned lower_limit, 1600 unsigned higher_limit); 1601 void JumpIfIsInRange(Register value, unsigned lower_limit, 1602 unsigned higher_limit, Label* on_in_range); 1603 1604 // --------------------------------------------------------------------------- 1605 // In-place weak references. 1606 void LoadWeakValue(Register out, Register in, Label* target_if_cleared); 1607 1608 // --------------------------------------------------------------------------- 1609 // StatsCounter support 1610 1611 void IncrementCounter(StatsCounter* counter, int value, Register scratch1, 1612 Register scratch2) { 1613 if (!FLAG_native_code_counters) return; 1614 EmitIncrementCounter(counter, value, scratch1, scratch2); 1615 } 1616 void EmitIncrementCounter(StatsCounter* counter, int value, Register scratch1, 1617 Register scratch2); 1618 void DecrementCounter(StatsCounter* counter, int value, Register scratch1, 1619 Register scratch2) { 1620 if (!FLAG_native_code_counters) return; 1621 EmitDecrementCounter(counter, value, scratch1, scratch2); 1622 } 1623 void EmitDecrementCounter(StatsCounter* counter, int value, Register scratch1, 1624 Register scratch2); 1625 1626 // --------------------------------------------------------------------------- 1627 // Stack limit utilities 1628 1629 MemOperand StackLimitAsMemOperand(StackLimitKind kind); 1630 void StackOverflowCheck(Register num_args, Register scratch, 1631 Label* stack_overflow); 1632 1633 // --------------------------------------------------------------------------- 1634 // JavaScript invokes 1635 1636 // Set up call kind marking in ecx. The method takes ecx as an 1637 // explicit first parameter to make the code more readable at the 1638 // call sites. 1639 // void SetCallKind(Register dst, CallKind kind); 1640 1641 // Removes current frame and its arguments from the stack preserving 1642 // the arguments and a return address pushed to the stack for the next call. 1643 // Both |callee_args_count| and |caller_args_count| do not include 1644 // receiver. |callee_args_count| is not modified. |caller_args_count| 1645 // is trashed. 1646 1647 // Invoke the JavaScript function code by either calling or jumping. 1648 void InvokeFunctionCode(Register function, Register new_target, 1649 Register expected_parameter_count, 1650 Register actual_parameter_count, InvokeType type); 1651 1652 // On function call, call into the debugger if necessary. 1653 void CheckDebugHook(Register fun, Register new_target, 1654 Register expected_parameter_count, 1655 Register actual_parameter_count); 1656 1657 // Invoke the JavaScript function in the given register. Changes the 1658 // current context to the context in the function before invoking. 1659 void InvokeFunctionWithNewTarget(Register function, Register new_target, 1660 Register actual_parameter_count, 1661 InvokeType type); 1662 void InvokeFunction(Register function, Register expected_parameter_count, 1663 Register actual_parameter_count, InvokeType type); 1664 1665 // Exception handling 1666 1667 // Push a new stack handler and link into stack handler chain. 1668 void PushStackHandler(); 1669 1670 // Unlink the stack handler on top of the stack from the stack handler chain. 1671 // Must preserve the result register. 1672 void PopStackHandler(); 1673 1674 // Enter exit frame. 1675 // stack_space - extra stack space, used for parameters before call to C. 1676 // At least one slot (for the return address) should be provided. 1677 void EnterExitFrame(bool save_doubles, int stack_space = 1, 1678 StackFrame::Type frame_type = StackFrame::EXIT); 1679 1680 // Leave the current exit frame. Expects the return value in r0. 1681 // Expect the number of values, pushed prior to the exit frame, to 1682 // remove in a register (or no_reg, if there is nothing to remove). 1683 void LeaveExitFrame(bool save_doubles, Register argument_count, 1684 bool argument_count_is_length = false); 1685 1686 // Load the global proxy from the current context. 1687 void LoadGlobalProxy(Register dst) { 1688 LoadNativeContextSlot(dst, Context::GLOBAL_PROXY_INDEX); 1689 } 1690 1691 void LoadNativeContextSlot(Register dst, int index); 1692 1693 // --------------------------------------------------------------------------- 1694 // Smi utilities 1695 1696 // Jump if either of the registers contain a non-smi. 1697 inline void JumpIfNotSmi(Register value, Label* not_smi_label) { 1698 TestIfSmi(value); 1699 bne(not_smi_label /*, cr0*/); 1700 } 1701 1702#if !defined(V8_COMPRESS_POINTERS) && !defined(V8_31BIT_SMIS_ON_64BIT_ARCH) 1703 // Ensure it is permissible to read/write int value directly from 1704 // upper half of the smi. 1705 STATIC_ASSERT(kSmiTag == 0); 1706 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); 1707#endif 1708#if V8_TARGET_LITTLE_ENDIAN 1709#define SmiWordOffset(offset) (offset + kSystemPointerSize / 2) 1710#else 1711#define SmiWordOffset(offset) offset 1712#endif 1713 1714 // Abort execution if argument is not a Constructor, enabled via --debug-code. 1715 void AssertConstructor(Register object, Register scratch); 1716 1717 // Abort execution if argument is not a JSFunction, enabled via --debug-code. 1718 void AssertFunction(Register object); 1719 1720 // Abort execution if argument is not a callable JSFunction, enabled via 1721 // --debug-code. 1722 void AssertCallableFunction(Register object); 1723 1724 // Abort execution if argument is not a JSBoundFunction, 1725 // enabled via --debug-code. 1726 void AssertBoundFunction(Register object); 1727 1728 // Abort execution if argument is not a JSGeneratorObject (or subclass), 1729 // enabled via --debug-code. 1730 void AssertGeneratorObject(Register object); 1731 1732 // Abort execution if argument is not undefined or an AllocationSite, enabled 1733 // via --debug-code. 1734 void AssertUndefinedOrAllocationSite(Register object, Register scratch); 1735 1736 template <typename Field> 1737 void DecodeField(Register dst, Register src) { 1738 ExtractBitRange(dst, src, Field::kShift + Field::kSize - 1, Field::kShift); 1739 } 1740 1741 template <typename Field> 1742 void DecodeField(Register reg) { 1743 DecodeField<Field>(reg, reg); 1744 } 1745 1746 // --------------------------------------------------------------------------- 1747 // GC Support 1748 1749 void IncrementalMarkingRecordWriteHelper(Register object, Register value, 1750 Register address); 1751 1752 void CallJSEntry(Register target); 1753 static int CallSizeNotPredictableCodeSize(Address target, 1754 RelocInfo::Mode rmode, 1755 Condition cond = al); 1756 // Notify the garbage collector that we wrote a pointer into an object. 1757 // |object| is the object being stored into, |value| is the object being 1758 // stored. value and scratch registers are clobbered by the operation. 1759 // The offset is the offset from the start of the object, not the offset from 1760 // the tagged HeapObject pointer. For use with FieldMemOperand(reg, off). 1761 void RecordWriteField( 1762 Register object, int offset, Register value, Register slot_address, 1763 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp, 1764 RememberedSetAction remembered_set_action = RememberedSetAction::kEmit, 1765 SmiCheck smi_check = SmiCheck::kInline); 1766 1767 // For a given |object| notify the garbage collector that the slot |address| 1768 // has been written. |value| is the object being stored. The value and 1769 // address registers are clobbered by the operation. 1770 void RecordWrite( 1771 Register object, Register slot_address, Register value, 1772 LinkRegisterStatus lr_status, SaveFPRegsMode save_fp, 1773 RememberedSetAction remembered_set_action = RememberedSetAction::kEmit, 1774 SmiCheck smi_check = SmiCheck::kInline); 1775 1776 private: 1777 static const int kSmiShift = kSmiTagSize + kSmiShiftSize; 1778 // Helper functions for generating invokes. 1779 void InvokePrologue(Register expected_parameter_count, 1780 Register actual_parameter_count, Label* done, 1781 InvokeType type); 1782 1783 DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler); 1784}; 1785 1786#define ACCESS_MASM(masm) masm-> 1787 1788} // namespace internal 1789} // namespace v8 1790 1791#endif // V8_CODEGEN_S390_MACRO_ASSEMBLER_S390_H_ 1792