1 // Copyright (c) 1994-2006 Sun Microsystems Inc. 2 // All Rights Reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions 6 // are met: 7 // 8 // - Redistributions of source code must retain the above copyright notice, 9 // this list of conditions and the following disclaimer. 10 // 11 // - Redistribution in binary form must reproduce the above copyright 12 // notice, this list of conditions and the following disclaimer in the 13 // documentation and/or other materials provided with the 14 // distribution. 15 // 16 // - Neither the name of Sun Microsystems or the names of contributors may 17 // be used to endorse or promote products derived from this software without 18 // specific prior written permission. 19 // 20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 // OF THE POSSIBILITY OF SUCH DAMAGE. 32 33 // The original source code covered by the above license above has been 34 // modified significantly by Google Inc. 35 // Copyright 2014 the V8 project authors. All rights reserved. 36 37 // A light-weight S390 Assembler 38 // Generates user mode instructions for z/Architecture 39 40 #ifndef V8_S390_ASSEMBLER_S390_H_ 41 #define V8_S390_ASSEMBLER_S390_H_ 42 #include <stdio.h> 43 #if V8_HOST_ARCH_S390 44 // elf.h include is required for auxv check for STFLE facility used 45 // for hardware detection, which is sensible only on s390 hosts. 46 #include <elf.h> 47 #endif 48 49 #include <fcntl.h> 50 #include <unistd.h> 51 #include "src/assembler.h" 52 #include "src/s390/constants-s390.h" 53 54 #define ABI_USES_FUNCTION_DESCRIPTORS 0 55 56 #define ABI_PASSES_HANDLES_IN_REGS 1 57 58 // ObjectPair is defined under runtime/runtime-util.h. 59 // On 31-bit, ObjectPair == uint64_t. ABI dictates long long 60 // be returned with the lower addressed half in r2 61 // and the higher addressed half in r3. (Returns in Regs) 62 // On 64-bit, ObjectPair is a Struct. ABI dictaes Structs be 63 // returned in a storage buffer allocated by the caller, 64 // with the address of this buffer passed as a hidden 65 // argument in r2. (Does NOT return in Regs) 66 // For x86 linux, ObjectPair is returned in registers. 67 #if V8_TARGET_ARCH_S390X 68 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 0 69 #else 70 #define ABI_RETURNS_OBJECTPAIR_IN_REGS 1 71 #endif 72 73 #define ABI_CALL_VIA_IP 1 74 75 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC 76 77 namespace v8 { 78 namespace internal { 79 80 // clang-format off 81 #define GENERAL_REGISTERS(V) \ 82 V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ 83 V(r8) V(r9) V(r10) V(fp) V(ip) V(r13) V(r14) V(sp) 84 85 #define ALLOCATABLE_GENERAL_REGISTERS(V) \ 86 V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \ 87 V(r8) V(r9) V(r13) 88 89 #define DOUBLE_REGISTERS(V) \ 90 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 91 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) 92 93 #define FLOAT_REGISTERS DOUBLE_REGISTERS 94 #define SIMD128_REGISTERS DOUBLE_REGISTERS 95 96 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \ 97 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \ 98 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) V(d0) 99 // clang-format on 100 101 // CPU Registers. 102 // 103 // 1) We would prefer to use an enum, but enum values are assignment- 104 // compatible with int, which has caused code-generation bugs. 105 // 106 // 2) We would prefer to use a class instead of a struct but we don't like 107 // the register initialization to depend on the particular initialization 108 // order (which appears to be different on OS X, Linux, and Windows for the 109 // installed versions of C++ we tried). Using a struct permits C-style 110 // "initialization". Also, the Register objects cannot be const as this 111 // forces initialization stubs in MSVC, making us dependent on initialization 112 // order. 113 // 114 // 3) By not using an enum, we are possibly preventing the compiler from 115 // doing certain constant folds, which may significantly reduce the 116 // code generated for some assembly instructions (because they boil down 117 // to a few constants). If this is a problem, we could change the code 118 // such that we use an enum in optimized mode, and the struct in debug 119 // mode. This way we get the compile-time error checking in debug mode 120 // and best performance in optimized code. 121 122 struct Register { 123 enum Code { 124 #define REGISTER_CODE(R) kCode_##R, 125 GENERAL_REGISTERS(REGISTER_CODE) 126 #undef REGISTER_CODE 127 kAfterLast, 128 kCode_no_reg = -1 129 }; 130 static const int kNumRegisters = Code::kAfterLast; 131 132 #define REGISTER_COUNT(R) 1 + 133 static const int kNumAllocatable = 134 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT) 0; 135 #undef REGISTER_COUNT 136 137 #define REGISTER_BIT(R) 1 << kCode_##R | 138 static const RegList kAllocatable = 139 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT) 0; 140 #undef REGISTER_BIT 141 from_codeRegister142 static Register from_code(int code) { 143 DCHECK(code >= 0); 144 DCHECK(code < kNumRegisters); 145 Register r = {code}; 146 return r; 147 } 148 is_validRegister149 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } isRegister150 bool is(Register reg) const { return reg_code == reg.reg_code; } codeRegister151 int code() const { 152 DCHECK(is_valid()); 153 return reg_code; 154 } bitRegister155 int bit() const { 156 DCHECK(is_valid()); 157 return 1 << reg_code; 158 } 159 set_codeRegister160 void set_code(int code) { 161 reg_code = code; 162 DCHECK(is_valid()); 163 } 164 165 #if V8_TARGET_LITTLE_ENDIAN 166 static const int kMantissaOffset = 0; 167 static const int kExponentOffset = 4; 168 #else 169 static const int kMantissaOffset = 4; 170 static const int kExponentOffset = 0; 171 #endif 172 173 // Unfortunately we can't make this private in a struct. 174 int reg_code; 175 }; 176 177 typedef struct Register Register; 178 179 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R}; 180 GENERAL_REGISTERS(DECLARE_REGISTER) 181 #undef DECLARE_REGISTER 182 const Register no_reg = {Register::kCode_no_reg}; 183 184 // Register aliases 185 const Register kLithiumScratch = r1; // lithium scratch. 186 const Register kRootRegister = r10; // Roots array pointer. 187 const Register cp = r13; // JavaScript context pointer. 188 189 static const bool kSimpleFPAliasing = true; 190 static const bool kSimdMaskRegisters = false; 191 192 // Double word FP register. 193 struct DoubleRegister { 194 enum Code { 195 #define REGISTER_CODE(R) kCode_##R, 196 DOUBLE_REGISTERS(REGISTER_CODE) 197 #undef REGISTER_CODE 198 kAfterLast, 199 kCode_no_reg = -1 200 }; 201 202 static const int kNumRegisters = Code::kAfterLast; 203 static const int kMaxNumRegisters = kNumRegisters; 204 is_validDoubleRegister205 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; } isDoubleRegister206 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; } 207 codeDoubleRegister208 int code() const { 209 DCHECK(is_valid()); 210 return reg_code; 211 } 212 bitDoubleRegister213 int bit() const { 214 DCHECK(is_valid()); 215 return 1 << reg_code; 216 } 217 from_codeDoubleRegister218 static DoubleRegister from_code(int code) { 219 DoubleRegister r = {code}; 220 return r; 221 } 222 223 int reg_code; 224 }; 225 226 typedef DoubleRegister FloatRegister; 227 228 // TODO(john.yan) Define SIMD registers. 229 typedef DoubleRegister Simd128Register; 230 231 #define DECLARE_REGISTER(R) \ 232 const DoubleRegister R = {DoubleRegister::kCode_##R}; 233 DOUBLE_REGISTERS(DECLARE_REGISTER) 234 #undef DECLARE_REGISTER 235 const Register no_dreg = {Register::kCode_no_reg}; 236 237 // Aliases for double registers. Defined using #define instead of 238 // "static const DoubleRegister&" because Clang complains otherwise when a 239 // compilation unit that includes this header doesn't use the variables. 240 #define kDoubleRegZero d14 241 #define kScratchDoubleReg d13 242 243 Register ToRegister(int num); 244 245 // Coprocessor register 246 struct CRegister { is_validCRegister247 bool is_valid() const { return 0 <= reg_code && reg_code < 8; } isCRegister248 bool is(CRegister creg) const { return reg_code == creg.reg_code; } codeCRegister249 int code() const { 250 DCHECK(is_valid()); 251 return reg_code; 252 } bitCRegister253 int bit() const { 254 DCHECK(is_valid()); 255 return 1 << reg_code; 256 } 257 258 // Unfortunately we can't make this private in a struct. 259 int reg_code; 260 }; 261 262 const CRegister no_creg = {-1}; 263 264 const CRegister cr0 = {0}; 265 const CRegister cr1 = {1}; 266 const CRegister cr2 = {2}; 267 const CRegister cr3 = {3}; 268 const CRegister cr4 = {4}; 269 const CRegister cr5 = {5}; 270 const CRegister cr6 = {6}; 271 const CRegister cr7 = {7}; 272 273 // ----------------------------------------------------------------------------- 274 // Machine instruction Operands 275 276 #if V8_TARGET_ARCH_S390X 277 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64; 278 #else 279 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32; 280 #endif 281 282 // Class Operand represents a shifter operand in data processing instructions 283 // defining immediate numbers and masks 284 typedef uint8_t Length; 285 286 struct Mask { 287 uint8_t mask; valueMask288 uint8_t value() { return mask; } from_valueMask289 static Mask from_value(uint8_t input) { 290 DCHECK(input <= 0x0F); 291 Mask m = {input}; 292 return m; 293 } 294 }; 295 296 class Operand BASE_EMBEDDED { 297 public: 298 // immediate 299 INLINE(explicit Operand(intptr_t immediate, 300 RelocInfo::Mode rmode = kRelocInfo_NONEPTR)); INLINE(static Operand Zero ())301 INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); } 302 INLINE(explicit Operand(const ExternalReference& f)); 303 explicit Operand(Handle<Object> handle); 304 INLINE(explicit Operand(Smi* value)); 305 306 // rm 307 INLINE(explicit Operand(Register rm)); 308 309 // Return true if this is a register operand. 310 INLINE(bool is_reg() const); 311 312 bool must_output_reloc_info(const Assembler* assembler) const; 313 immediate()314 inline intptr_t immediate() const { 315 DCHECK(!rm_.is_valid()); 316 return imm_; 317 } 318 setBits(int n)319 inline void setBits(int n) { 320 imm_ = (static_cast<uint32_t>(imm_) << (32 - n)) >> (32 - n); 321 } 322 rm()323 Register rm() const { return rm_; } 324 325 private: 326 Register rm_; 327 intptr_t imm_; // valid if rm_ == no_reg 328 RelocInfo::Mode rmode_; 329 330 friend class Assembler; 331 friend class MacroAssembler; 332 }; 333 334 typedef int32_t Disp; 335 336 // Class MemOperand represents a memory operand in load and store instructions 337 // On S390, we have various flavours of memory operands: 338 // 1) a base register + 16 bit unsigned displacement 339 // 2) a base register + index register + 16 bit unsigned displacement 340 // 3) a base register + index register + 20 bit signed displacement 341 class MemOperand BASE_EMBEDDED { 342 public: 343 explicit MemOperand(Register rx, Disp offset = 0); 344 explicit MemOperand(Register rx, Register rb, Disp offset = 0); 345 offset()346 int32_t offset() const { return offset_; } getDisplacement()347 uint32_t getDisplacement() const { return offset(); } 348 349 // Base register rb()350 Register rb() const { 351 DCHECK(!baseRegister.is(no_reg)); 352 return baseRegister; 353 } 354 getBaseRegister()355 Register getBaseRegister() const { return rb(); } 356 357 // Index Register rx()358 Register rx() const { 359 DCHECK(!indexRegister.is(no_reg)); 360 return indexRegister; 361 } getIndexRegister()362 Register getIndexRegister() const { return rx(); } 363 364 private: 365 Register baseRegister; // base 366 Register indexRegister; // index 367 int32_t offset_; // offset 368 369 friend class Assembler; 370 }; 371 372 class DeferredRelocInfo { 373 public: DeferredRelocInfo()374 DeferredRelocInfo() {} DeferredRelocInfo(int position,RelocInfo::Mode rmode,intptr_t data)375 DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data) 376 : position_(position), rmode_(rmode), data_(data) {} 377 position()378 int position() const { return position_; } rmode()379 RelocInfo::Mode rmode() const { return rmode_; } data()380 intptr_t data() const { return data_; } 381 382 private: 383 int position_; 384 RelocInfo::Mode rmode_; 385 intptr_t data_; 386 }; 387 388 class Assembler : public AssemblerBase { 389 public: 390 // Create an assembler. Instructions and relocation information are emitted 391 // into a buffer, with the instructions starting from the beginning and the 392 // relocation information starting from the end of the buffer. See CodeDesc 393 // for a detailed comment on the layout (globals.h). 394 // 395 // If the provided buffer is NULL, the assembler allocates and grows its own 396 // buffer, and buffer_size determines the initial buffer size. The buffer is 397 // owned by the assembler and deallocated upon destruction of the assembler. 398 // 399 // If the provided buffer is not NULL, the assembler uses the provided buffer 400 // for code generation and assumes its size to be buffer_size. If the buffer 401 // is too small, a fatal error occurs. No deallocation of the buffer is done 402 // upon destruction of the assembler. 403 Assembler(Isolate* isolate, void* buffer, int buffer_size); ~Assembler()404 virtual ~Assembler() {} 405 406 // GetCode emits any pending (non-emitted) code and fills the descriptor 407 // desc. GetCode() is idempotent; it returns the same result if no other 408 // Assembler functions are invoked in between GetCode() calls. 409 void GetCode(CodeDesc* desc); 410 411 // Label operations & relative jumps (PPUM Appendix D) 412 // 413 // Takes a branch opcode (cc) and a label (L) and generates 414 // either a backward branch or a forward branch and links it 415 // to the label fixup chain. Usage: 416 // 417 // Label L; // unbound label 418 // j(cc, &L); // forward branch to unbound label 419 // bind(&L); // bind label to the current pc 420 // j(cc, &L); // backward branch to bound label 421 // bind(&L); // illegal: a label may be bound only once 422 // 423 // Note: The same Label can be used for forward and backward branches 424 // but it may be bound only once. 425 426 void bind(Label* L); // binds an unbound label L to the current code position 427 428 // Links a label at the current pc_offset(). If already bound, returns the 429 // bound position. If already linked, returns the position of the prior link. 430 // Otherwise, returns the current pc_offset(). 431 int link(Label* L); 432 433 // Determines if Label is bound and near enough so that a single 434 // branch instruction can be used to reach it. 435 bool is_near(Label* L, Condition cond); 436 437 // Returns the branch offset to the given label from the current code position 438 // Links the label to the current position if it is still unbound branch_offset(Label * L)439 int branch_offset(Label* L) { return link(L) - pc_offset(); } 440 441 // Puts a labels target address at the given position. 442 // The high 8 bits are set to zero. 443 void label_at_put(Label* L, int at_offset); 444 void load_label_offset(Register r1, Label* L); 445 446 // Read/Modify the code target address in the branch/call instruction at pc. 447 INLINE(static Address target_address_at(Address pc, Address constant_pool)); 448 INLINE(static void set_target_address_at( 449 Isolate* isolate, Address pc, Address constant_pool, Address target, 450 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); 451 INLINE(static Address target_address_at(Address pc, Code* code)); 452 INLINE(static void set_target_address_at( 453 Isolate* isolate, Address pc, Code* code, Address target, 454 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)); 455 456 // Return the code target address at a call site from the return address 457 // of that call in the instruction stream. 458 inline static Address target_address_from_return_address(Address pc); 459 460 // Given the address of the beginning of a call, return the address 461 // in the instruction stream that the call will return to. 462 INLINE(static Address return_address_from_call_start(Address pc)); 463 464 inline Handle<Object> code_target_object_handle_at(Address pc); 465 // This sets the branch destination. 466 // This is for calls and branches within generated code. 467 inline static void deserialization_set_special_target_at( 468 Isolate* isolate, Address instruction_payload, Code* code, 469 Address target); 470 471 // This sets the internal reference at the pc. 472 inline static void deserialization_set_target_internal_reference_at( 473 Isolate* isolate, Address pc, Address target, 474 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE); 475 476 // Here we are patching the address in the IIHF/IILF instruction pair. 477 // These values are used in the serialization process and must be zero for 478 // S390 platform, as Code, Embedded Object or External-reference pointers 479 // are split across two consecutive instructions and don't exist separately 480 // in the code, so the serializer should not step forwards in memory after 481 // a target is resolved and written. 482 static const int kSpecialTargetSize = 0; 483 484 // Number of bytes for instructions used to store pointer sized constant. 485 #if V8_TARGET_ARCH_S390X 486 static const int kBytesForPtrConstant = 12; // IIHF + IILF 487 #else 488 static const int kBytesForPtrConstant = 6; // IILF 489 #endif 490 491 // Distance between the instruction referring to the address of the call 492 // target and the return address. 493 494 // Offset between call target address and return address 495 // for BRASL calls 496 // Patch will be appiled to other FIXED_SEQUENCE call 497 static const int kCallTargetAddressOffset = 6; 498 499 // The length of FIXED_SEQUENCE call 500 // iihf r8, <address_hi> // <64-bit only> 501 // iilf r8, <address_lo> 502 // basr r14, r8 503 #if V8_TARGET_ARCH_S390X 504 static const int kCallSequenceLength = 14; 505 #else 506 static const int kCallSequenceLength = 8; 507 #endif 508 509 // This is the length of the BreakLocationIterator::SetDebugBreakAtReturn() 510 // code patch FIXED_SEQUENCE in bytes! 511 // JS Return Sequence = Call Sequence + BKPT 512 // static const int kJSReturnSequenceLength = kCallSequenceLength + 2; 513 514 // This is the length of the code sequence from SetDebugBreakAtSlot() 515 // FIXED_SEQUENCE in bytes! 516 static const int kDebugBreakSlotLength = kCallSequenceLength; 517 static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset; 518 519 // Length to patch between the start of the JS return sequence 520 // from SetDebugBreakAtReturn and the address from 521 // break_address_from_return_address. 522 // 523 // frame->pc() in Debug::SetAfterBreakTarget will point to BKPT in 524 // JS return sequence, so the length to patch will not include BKPT 525 // instruction length. 526 // static const int kPatchReturnSequenceAddressOffset = 527 // kCallSequenceLength - kPatchDebugBreakSlotReturnOffset; 528 529 // Length to patch between the start of the FIXED call sequence from 530 // SetDebugBreakAtSlot() and the the address from 531 // break_address_from_return_address. 532 static const int kPatchDebugBreakSlotAddressOffset = 533 kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset; 534 encode_crbit(const CRegister & cr,enum CRBit crbit)535 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) { 536 return ((cr.code() * CRWIDTH) + crbit); 537 } 538 539 // --------------------------------------------------------------------------- 540 // Code generation 541 542 template <class T, int size, int lo, int hi> getfield(T value)543 inline T getfield(T value) { 544 DCHECK(lo < hi); 545 DCHECK(size > 0); 546 int mask = hi - lo; 547 int shift = size * 8 - hi; 548 uint32_t mask_value = (mask == 32) ? 0xffffffff : (1 << mask) - 1; 549 return (value & mask_value) << shift; 550 } 551 552 // Declare generic instruction formats by fields e_format(Opcode opcode)553 inline void e_format(Opcode opcode) { 554 emit2bytes(getfield<uint16_t, 2, 0, 16>(opcode)); 555 } 556 i_format(Opcode opcode,int f1)557 inline void i_format(Opcode opcode, int f1) { 558 emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) | 559 getfield<uint16_t, 2, 8, 16>(f1)); 560 } 561 ie_format(Opcode opcode,int f1,int f2)562 inline void ie_format(Opcode opcode, int f1, int f2) { 563 emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) | 564 getfield<uint32_t, 4, 24, 28>(f1) | 565 getfield<uint32_t, 4, 28, 32>(f2)); 566 } mii_format(Opcode opcode,int f1,int f2,int f3)567 inline void mii_format(Opcode opcode, int f1, int f2, int f3) { 568 emit6bytes( 569 getfield<uint64_t, 6, 0, 8>(opcode) | getfield<uint64_t, 6, 8, 12>(f1) | 570 getfield<uint64_t, 6, 12, 24>(f2) | getfield<uint64_t, 6, 24, 48>(f3)); 571 } 572 ri_format(Opcode opcode,int f1,int f2)573 inline void ri_format(Opcode opcode, int f1, int f2) { 574 uint32_t op1 = opcode >> 4; 575 uint32_t op2 = opcode & 0xf; 576 emit4bytes( 577 getfield<uint32_t, 4, 0, 8>(op1) | getfield<uint32_t, 4, 8, 12>(f1) | 578 getfield<uint32_t, 4, 12, 16>(op2) | getfield<uint32_t, 4, 16, 32>(f2)); 579 } 580 rie_1_format(Opcode opcode,int f1,int f2,int f3,int f4)581 inline void rie_1_format(Opcode opcode, int f1, int f2, int f3, int f4) { 582 uint32_t op1 = opcode >> 8; 583 uint32_t op2 = opcode & 0xff; 584 emit6bytes( 585 getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) | 586 getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 32>(f3) | 587 getfield<uint64_t, 6, 32, 36>(f4) | getfield<uint64_t, 6, 40, 48>(op2)); 588 } 589 rie_2_format(Opcode opcode,int f1,int f2,int f3,int f4)590 inline void rie_2_format(Opcode opcode, int f1, int f2, int f3, int f4) { 591 uint32_t op1 = opcode >> 8; 592 uint32_t op2 = opcode & 0xff; 593 emit6bytes( 594 getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) | 595 getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 32>(f3) | 596 getfield<uint64_t, 6, 32, 40>(f4) | getfield<uint64_t, 6, 40, 48>(op2)); 597 } 598 rie_3_format(Opcode opcode,int f1,int f2,int f3,int f4,int f5)599 inline void rie_3_format(Opcode opcode, int f1, int f2, int f3, int f4, 600 int f5) { 601 uint32_t op1 = opcode >> 8; 602 uint32_t op2 = opcode & 0xff; 603 emit6bytes( 604 getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) | 605 getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 24>(f3) | 606 getfield<uint64_t, 6, 24, 32>(f4) | getfield<uint64_t, 6, 32, 40>(f5) | 607 getfield<uint64_t, 6, 40, 48>(op2)); 608 } 609 610 #define DECLARE_S390_RIL_AB_INSTRUCTIONS(name, op_name, op_value) \ 611 template <class R1> \ 612 inline void name(R1 r1, const Operand& i2) { \ 613 ril_format(op_name, r1.code(), i2.immediate()); \ 614 } 615 #define DECLARE_S390_RIL_C_INSTRUCTIONS(name, op_name, op_value) \ 616 inline void name(Condition m1, const Operand& i2) { \ 617 ril_format(op_name, m1, i2.immediate()); \ 618 } 619 ril_format(Opcode opcode,int f1,int f2)620 inline void ril_format(Opcode opcode, int f1, int f2) { 621 uint32_t op1 = opcode >> 4; 622 uint32_t op2 = opcode & 0xf; 623 emit6bytes( 624 getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) | 625 getfield<uint64_t, 6, 12, 16>(op2) | getfield<uint64_t, 6, 16, 48>(f2)); 626 } 627 S390_RIL_A_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS) S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS)628 S390_RIL_B_OPCODE_LIST(DECLARE_S390_RIL_AB_INSTRUCTIONS) 629 S390_RIL_C_OPCODE_LIST(DECLARE_S390_RIL_C_INSTRUCTIONS) 630 #undef DECLARE_S390_RIL_AB_INSTRUCTIONS 631 #undef DECLARE_S390_RIL_C_INSTRUCTIONS 632 633 inline void ris_format(Opcode opcode, int f1, int f2, int f3, int f4, 634 int f5) { 635 uint32_t op1 = opcode >> 8; 636 uint32_t op2 = opcode & 0xff; 637 emit6bytes( 638 getfield<uint64_t, 6, 0, 8>(op1) | getfield<uint64_t, 6, 8, 12>(f1) | 639 getfield<uint64_t, 6, 12, 16>(f2) | getfield<uint64_t, 6, 16, 20>(f3) | 640 getfield<uint64_t, 6, 20, 32>(f4) | getfield<uint64_t, 6, 32, 40>(f5) | 641 getfield<uint64_t, 6, 40, 48>(op2)); 642 } 643 644 #define DECLARE_S390_RR_INSTRUCTIONS(name, op_name, op_value) \ 645 inline void name(Register r1, Register r2) { \ 646 rr_format(op_name, r1.code(), r2.code()); \ 647 } \ 648 inline void name(DoubleRegister r1, DoubleRegister r2) { \ 649 rr_format(op_name, r1.code(), r2.code()); \ 650 } \ 651 inline void name(Condition m1, Register r2) { \ 652 rr_format(op_name, m1, r2.code()); \ 653 } 654 rr_format(Opcode opcode,int f1,int f2)655 inline void rr_format(Opcode opcode, int f1, int f2) { 656 emit2bytes(getfield<uint16_t, 2, 0, 8>(opcode) | 657 getfield<uint16_t, 2, 8, 12>(f1) | 658 getfield<uint16_t, 2, 12, 16>(f2)); 659 } S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS)660 S390_RR_OPCODE_LIST(DECLARE_S390_RR_INSTRUCTIONS) 661 #undef DECLARE_S390_RR_INSTRUCTIONS 662 663 #define DECLARE_S390_RRD_INSTRUCTIONS(name, op_name, op_value) \ 664 template <class R1, class R2, class R3> \ 665 inline void name(R1 r1, R3 r3, R2 r2) { \ 666 rrd_format(op_name, r1.code(), r3.code(), r2.code()); \ 667 } 668 inline void rrd_format(Opcode opcode, int f1, int f2, int f3) { 669 emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) | 670 getfield<uint32_t, 4, 16, 20>(f1) | 671 getfield<uint32_t, 4, 24, 28>(f2) | 672 getfield<uint32_t, 4, 28, 32>(f3)); 673 } S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS)674 S390_RRD_OPCODE_LIST(DECLARE_S390_RRD_INSTRUCTIONS) 675 #undef DECLARE_S390_RRD_INSTRUCTIONS 676 677 #define DECLARE_S390_RRE_INSTRUCTIONS(name, op_name, op_value) \ 678 template <class R1, class R2> \ 679 inline void name(R1 r1, R2 r2) { \ 680 rre_format(op_name, r1.code(), r2.code()); \ 681 } 682 inline void rre_format(Opcode opcode, int f1, int f2) { 683 emit4bytes(getfield<uint32_t, 4, 0, 16>(opcode) | 684 getfield<uint32_t, 4, 24, 28>(f1) | 685 getfield<uint32_t, 4, 28, 32>(f2)); 686 } S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS)687 S390_RRE_OPCODE_LIST(DECLARE_S390_RRE_INSTRUCTIONS) 688 // Special format 689 void lzdr(DoubleRegister r1) { rre_format(LZDR, r1.code(), 0); } 690 #undef DECLARE_S390_RRE_INSTRUCTIONS 691 rrf_format(Opcode opcode,int f1,int f2,int f3,int f4)692 inline void rrf_format(Opcode opcode, int f1, int f2, int f3, int f4) { 693 emit4bytes( 694 getfield<uint32_t, 4, 0, 16>(opcode) | 695 getfield<uint32_t, 4, 16, 20>(f1) | getfield<uint32_t, 4, 20, 24>(f2) | 696 getfield<uint32_t, 4, 24, 28>(f3) | getfield<uint32_t, 4, 28, 32>(f4)); 697 } 698 699 #define DECLARE_S390_RX_INSTRUCTIONS(name, op_name, op_value) \ 700 template <class R1> \ 701 inline void name(R1 r1, Register x2, Register b2, Disp d2) { \ 702 rx_format(op_name, r1.code(), x2.code(), b2.code(), d2); \ 703 } \ 704 template <class R1> \ 705 inline void name(R1 r1, const MemOperand& opnd) { \ 706 name(r1, opnd.getIndexRegister(), \ 707 opnd.getBaseRegister(), opnd.getDisplacement()); \ 708 } 709 rx_format(Opcode opcode,int f1,int f2,int f3,int f4)710 inline void rx_format(Opcode opcode, int f1, int f2, int f3, int f4) { 711 DCHECK(is_uint8(opcode)); 712 DCHECK(is_uint12(f4)); 713 emit4bytes(getfield<uint32_t, 4, 0, 8>(opcode) | 714 getfield<uint32_t, 4, 8, 12>(f1) | 715 getfield<uint32_t, 4, 12, 16>(f2) | 716 getfield<uint32_t, 4, 16, 20>(f3) | 717 getfield<uint32_t, 4, 20, 32>(f4)); 718 } S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS)719 S390_RX_A_OPCODE_LIST(DECLARE_S390_RX_INSTRUCTIONS) 720 721 void bc(Condition cond, const MemOperand& opnd) { 722 bc(cond, opnd.getIndexRegister(), 723 opnd.getBaseRegister(), opnd.getDisplacement()); 724 } bc(Condition cond,Register x2,Register b2,Disp d2)725 void bc(Condition cond, Register x2, Register b2, Disp d2) { 726 rx_format(BC, cond, x2.code(), b2.code(), d2); 727 } 728 #undef DECLARE_S390_RX_INSTRUCTIONS 729 730 #define DECLARE_S390_RXY_INSTRUCTIONS(name, op_name, op_value) \ 731 template <class R1, class R2> \ 732 inline void name(R1 r1, R2 r2, Register b2, Disp d2) { \ 733 rxy_format(op_name, r1.code(), r2.code(), b2.code(), d2); \ 734 } \ 735 template <class R1> \ 736 inline void name(R1 r1, const MemOperand& opnd) { \ 737 name(r1, opnd.getIndexRegister(), \ 738 opnd.getBaseRegister(), opnd.getDisplacement()); \ 739 } 740 rxy_format(Opcode opcode,int f1,int f2,int f3,int f4)741 inline void rxy_format(Opcode opcode, int f1, int f2, int f3, int f4) { 742 DCHECK(is_uint16(opcode)); 743 DCHECK(is_int20(f4)); 744 emit6bytes(getfield<uint64_t, 6, 0, 8>(opcode >> 8) | 745 getfield<uint64_t, 6, 8, 12>(f1) | 746 getfield<uint64_t, 6, 12, 16>(f2) | 747 getfield<uint64_t, 6, 16, 20>(f3) | 748 getfield<uint64_t, 6, 20, 32>(f4 & 0x0fff) | 749 getfield<uint64_t, 6, 32, 40>(f4 >> 12) | 750 getfield<uint64_t, 6, 40, 48>(opcode & 0x00ff)); 751 } S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS)752 S390_RXY_A_OPCODE_LIST(DECLARE_S390_RXY_INSTRUCTIONS) 753 754 void pfd(Condition cond, const MemOperand& opnd) { 755 pfd(cond, opnd.getIndexRegister(), 756 opnd.getBaseRegister(), opnd.getDisplacement()); 757 } pfd(Condition cond,Register x2,Register b2,Disp d2)758 void pfd(Condition cond, Register x2, Register b2, Disp d2) { 759 rxy_format(PFD, cond, x2.code(), b2.code(), d2); 760 } 761 #undef DECLARE_S390_RXY_INSTRUCTIONS 762 763 // Helper for unconditional branch to Label with update to save register b(Register r,Label * l)764 void b(Register r, Label* l) { 765 int32_t halfwords = branch_offset(l) / 2; 766 brasl(r, Operand(halfwords)); 767 } 768 769 // Conditional Branch Instruction - Generates either BRC / BRCL 770 void branchOnCond(Condition c, int branch_offset, bool is_bound = false); 771 772 // Helpers for conditional branch to Label 773 void b(Condition cond, Label* l, Label::Distance dist = Label::kFar) { 774 branchOnCond(cond, branch_offset(l), 775 l->is_bound() || (dist == Label::kNear)); 776 } 777 778 void bc_short(Condition cond, Label* l, Label::Distance dist = Label::kFar) { 779 b(cond, l, Label::kNear); 780 } 781 // Helpers for conditional branch to Label 782 void beq(Label* l, Label::Distance dist = Label::kFar) { b(eq, l, dist); } 783 void bne(Label* l, Label::Distance dist = Label::kFar) { b(ne, l, dist); } 784 void blt(Label* l, Label::Distance dist = Label::kFar) { b(lt, l, dist); } 785 void ble(Label* l, Label::Distance dist = Label::kFar) { b(le, l, dist); } 786 void bgt(Label* l, Label::Distance dist = Label::kFar) { b(gt, l, dist); } 787 void bge(Label* l, Label::Distance dist = Label::kFar) { b(ge, l, dist); } 788 void b(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); } 789 void jmp(Label* l, Label::Distance dist = Label::kFar) { b(al, l, dist); } 790 void bunordered(Label* l, Label::Distance dist = Label::kFar) { 791 b(unordered, l, dist); 792 } 793 void bordered(Label* l, Label::Distance dist = Label::kFar) { 794 b(ordered, l, dist); 795 } 796 797 // Helpers for conditional indirect branch off register b(Condition cond,Register r)798 void b(Condition cond, Register r) { bcr(cond, r); } beq(Register r)799 void beq(Register r) { b(eq, r); } bne(Register r)800 void bne(Register r) { b(ne, r); } blt(Register r)801 void blt(Register r) { b(lt, r); } ble(Register r)802 void ble(Register r) { b(le, r); } bgt(Register r)803 void bgt(Register r) { b(gt, r); } bge(Register r)804 void bge(Register r) { b(ge, r); } b(Register r)805 void b(Register r) { b(al, r); } jmp(Register r)806 void jmp(Register r) { b(al, r); } bunordered(Register r)807 void bunordered(Register r) { b(unordered, r); } bordered(Register r)808 void bordered(Register r) { b(ordered, r); } 809 810 // --------------------------------------------------------------------------- 811 // Code generation 812 813 // Insert the smallest number of nop instructions 814 // possible to align the pc offset to a multiple 815 // of m. m must be a power of 2 (>= 4). 816 void Align(int m); 817 // Insert the smallest number of zero bytes possible to align the pc offset 818 // to a mulitple of m. m must be a power of 2 (>= 2). 819 void DataAlign(int m); 820 // Aligns code to something that's optimal for a jump target for the platform. 821 void CodeTargetAlign(); 822 breakpoint(bool do_print)823 void breakpoint(bool do_print) { 824 if (do_print) { 825 PrintF("DebugBreak is inserted to %p\n", static_cast<void*>(pc_)); 826 } 827 #if V8_HOST_ARCH_64_BIT 828 int64_t value = reinterpret_cast<uint64_t>(&v8::base::OS::DebugBreak); 829 int32_t hi_32 = static_cast<int64_t>(value) >> 32; 830 int32_t lo_32 = static_cast<int32_t>(value); 831 832 iihf(r1, Operand(hi_32)); 833 iilf(r1, Operand(lo_32)); 834 #else 835 iilf(r1, Operand(reinterpret_cast<uint32_t>(&v8::base::OS::DebugBreak))); 836 #endif 837 basr(r14, r1); 838 } 839 840 void call(Handle<Code> target, RelocInfo::Mode rmode, 841 TypeFeedbackId ast_id = TypeFeedbackId::None()); 842 void jump(Handle<Code> target, RelocInfo::Mode rmode, Condition cond); 843 844 // S390 instruction generation 845 #define I_FORM(name) void name(const Operand& i) 846 847 #define RR_FORM(name) void name(Register r1, Register r2) 848 849 #define RR2_FORM(name) void name(Condition m1, Register r2) 850 851 #define RI1_FORM(name) void name(Register r, const Operand& i) 852 853 #define RI2_FORM(name) void name(Condition m, const Operand& i) 854 855 #define RIE_FORM(name) void name(Register r1, Register R3, const Operand& i) 856 857 #define RIE_F_FORM(name) \ 858 void name(Register r1, Register r2, const Operand& i3, const Operand& i4, \ 859 const Operand& i5) 860 861 #define RXE_FORM(name) \ 862 void name(Register r1, const MemOperand& opnd); \ 863 void name(Register r1, Register b2, Register x2, Disp d2) 864 865 #define RXF_FORM(name) \ 866 void name(Register r1, Register r3, const MemOperand& opnd); \ 867 void name(Register r1, Register r3, Register b2, Register x2, Disp d2) 868 869 #define RSI_FORM(name) void name(Register r1, Register r3, const Operand& i) 870 871 #define RIS_FORM(name) \ 872 void name(Register r1, Condition m3, Register b4, Disp d4, \ 873 const Operand& i2); \ 874 void name(Register r1, const Operand& i2, Condition m3, \ 875 const MemOperand& opnd) 876 877 #define SI_FORM(name) \ 878 void name(const MemOperand& opnd, const Operand& i); \ 879 void name(const Operand& i2, Register b1, Disp d1) 880 881 #define SIL_FORM(name) \ 882 void name(Register b1, Disp d1, const Operand& i2); \ 883 void name(const MemOperand& opnd, const Operand& i2) 884 885 #define RRF1_FORM(name) void name(Register r1, Register r2, Register r3) 886 887 #define RRF2_FORM(name) void name(Condition m1, Register r1, Register r2) 888 889 #define RRF3_FORM(name) \ 890 void name(Register r3, Condition m4, Register r1, Register r2) 891 892 #define RS1_FORM(name) \ 893 void name(Register r1, Register r3, const MemOperand& opnd); \ 894 void name(Register r1, Register r3, Register b2, Disp d2) 895 896 #define RS2_FORM(name) \ 897 void name(Register r1, Condition m3, const MemOperand& opnd); \ 898 void name(Register r1, Condition m3, Register b2, Disp d2) 899 900 #define RSE_FORM(name) \ 901 void name(Register r1, Register r3, const MemOperand& opnd); \ 902 void name(Register r1, Register r3, Register b2, Disp d2) 903 904 #define RSL_FORM(name) \ 905 void name(Length l, Register b2, Disp d2); \ 906 void name(const MemOperand& opnd) 907 908 #define RSY1_FORM(name) \ 909 void name(Register r1, Register r3, Register b2, Disp d2); \ 910 void name(Register r1, Register r3, const MemOperand& opnd) 911 912 #define RSY2_FORM(name) \ 913 void name(Register r1, Condition m3, Register b2, Disp d2); \ 914 void name(Register r1, Condition m3, const MemOperand& opnd) 915 916 #define RRS_FORM(name) \ 917 void name(Register r1, Register r2, Register b4, Disp d4, Condition m3); \ 918 void name(Register r1, Register r2, Condition m3, const MemOperand& opnd) 919 920 #define S_FORM(name) \ 921 void name(Register b2, Disp d2); \ 922 void name(const MemOperand& opnd) 923 924 #define SIY_FORM(name) \ 925 void name(const Operand& i2, Register b1, Disp d1); \ 926 void name(const MemOperand& opnd, const Operand& i) 927 928 #define SS1_FORM(name) \ 929 void name(Register b1, Disp d1, Register b3, Disp d2, Length length); \ 930 void name(const MemOperand& opnd1, const MemOperand& opnd2, Length length) 931 932 #define SS2_FORM(name) \ 933 void name(const MemOperand& opnd1, const MemOperand& opnd2, Length length1, \ 934 Length length2); \ 935 void name(Register b1, Disp d1, Register b2, Disp d2, Length l1, Length l2) 936 937 #define SS3_FORM(name) \ 938 void name(const MemOperand& opnd1, const MemOperand& opnd2, Length length); \ 939 void name(const Operand& i3, Register b1, Disp d1, Register b2, Disp d2, \ 940 Length l1) 941 942 #define SS4_FORM(name) \ 943 void name(const MemOperand& opnd1, const MemOperand& opnd2); \ 944 void name(Register r1, Register r3, Register b1, Disp d1, Register b2, \ 945 Disp d2) 946 947 #define SS5_FORM(name) \ 948 void name(const MemOperand& opnd1, const MemOperand& opnd2); \ 949 void name(Register r1, Register r3, Register b3, Disp d2, Register b4, \ 950 Disp d4) 951 952 #define SSE_FORM(name) \ 953 void name(Register b1, Disp d1, Register b2, Disp d2); \ 954 void name(const MemOperand& opnd1, const MemOperand& opnd2) 955 956 #define SSF_FORM(name) \ 957 void name(Register r3, Register b1, Disp d1, Register b2, Disp d2); \ 958 void name(Register r3, const MemOperand& opnd1, const MemOperand& opnd2) 959 960 #define DECLARE_VRR_A_INSTRUCTIONS(name, opcode_name, opcode_value) \ 961 void name(DoubleRegister v1, DoubleRegister v2, Condition m5, Condition m4, \ 962 Condition m3) { \ 963 uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \ 964 (static_cast<uint64_t>(v1.code())) * B36 | \ 965 (static_cast<uint64_t>(v2.code())) * B32 | \ 966 (static_cast<uint64_t>(m5 & 0xF)) * B20 | \ 967 (static_cast<uint64_t>(m4 & 0xF)) * B16 | \ 968 (static_cast<uint64_t>(m3 & 0xF)) * B12 | \ 969 (static_cast<uint64_t>(opcode_value & 0x00FF)); \ 970 emit6bytes(code); \ 971 } 972 S390_VRR_A_OPCODE_LIST(DECLARE_VRR_A_INSTRUCTIONS) 973 #undef DECLARE_VRR_A_INSTRUCTIONS 974 975 #define DECLARE_VRR_C_INSTRUCTIONS(name, opcode_name, opcode_value) \ 976 void name(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3, \ 977 Condition m6, Condition m5, Condition m4) { \ 978 uint64_t code = (static_cast<uint64_t>(opcode_value & 0xFF00)) * B32 | \ 979 (static_cast<uint64_t>(v1.code())) * B36 | \ 980 (static_cast<uint64_t>(v2.code())) * B32 | \ 981 (static_cast<uint64_t>(v3.code())) * B28 | \ 982 (static_cast<uint64_t>(m6 & 0xF)) * B20 | \ 983 (static_cast<uint64_t>(m5 & 0xF)) * B16 | \ 984 (static_cast<uint64_t>(m4 & 0xF)) * B12 | \ 985 (static_cast<uint64_t>(opcode_value & 0x00FF)); \ 986 emit6bytes(code); \ 987 } S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS)988 S390_VRR_C_OPCODE_LIST(DECLARE_VRR_C_INSTRUCTIONS) 989 #undef DECLARE_VRR_C_INSTRUCTIONS 990 991 // Single Element format 992 void vfa(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) { 993 vfa(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8), 994 static_cast<Condition>(3)); 995 } vfs(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)996 void vfs(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) { 997 vfs(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8), 998 static_cast<Condition>(3)); 999 } vfm(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)1000 void vfm(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) { 1001 vfm(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8), 1002 static_cast<Condition>(3)); 1003 } vfd(DoubleRegister v1,DoubleRegister v2,DoubleRegister v3)1004 void vfd(DoubleRegister v1, DoubleRegister v2, DoubleRegister v3) { 1005 vfd(v1, v2, v3, static_cast<Condition>(0), static_cast<Condition>(8), 1006 static_cast<Condition>(3)); 1007 } 1008 1009 // S390 instruction sets 1010 RXE_FORM(ddb); 1011 SS1_FORM(ed); 1012 RRF2_FORM(fidbr); 1013 RI1_FORM(iihh); 1014 RI1_FORM(iihl); 1015 RI1_FORM(iilh); 1016 RI1_FORM(iill); 1017 RSY1_FORM(loc); 1018 RXE_FORM(mdb); 1019 SS4_FORM(mvck); 1020 SSF_FORM(mvcos); 1021 SS4_FORM(mvcs); 1022 SS1_FORM(mvn); 1023 SS1_FORM(nc); 1024 SI_FORM(ni); 1025 RI1_FORM(nilh); 1026 RI1_FORM(nill); 1027 RI1_FORM(oill); 1028 RXE_FORM(sdb); 1029 RS1_FORM(srdl); 1030 RI1_FORM(tmll); 1031 SS1_FORM(tr); 1032 S_FORM(ts); 1033 1034 // Load Address Instructions 1035 void larl(Register r, Label* l); 1036 1037 // Load Instructions 1038 void lhi(Register r, const Operand& imm); 1039 void lghi(Register r, const Operand& imm); 1040 1041 // Load Multiple Instructions 1042 void lm(Register r1, Register r2, const MemOperand& src); 1043 void lmy(Register r1, Register r2, const MemOperand& src); 1044 void lmg(Register r1, Register r2, const MemOperand& src); 1045 1046 // Load On Condition Instructions 1047 void locr(Condition m3, Register r1, Register r2); 1048 void locgr(Condition m3, Register r1, Register r2); 1049 void loc(Condition m3, Register r1, const MemOperand& src); 1050 void locg(Condition m3, Register r1, const MemOperand& src); 1051 1052 // Store Instructions 1053 1054 // Store Multiple Instructions 1055 void stm(Register r1, Register r2, const MemOperand& src); 1056 void stmy(Register r1, Register r2, const MemOperand& src); 1057 void stmg(Register r1, Register r2, const MemOperand& src); 1058 1059 // Compare Instructions 1060 void chi(Register r, const Operand& opnd); 1061 void cghi(Register r, const Operand& opnd); 1062 1063 // Compare Logical Instructions 1064 void cli(const MemOperand& mem, const Operand& imm); 1065 void cliy(const MemOperand& mem, const Operand& imm); 1066 void clc(const MemOperand& opnd1, const MemOperand& opnd2, Length length); 1067 1068 // Test Under Mask Instructions 1069 void tm(const MemOperand& mem, const Operand& imm); 1070 void tmy(const MemOperand& mem, const Operand& imm); 1071 1072 // Rotate Instructions 1073 void rll(Register r1, Register r3, Register opnd); 1074 void rll(Register r1, Register r3, const Operand& opnd); 1075 void rll(Register r1, Register r3, Register r2, const Operand& opnd); 1076 void rllg(Register r1, Register r3, const Operand& opnd); 1077 void rllg(Register r1, Register r3, const Register opnd); 1078 void rllg(Register r1, Register r3, Register r2, const Operand& opnd); 1079 1080 // Shift Instructions (32) 1081 void sll(Register r1, Register opnd); 1082 void sll(Register r1, const Operand& opnd); 1083 void sllk(Register r1, Register r3, Register opnd); 1084 void sllk(Register r1, Register r3, const Operand& opnd); 1085 void srl(Register r1, Register opnd); 1086 void srl(Register r1, const Operand& opnd); 1087 void srlk(Register r1, Register r3, Register opnd); 1088 void srlk(Register r1, Register r3, const Operand& opnd); 1089 void sra(Register r1, Register opnd); 1090 void sra(Register r1, const Operand& opnd); 1091 void srak(Register r1, Register r3, Register opnd); 1092 void srak(Register r1, Register r3, const Operand& opnd); 1093 void sla(Register r1, Register opnd); 1094 void sla(Register r1, const Operand& opnd); 1095 void slak(Register r1, Register r3, Register opnd); 1096 void slak(Register r1, Register r3, const Operand& opnd); 1097 1098 // Shift Instructions (64) 1099 void sllg(Register r1, Register r3, const Operand& opnd); 1100 void sllg(Register r1, Register r3, const Register opnd); 1101 void srlg(Register r1, Register r3, const Operand& opnd); 1102 void srlg(Register r1, Register r3, const Register opnd); 1103 void srag(Register r1, Register r3, const Operand& opnd); 1104 void srag(Register r1, Register r3, const Register opnd); 1105 void srda(Register r1, const Operand& opnd); 1106 void srdl(Register r1, const Operand& opnd); 1107 void slag(Register r1, Register r3, const Operand& opnd); 1108 void slag(Register r1, Register r3, const Register opnd); 1109 void sldl(Register r1, Register b2, const Operand& opnd); 1110 void srdl(Register r1, Register b2, const Operand& opnd); 1111 void srda(Register r1, Register b2, const Operand& opnd); 1112 1113 // Rotate and Insert Selected Bits 1114 void risbg(Register dst, Register src, const Operand& startBit, 1115 const Operand& endBit, const Operand& shiftAmt, 1116 bool zeroBits = true); 1117 void risbgn(Register dst, Register src, const Operand& startBit, 1118 const Operand& endBit, const Operand& shiftAmt, 1119 bool zeroBits = true); 1120 1121 // Move Character (Mem to Mem) 1122 void mvc(const MemOperand& opnd1, const MemOperand& opnd2, uint32_t length); 1123 1124 // Branch Instructions 1125 void bras(Register r, const Operand& opnd); 1126 void brc(Condition c, const Operand& opnd); 1127 void brct(Register r1, const Operand& opnd); 1128 void brctg(Register r1, const Operand& opnd); 1129 1130 // 32-bit Add Instructions 1131 void ahi(Register r1, const Operand& opnd); 1132 void ahik(Register r1, Register r3, const Operand& opnd); 1133 void ark(Register r1, Register r2, Register r3); 1134 void asi(const MemOperand&, const Operand&); 1135 1136 // 64-bit Add Instructions 1137 void aghi(Register r1, const Operand& opnd); 1138 void aghik(Register r1, Register r3, const Operand& opnd); 1139 void agrk(Register r1, Register r2, Register r3); 1140 void agsi(const MemOperand&, const Operand&); 1141 1142 // 32-bit Add Logical Instructions 1143 void alrk(Register r1, Register r2, Register r3); 1144 1145 // 64-bit Add Logical Instructions 1146 void algrk(Register r1, Register r2, Register r3); 1147 1148 // 32-bit Subtract Instructions 1149 void srk(Register r1, Register r2, Register r3); 1150 1151 // 64-bit Subtract Instructions 1152 void sgrk(Register r1, Register r2, Register r3); 1153 1154 // 32-bit Subtract Logical Instructions 1155 void slrk(Register r1, Register r2, Register r3); 1156 1157 // 64-bit Subtract Logical Instructions 1158 void slgrk(Register r1, Register r2, Register r3); 1159 1160 // 32-bit Multiply Instructions 1161 void mhi(Register r1, const Operand& opnd); 1162 void msrkc(Register r1, Register r2, Register r3); 1163 void msgrkc(Register r1, Register r2, Register r3); 1164 1165 // 64-bit Multiply Instructions 1166 void mghi(Register r1, const Operand& opnd); 1167 1168 // Bitwise Instructions (AND / OR / XOR) 1169 void nrk(Register r1, Register r2, Register r3); 1170 void ngrk(Register r1, Register r2, Register r3); 1171 void ork(Register r1, Register r2, Register r3); 1172 void ogrk(Register r1, Register r2, Register r3); 1173 void xrk(Register r1, Register r2, Register r3); 1174 void xgrk(Register r1, Register r2, Register r3); 1175 void xc(const MemOperand& opnd1, const MemOperand& opnd2, Length length); 1176 1177 // Floating <-> Fixed Point Conversion Instructions 1178 void cdlfbr(Condition m3, Condition m4, DoubleRegister fltReg, 1179 Register fixReg); 1180 void cdlgbr(Condition m3, Condition m4, DoubleRegister fltReg, 1181 Register fixReg); 1182 void celgbr(Condition m3, Condition m4, DoubleRegister fltReg, 1183 Register fixReg); 1184 void celfbr(Condition m3, Condition m4, DoubleRegister fltReg, 1185 Register fixReg); 1186 void clfdbr(Condition m3, Condition m4, Register fixReg, 1187 DoubleRegister fltReg); 1188 void clfebr(Condition m3, Condition m4, Register fixReg, 1189 DoubleRegister fltReg); 1190 void clgdbr(Condition m3, Condition m4, Register fixReg, 1191 DoubleRegister fltReg); 1192 void clgebr(Condition m3, Condition m4, Register fixReg, 1193 DoubleRegister fltReg); 1194 void cfdbr(Condition m, Register fixReg, DoubleRegister fltReg); 1195 void cgebr(Condition m, Register fixReg, DoubleRegister fltReg); 1196 void cgdbr(Condition m, Register fixReg, DoubleRegister fltReg); 1197 void cfebr(Condition m3, Register fixReg, DoubleRegister fltReg); 1198 void cefbr(Condition m3, DoubleRegister fltReg, Register fixReg); 1199 1200 // Floating Point Compare Instructions 1201 void cdb(DoubleRegister r1, const MemOperand& opnd); 1202 void ceb(DoubleRegister r1, const MemOperand& opnd); 1203 1204 // Floating Point Arithmetic Instructions 1205 void adb(DoubleRegister r1, const MemOperand& opnd); 1206 void sdb(DoubleRegister r1, const MemOperand& opnd); 1207 void mdb(DoubleRegister r1, const MemOperand& opnd); 1208 void ddb(DoubleRegister r1, const MemOperand& opnd); 1209 void sqdb(DoubleRegister r1, const MemOperand& opnd); 1210 void ldeb(DoubleRegister r1, const MemOperand& opnd); 1211 1212 enum FIDBRA_MASK3 { 1213 FIDBRA_CURRENT_ROUNDING_MODE = 0, 1214 FIDBRA_ROUND_TO_NEAREST_AWAY_FROM_0 = 1, 1215 // ... 1216 FIDBRA_ROUND_TOWARD_0 = 5, 1217 FIDBRA_ROUND_TOWARD_POS_INF = 6, 1218 FIDBRA_ROUND_TOWARD_NEG_INF = 7 1219 }; 1220 void fiebra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3); 1221 void fidbra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3); 1222 1223 // Move integer 1224 void mvhi(const MemOperand& opnd1, const Operand& i2); 1225 void mvghi(const MemOperand& opnd1, const Operand& i2); 1226 1227 // Exception-generating instructions and debugging support 1228 void stop(const char* msg, Condition cond = al, 1229 int32_t code = kDefaultStopCode, CRegister cr = cr7); 1230 1231 void bkpt(uint32_t imm16); // v5 and above 1232 1233 // Different nop operations are used by the code generator to detect certain 1234 // states of the generated code. 1235 enum NopMarkerTypes { 1236 NON_MARKING_NOP = 0, 1237 GROUP_ENDING_NOP, 1238 DEBUG_BREAK_NOP, 1239 // IC markers. 1240 PROPERTY_ACCESS_INLINED, 1241 PROPERTY_ACCESS_INLINED_CONTEXT, 1242 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE, 1243 // Helper values. 1244 LAST_CODE_MARKER, 1245 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED 1246 }; 1247 1248 void nop(int type = 0); // 0 is the default non-marking type. 1249 1250 void dumy(int r1, int x2, int b2, int d2); 1251 1252 // Check the code size generated from label to here. SizeOfCodeGeneratedSince(Label * label)1253 int SizeOfCodeGeneratedSince(Label* label) { 1254 return pc_offset() - label->pos(); 1255 } 1256 1257 // Debugging 1258 1259 // Mark address of a debug break slot. 1260 void RecordDebugBreakSlot(RelocInfo::Mode mode); 1261 1262 // Record the AST id of the CallIC being compiled, so that it can be placed 1263 // in the relocation information. SetRecordedAstId(TypeFeedbackId ast_id)1264 void SetRecordedAstId(TypeFeedbackId ast_id) { recorded_ast_id_ = ast_id; } 1265 RecordedAstId()1266 TypeFeedbackId RecordedAstId() { 1267 // roohack - another issue??? DCHECK(!recorded_ast_id_.IsNone()); 1268 return recorded_ast_id_; 1269 } 1270 ClearRecordedAstId()1271 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); } 1272 1273 // Record a comment relocation entry that can be used by a disassembler. 1274 // Use --code-comments to enable. 1275 void RecordComment(const char* msg); 1276 1277 // Record a deoptimization reason that can be used by a log or cpu profiler. 1278 // Use --trace-deopt to enable. 1279 void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position, 1280 int id); 1281 1282 // Writes a single byte or word of data in the code stream. Used 1283 // for inline tables, e.g., jump-tables. 1284 void db(uint8_t data); 1285 void dd(uint32_t data); 1286 void dq(uint64_t data); 1287 void dp(uintptr_t data); 1288 PatchConstantPoolAccessInstruction(int pc_offset,int offset,ConstantPoolEntry::Access access,ConstantPoolEntry::Type type)1289 void PatchConstantPoolAccessInstruction(int pc_offset, int offset, 1290 ConstantPoolEntry::Access access, 1291 ConstantPoolEntry::Type type) { 1292 // No embedded constant pool support. 1293 UNREACHABLE(); 1294 } 1295 1296 // Read/patch instructions instr_at(int pos)1297 SixByteInstr instr_at(int pos) { 1298 return Instruction::InstructionBits(buffer_ + pos); 1299 } 1300 template <typename T> instr_at_put(int pos,T instr)1301 void instr_at_put(int pos, T instr) { 1302 Instruction::SetInstructionBits<T>(buffer_ + pos, instr); 1303 } 1304 1305 // Decodes instruction at pos, and returns its length instr_length_at(int pos)1306 int32_t instr_length_at(int pos) { 1307 return Instruction::InstructionLength(buffer_ + pos); 1308 } 1309 instr_at(byte * pc)1310 static SixByteInstr instr_at(byte* pc) { 1311 return Instruction::InstructionBits(pc); 1312 } 1313 1314 static Condition GetCondition(Instr instr); 1315 1316 static bool IsBranch(Instr instr); 1317 #if V8_TARGET_ARCH_S390X 1318 static bool Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2); 1319 #else 1320 static bool Is32BitLoadIntoIP(SixByteInstr instr); 1321 #endif 1322 1323 static bool IsCmpRegister(Instr instr); 1324 static bool IsCmpImmediate(Instr instr); 1325 static bool IsNop(SixByteInstr instr, int type = NON_MARKING_NOP); 1326 1327 // The code currently calls CheckBuffer() too often. This has the side 1328 // effect of randomly growing the buffer in the middle of multi-instruction 1329 // sequences. 1330 // 1331 // This function allows outside callers to check and grow the buffer 1332 void EnsureSpaceFor(int space_needed); 1333 1334 void EmitRelocations(); 1335 void emit_label_addr(Label* label); 1336 1337 public: buffer_pos()1338 byte* buffer_pos() const { return buffer_; } 1339 1340 protected: 1341 // Relocation for a type-recording IC has the AST id added to it. This 1342 // member variable is a way to pass the information from the call site to 1343 // the relocation info. 1344 TypeFeedbackId recorded_ast_id_; 1345 buffer_space()1346 int buffer_space() const { return reloc_info_writer.pos() - pc_; } 1347 1348 // Decode instruction(s) at pos and return backchain to previous 1349 // label reference or kEndOfChain. 1350 int target_at(int pos); 1351 1352 // Patch instruction(s) at pos to target target_pos (e.g. branch) 1353 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr); 1354 1355 // Record reloc info for current pc_ 1356 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0); 1357 1358 private: 1359 // Code generation 1360 // The relocation writer's position is at least kGap bytes below the end of 1361 // the generated instructions. This is so that multi-instruction sequences do 1362 // not have to check for overflow. The same is true for writes of large 1363 // relocation info entries. 1364 static const int kGap = 32; 1365 1366 // Relocation info generation 1367 // Each relocation is encoded as a variable size value 1368 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize; 1369 RelocInfoWriter reloc_info_writer; 1370 std::vector<DeferredRelocInfo> relocations_; 1371 1372 // The bound position, before this we cannot do instruction elimination. 1373 int last_bound_pos_; 1374 1375 // Code emission 1376 inline void CheckBuffer(); 1377 void GrowBuffer(int needed = 0); 1378 inline void TrackBranch(); 1379 inline void UntrackBranch(); 1380 1381 inline int32_t emit_code_target( 1382 Handle<Code> target, RelocInfo::Mode rmode, 1383 TypeFeedbackId ast_id = TypeFeedbackId::None()); 1384 1385 // Helpers to emit binary encoding of 2/4/6 byte instructions. 1386 inline void emit2bytes(uint16_t x); 1387 inline void emit4bytes(uint32_t x); 1388 inline void emit6bytes(uint64_t x); 1389 1390 // Helpers to emit binary encoding for various instruction formats. 1391 1392 inline void rr2_form(uint8_t op, Condition m1, Register r2); 1393 1394 inline void ri_form(Opcode op, Register r1, const Operand& i2); 1395 inline void ri_form(Opcode op, Condition m1, const Operand& i2); 1396 1397 inline void rie_form(Opcode op, Register r1, Register r3, const Operand& i2); 1398 inline void rie_f_form(Opcode op, Register r1, Register r2, const Operand& i3, 1399 const Operand& i4, const Operand& i5); 1400 1401 inline void ris_form(Opcode op, Register r1, Condition m3, Register b4, 1402 Disp d4, const Operand& i2); 1403 1404 inline void rrf1_form(Opcode op, Register r1, Register r2, Register r3); 1405 inline void rrf1_form(uint32_t x); 1406 inline void rrf2_form(uint32_t x); 1407 inline void rrf3_form(uint32_t x); 1408 inline void rrfe_form(Opcode op, Condition m3, Condition m4, Register r1, 1409 Register r2); 1410 1411 inline void rrs_form(Opcode op, Register r1, Register r2, Register b4, 1412 Disp d4, Condition m3); 1413 1414 inline void rs_form(Opcode op, Register r1, Condition m3, Register b2, 1415 const Disp d2); 1416 inline void rs_form(Opcode op, Register r1, Register r3, Register b2, 1417 const Disp d2); 1418 1419 inline void rsi_form(Opcode op, Register r1, Register r3, const Operand& i2); 1420 inline void rsl_form(Opcode op, Length l1, Register b2, Disp d2); 1421 1422 inline void rsy_form(Opcode op, Register r1, Register r3, Register b2, 1423 const Disp d2); 1424 inline void rsy_form(Opcode op, Register r1, Condition m3, Register b2, 1425 const Disp d2); 1426 1427 inline void rxe_form(Opcode op, Register r1, Register x2, Register b2, 1428 Disp d2); 1429 1430 inline void rxf_form(Opcode op, Register r1, Register r3, Register b2, 1431 Register x2, Disp d2); 1432 1433 inline void s_form(Opcode op, Register b1, Disp d2); 1434 1435 inline void si_form(Opcode op, const Operand& i2, Register b1, Disp d1); 1436 inline void siy_form(Opcode op, const Operand& i2, Register b1, Disp d1); 1437 1438 inline void sil_form(Opcode op, Register b1, Disp d1, const Operand& i2); 1439 1440 inline void ss_form(Opcode op, Length l, Register b1, Disp d1, Register b2, 1441 Disp d2); 1442 inline void ss_form(Opcode op, Length l1, Length l2, Register b1, Disp d1, 1443 Register b2, Disp d2); 1444 inline void ss_form(Opcode op, Length l1, const Operand& i3, Register b1, 1445 Disp d1, Register b2, Disp d2); 1446 inline void ss_form(Opcode op, Register r1, Register r2, Register b1, Disp d1, 1447 Register b2, Disp d2); 1448 inline void sse_form(Opcode op, Register b1, Disp d1, Register b2, Disp d2); 1449 inline void ssf_form(Opcode op, Register r3, Register b1, Disp d1, 1450 Register b2, Disp d2); 1451 1452 // Labels 1453 void print(Label* L); 1454 int max_reach_from(int pos); 1455 void bind_to(Label* L, int pos); 1456 void next(Label* L); 1457 1458 friend class RegExpMacroAssemblerS390; 1459 friend class RelocInfo; 1460 friend class CodePatcher; 1461 1462 List<Handle<Code> > code_targets_; 1463 friend class EnsureSpace; 1464 }; 1465 1466 class EnsureSpace BASE_EMBEDDED { 1467 public: EnsureSpace(Assembler * assembler)1468 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); } 1469 }; 1470 1471 } // namespace internal 1472 } // namespace v8 1473 1474 #endif // V8_S390_ASSEMBLER_S390_H_ 1475