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#include "src/s390/assembler-s390.h" 38 39#if V8_TARGET_ARCH_S390 40 41#if V8_HOST_ARCH_S390 42#include <elf.h> // Required for auxv checks for STFLE support 43#endif 44 45#include "src/base/bits.h" 46#include "src/base/cpu.h" 47#include "src/s390/assembler-s390-inl.h" 48 49#include "src/macro-assembler.h" 50 51namespace v8 { 52namespace internal { 53 54// Get the CPU features enabled by the build. 55static unsigned CpuFeaturesImpliedByCompiler() { 56 unsigned answer = 0; 57 return answer; 58} 59 60// Check whether Store Facility STFLE instruction is available on the platform. 61// Instruction returns a bit vector of the enabled hardware facilities. 62static bool supportsSTFLE() { 63#if V8_HOST_ARCH_S390 64 static bool read_tried = false; 65 static uint32_t auxv_hwcap = 0; 66 67 if (!read_tried) { 68 // Open the AUXV (auxilliary vector) psuedo-file 69 int fd = open("/proc/self/auxv", O_RDONLY); 70 71 read_tried = true; 72 if (fd != -1) { 73#if V8_TARGET_ARCH_S390X 74 static Elf64_auxv_t buffer[16]; 75 Elf64_auxv_t* auxv_element; 76#else 77 static Elf32_auxv_t buffer[16]; 78 Elf32_auxv_t* auxv_element; 79#endif 80 int bytes_read = 0; 81 while (bytes_read >= 0) { 82 // Read a chunk of the AUXV 83 bytes_read = read(fd, buffer, sizeof(buffer)); 84 // Locate and read the platform field of AUXV if it is in the chunk 85 for (auxv_element = buffer; 86 auxv_element + sizeof(auxv_element) <= buffer + bytes_read && 87 auxv_element->a_type != AT_NULL; 88 auxv_element++) { 89 // We are looking for HWCAP entry in AUXV to search for STFLE support 90 if (auxv_element->a_type == AT_HWCAP) { 91 /* Note: Both auxv_hwcap and buffer are static */ 92 auxv_hwcap = auxv_element->a_un.a_val; 93 goto done_reading; 94 } 95 } 96 } 97 done_reading: 98 close(fd); 99 } 100 } 101 102 // Did not find result 103 if (0 == auxv_hwcap) { 104 return false; 105 } 106 107 // HWCAP_S390_STFLE is defined to be 4 in include/asm/elf.h. Currently 108 // hardcoded in case that include file does not exist. 109 const uint32_t HWCAP_S390_STFLE = 4; 110 return (auxv_hwcap & HWCAP_S390_STFLE); 111#else 112 // STFLE is not available on non-s390 hosts 113 return false; 114#endif 115} 116 117void CpuFeatures::ProbeImpl(bool cross_compile) { 118 supported_ |= CpuFeaturesImpliedByCompiler(); 119 icache_line_size_ = 256; 120 121 // Only use statically determined features for cross compile (snapshot). 122 if (cross_compile) return; 123 124#ifdef DEBUG 125 initialized_ = true; 126#endif 127 128 static bool performSTFLE = supportsSTFLE(); 129 130// Need to define host, as we are generating inlined S390 assembly to test 131// for facilities. 132#if V8_HOST_ARCH_S390 133 if (performSTFLE) { 134 // STFLE D(B) requires: 135 // GPR0 to specify # of double words to update minus 1. 136 // i.e. GPR0 = 0 for 1 doubleword 137 // D(B) to specify to memory location to store the facilities bits 138 // The facilities we are checking for are: 139 // Bit 45 - Distinct Operands for instructions like ARK, SRK, etc. 140 // As such, we require only 1 double word 141 int64_t facilities[3] = {0L}; 142 // LHI sets up GPR0 143 // STFLE is specified as .insn, as opcode is not recognized. 144 // We register the instructions kill r0 (LHI) and the CC (STFLE). 145 asm volatile( 146 "lhi 0,2\n" 147 ".insn s,0xb2b00000,%0\n" 148 : "=Q"(facilities) 149 : 150 : "cc", "r0"); 151 152 uint64_t one = static_cast<uint64_t>(1); 153 // Test for Distinct Operands Facility - Bit 45 154 if (facilities[0] & (one << (63 - 45))) { 155 supported_ |= (1u << DISTINCT_OPS); 156 } 157 // Test for General Instruction Extension Facility - Bit 34 158 if (facilities[0] & (one << (63 - 34))) { 159 supported_ |= (1u << GENERAL_INSTR_EXT); 160 } 161 // Test for Floating Point Extension Facility - Bit 37 162 if (facilities[0] & (one << (63 - 37))) { 163 supported_ |= (1u << FLOATING_POINT_EXT); 164 } 165 // Test for Vector Facility - Bit 129 166 if (facilities[2] & (one << (63 - (129 - 128)))) { 167 supported_ |= (1u << VECTOR_FACILITY); 168 } 169 // Test for Miscellaneous Instruction Extension Facility - Bit 58 170 if (facilities[0] & (1lu << (63 - 58))) { 171 supported_ |= (1u << MISC_INSTR_EXT2); 172 } 173 } 174#else 175 // All distinct ops instructions can be simulated 176 supported_ |= (1u << DISTINCT_OPS); 177 // RISBG can be simulated 178 supported_ |= (1u << GENERAL_INSTR_EXT); 179 supported_ |= (1u << FLOATING_POINT_EXT); 180 supported_ |= (1u << MISC_INSTR_EXT2); 181 USE(performSTFLE); // To avoid assert 182 supported_ |= (1u << VECTOR_FACILITY); 183#endif 184 supported_ |= (1u << FPU); 185} 186 187void CpuFeatures::PrintTarget() { 188 const char* s390_arch = NULL; 189 190#if V8_TARGET_ARCH_S390X 191 s390_arch = "s390x"; 192#else 193 s390_arch = "s390"; 194#endif 195 196 printf("target %s\n", s390_arch); 197} 198 199void CpuFeatures::PrintFeatures() { 200 printf("FPU=%d\n", CpuFeatures::IsSupported(FPU)); 201 printf("FPU_EXT=%d\n", CpuFeatures::IsSupported(FLOATING_POINT_EXT)); 202 printf("GENERAL_INSTR=%d\n", CpuFeatures::IsSupported(GENERAL_INSTR_EXT)); 203 printf("DISTINCT_OPS=%d\n", CpuFeatures::IsSupported(DISTINCT_OPS)); 204 printf("VECTOR_FACILITY=%d\n", CpuFeatures::IsSupported(VECTOR_FACILITY)); 205 printf("MISC_INSTR_EXT2=%d\n", CpuFeatures::IsSupported(MISC_INSTR_EXT2)); 206} 207 208Register ToRegister(int num) { 209 DCHECK(num >= 0 && num < kNumRegisters); 210 const Register kRegisters[] = {r0, r1, r2, r3, r4, r5, r6, r7, 211 r8, r9, r10, fp, ip, r13, r14, sp}; 212 return kRegisters[num]; 213} 214 215// ----------------------------------------------------------------------------- 216// Implementation of RelocInfo 217 218const int RelocInfo::kApplyMask = 219 RelocInfo::kCodeTargetMask | 1 << RelocInfo::INTERNAL_REFERENCE; 220 221bool RelocInfo::IsCodedSpecially() { 222 // The deserializer needs to know whether a pointer is specially 223 // coded. Being specially coded on S390 means that it is an iihf/iilf 224 // instruction sequence, and that is always the case inside code 225 // objects. 226 return true; 227} 228 229bool RelocInfo::IsInConstantPool() { return false; } 230 231Address RelocInfo::wasm_memory_reference() { 232 DCHECK(IsWasmMemoryReference(rmode_)); 233 return Assembler::target_address_at(pc_, host_); 234} 235 236uint32_t RelocInfo::wasm_memory_size_reference() { 237 DCHECK(IsWasmMemorySizeReference(rmode_)); 238 return static_cast<uint32_t>( 239 reinterpret_cast<intptr_t>(Assembler::target_address_at(pc_, host_))); 240} 241 242Address RelocInfo::wasm_global_reference() { 243 DCHECK(IsWasmGlobalReference(rmode_)); 244 return Assembler::target_address_at(pc_, host_); 245} 246 247uint32_t RelocInfo::wasm_function_table_size_reference() { 248 DCHECK(IsWasmFunctionTableSizeReference(rmode_)); 249 return static_cast<uint32_t>( 250 reinterpret_cast<intptr_t>(Assembler::target_address_at(pc_, host_))); 251} 252 253void RelocInfo::unchecked_update_wasm_memory_reference( 254 Address address, ICacheFlushMode flush_mode) { 255 Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode); 256} 257 258void RelocInfo::unchecked_update_wasm_size(uint32_t size, 259 ICacheFlushMode flush_mode) { 260 Assembler::set_target_address_at(isolate_, pc_, host_, 261 reinterpret_cast<Address>(size), flush_mode); 262} 263 264// ----------------------------------------------------------------------------- 265// Implementation of Operand and MemOperand 266// See assembler-s390-inl.h for inlined constructors 267 268Operand::Operand(Handle<Object> handle) { 269 AllowDeferredHandleDereference using_raw_address; 270 rm_ = no_reg; 271 // Verify all Objects referred by code are NOT in new space. 272 Object* obj = *handle; 273 if (obj->IsHeapObject()) { 274 imm_ = reinterpret_cast<intptr_t>(handle.location()); 275 rmode_ = RelocInfo::EMBEDDED_OBJECT; 276 } else { 277 // no relocation needed 278 imm_ = reinterpret_cast<intptr_t>(obj); 279 rmode_ = kRelocInfo_NONEPTR; 280 } 281} 282 283MemOperand::MemOperand(Register rn, int32_t offset) { 284 baseRegister = rn; 285 indexRegister = r0; 286 offset_ = offset; 287} 288 289MemOperand::MemOperand(Register rx, Register rb, int32_t offset) { 290 baseRegister = rb; 291 indexRegister = rx; 292 offset_ = offset; 293} 294 295// ----------------------------------------------------------------------------- 296// Specific instructions, constants, and masks. 297 298Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) 299 : AssemblerBase(isolate, buffer, buffer_size), 300 recorded_ast_id_(TypeFeedbackId::None()), 301 code_targets_(100) { 302 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); 303 304 last_bound_pos_ = 0; 305 ClearRecordedAstId(); 306 relocations_.reserve(128); 307} 308 309void Assembler::GetCode(CodeDesc* desc) { 310 EmitRelocations(); 311 312 // Set up code descriptor. 313 desc->buffer = buffer_; 314 desc->buffer_size = buffer_size_; 315 desc->instr_size = pc_offset(); 316 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 317 desc->origin = this; 318 desc->unwinding_info_size = 0; 319 desc->unwinding_info = nullptr; 320} 321 322void Assembler::Align(int m) { 323 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); 324 while ((pc_offset() & (m - 1)) != 0) { 325 nop(0); 326 } 327} 328 329void Assembler::CodeTargetAlign() { Align(8); } 330 331Condition Assembler::GetCondition(Instr instr) { 332 switch (instr & kCondMask) { 333 case BT: 334 return eq; 335 case BF: 336 return ne; 337 default: 338 UNIMPLEMENTED(); 339 } 340 return al; 341} 342 343#if V8_TARGET_ARCH_S390X 344// This code assumes a FIXED_SEQUENCE for 64bit loads (iihf/iilf) 345bool Assembler::Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2) { 346 // Check the instructions are the iihf/iilf load into ip 347 return (((instr1 >> 32) == 0xC0C8) && ((instr2 >> 32) == 0xC0C9)); 348} 349#else 350// This code assumes a FIXED_SEQUENCE for 32bit loads (iilf) 351bool Assembler::Is32BitLoadIntoIP(SixByteInstr instr) { 352 // Check the instruction is an iilf load into ip/r12. 353 return ((instr >> 32) == 0xC0C9); 354} 355#endif 356 357// Labels refer to positions in the (to be) generated code. 358// There are bound, linked, and unused labels. 359// 360// Bound labels refer to known positions in the already 361// generated code. pos() is the position the label refers to. 362// 363// Linked labels refer to unknown positions in the code 364// to be generated; pos() is the position of the last 365// instruction using the label. 366 367// The link chain is terminated by a negative code position (must be aligned) 368const int kEndOfChain = -4; 369 370// Returns the target address of the relative instructions, typically 371// of the form: pos + imm (where immediate is in # of halfwords for 372// BR* and LARL). 373int Assembler::target_at(int pos) { 374 SixByteInstr instr = instr_at(pos); 375 // check which type of branch this is 16 or 26 bit offset 376 Opcode opcode = Instruction::S390OpcodeValue(buffer_ + pos); 377 378 if (BRC == opcode || BRCT == opcode || BRCTG == opcode) { 379 int16_t imm16 = SIGN_EXT_IMM16((instr & kImm16Mask)); 380 imm16 <<= 1; // BRC immediate is in # of halfwords 381 if (imm16 == 0) return kEndOfChain; 382 return pos + imm16; 383 } else if (LLILF == opcode || BRCL == opcode || LARL == opcode || 384 BRASL == opcode) { 385 int32_t imm32 = 386 static_cast<int32_t>(instr & (static_cast<uint64_t>(0xffffffff))); 387 if (LLILF != opcode) 388 imm32 <<= 1; // BR* + LARL treat immediate in # of halfwords 389 if (imm32 == 0) return kEndOfChain; 390 return pos + imm32; 391 } 392 393 // Unknown condition 394 DCHECK(false); 395 return -1; 396} 397 398// Update the target address of the current relative instruction. 399void Assembler::target_at_put(int pos, int target_pos, bool* is_branch) { 400 SixByteInstr instr = instr_at(pos); 401 Opcode opcode = Instruction::S390OpcodeValue(buffer_ + pos); 402 403 if (is_branch != nullptr) { 404 *is_branch = (opcode == BRC || opcode == BRCT || opcode == BRCTG || 405 opcode == BRCL || opcode == BRASL); 406 } 407 408 if (BRC == opcode || BRCT == opcode || BRCTG == opcode) { 409 int16_t imm16 = target_pos - pos; 410 instr &= (~0xffff); 411 DCHECK(is_int16(imm16)); 412 instr_at_put<FourByteInstr>(pos, instr | (imm16 >> 1)); 413 return; 414 } else if (BRCL == opcode || LARL == opcode || BRASL == opcode) { 415 // Immediate is in # of halfwords 416 int32_t imm32 = target_pos - pos; 417 instr &= (~static_cast<uint64_t>(0xffffffff)); 418 instr_at_put<SixByteInstr>(pos, instr | (imm32 >> 1)); 419 return; 420 } else if (LLILF == opcode) { 421 DCHECK(target_pos == kEndOfChain || target_pos >= 0); 422 // Emitted label constant, not part of a branch. 423 // Make label relative to Code* of generated Code object. 424 int32_t imm32 = target_pos + (Code::kHeaderSize - kHeapObjectTag); 425 instr &= (~static_cast<uint64_t>(0xffffffff)); 426 instr_at_put<SixByteInstr>(pos, instr | imm32); 427 return; 428 } 429 DCHECK(false); 430} 431 432// Returns the maximum number of bits given instruction can address. 433int Assembler::max_reach_from(int pos) { 434 Opcode opcode = Instruction::S390OpcodeValue(buffer_ + pos); 435 436 // Check which type of instr. In theory, we can return 437 // the values below + 1, given offset is # of halfwords 438 if (BRC == opcode || BRCT == opcode || BRCTG == opcode) { 439 return 16; 440 } else if (LLILF == opcode || BRCL == opcode || LARL == opcode || 441 BRASL == opcode) { 442 return 31; // Using 31 as workaround instead of 32 as 443 // is_intn(x,32) doesn't work on 32-bit platforms. 444 // llilf: Emitted label constant, not part of 445 // a branch (regexp PushBacktrack). 446 } 447 DCHECK(false); 448 return 16; 449} 450 451void Assembler::bind_to(Label* L, int pos) { 452 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position 453 bool is_branch = false; 454 while (L->is_linked()) { 455 int fixup_pos = L->pos(); 456#ifdef DEBUG 457 int32_t offset = pos - fixup_pos; 458 int maxReach = max_reach_from(fixup_pos); 459#endif 460 next(L); // call next before overwriting link with target at fixup_pos 461 DCHECK(is_intn(offset, maxReach)); 462 target_at_put(fixup_pos, pos, &is_branch); 463 } 464 L->bind_to(pos); 465 466 // Keep track of the last bound label so we don't eliminate any instructions 467 // before a bound label. 468 if (pos > last_bound_pos_) last_bound_pos_ = pos; 469} 470 471void Assembler::bind(Label* L) { 472 DCHECK(!L->is_bound()); // label can only be bound once 473 bind_to(L, pc_offset()); 474} 475 476void Assembler::next(Label* L) { 477 DCHECK(L->is_linked()); 478 int link = target_at(L->pos()); 479 if (link == kEndOfChain) { 480 L->Unuse(); 481 } else { 482 DCHECK(link >= 0); 483 L->link_to(link); 484 } 485} 486 487bool Assembler::is_near(Label* L, Condition cond) { 488 DCHECK(L->is_bound()); 489 if (L->is_bound() == false) return false; 490 491 int maxReach = ((cond == al) ? 26 : 16); 492 int offset = L->pos() - pc_offset(); 493 494 return is_intn(offset, maxReach); 495} 496 497int Assembler::link(Label* L) { 498 int position; 499 if (L->is_bound()) { 500 position = L->pos(); 501 } else { 502 if (L->is_linked()) { 503 position = L->pos(); // L's link 504 } else { 505 // was: target_pos = kEndOfChain; 506 // However, using self to mark the first reference 507 // should avoid most instances of branch offset overflow. See 508 // target_at() for where this is converted back to kEndOfChain. 509 position = pc_offset(); 510 } 511 L->link_to(pc_offset()); 512 } 513 514 return position; 515} 516 517void Assembler::load_label_offset(Register r1, Label* L) { 518 int target_pos; 519 int constant; 520 if (L->is_bound()) { 521 target_pos = L->pos(); 522 constant = target_pos + (Code::kHeaderSize - kHeapObjectTag); 523 } else { 524 if (L->is_linked()) { 525 target_pos = L->pos(); // L's link 526 } else { 527 // was: target_pos = kEndOfChain; 528 // However, using branch to self to mark the first reference 529 // should avoid most instances of branch offset overflow. See 530 // target_at() for where this is converted back to kEndOfChain. 531 target_pos = pc_offset(); 532 } 533 L->link_to(pc_offset()); 534 535 constant = target_pos - pc_offset(); 536 } 537 llilf(r1, Operand(constant)); 538} 539 540// Pseudo op - branch on condition 541void Assembler::branchOnCond(Condition c, int branch_offset, bool is_bound) { 542 int offset_in_halfwords = branch_offset / 2; 543 if (is_bound && is_int16(offset_in_halfwords)) { 544 brc(c, Operand(offset_in_halfwords)); // short jump 545 } else { 546 brcl(c, Operand(offset_in_halfwords)); // long jump 547 } 548} 549 550// 32-bit Store Multiple - short displacement (12-bits unsigned) 551void Assembler::stm(Register r1, Register r2, const MemOperand& src) { 552 rs_form(STM, r1, r2, src.rb(), src.offset()); 553} 554 555// 32-bit Store Multiple - long displacement (20-bits signed) 556void Assembler::stmy(Register r1, Register r2, const MemOperand& src) { 557 rsy_form(STMY, r1, r2, src.rb(), src.offset()); 558} 559 560// 64-bit Store Multiple - long displacement (20-bits signed) 561void Assembler::stmg(Register r1, Register r2, const MemOperand& src) { 562 rsy_form(STMG, r1, r2, src.rb(), src.offset()); 563} 564 565// Exception-generating instructions and debugging support. 566// Stops with a non-negative code less than kNumOfWatchedStops support 567// enabling/disabling and a counter feature. See simulator-s390.h . 568void Assembler::stop(const char* msg, Condition cond, int32_t code, 569 CRegister cr) { 570 if (cond != al) { 571 Label skip; 572 b(NegateCondition(cond), &skip, Label::kNear); 573 bkpt(0); 574 bind(&skip); 575 } else { 576 bkpt(0); 577 } 578} 579 580void Assembler::bkpt(uint32_t imm16) { 581 // GDB software breakpoint instruction 582 emit2bytes(0x0001); 583} 584 585// Pseudo instructions. 586void Assembler::nop(int type) { 587 switch (type) { 588 case 0: 589 lr(r0, r0); 590 break; 591 case DEBUG_BREAK_NOP: 592 // TODO(john.yan): Use a better NOP break 593 oill(r3, Operand::Zero()); 594 break; 595 default: 596 UNIMPLEMENTED(); 597 } 598} 599 600 601 602// RI1 format: <insn> R1,I2 603// +--------+----+----+------------------+ 604// | OpCode | R1 |OpCd| I2 | 605// +--------+----+----+------------------+ 606// 0 8 12 16 31 607#define RI1_FORM_EMIT(name, op) \ 608 void Assembler::name(Register r, const Operand& i2) { ri_form(op, r, i2); } 609 610void Assembler::ri_form(Opcode op, Register r1, const Operand& i2) { 611 DCHECK(is_uint12(op)); 612 DCHECK(is_uint16(i2.imm_) || is_int16(i2.imm_)); 613 emit4bytes((op & 0xFF0) * B20 | r1.code() * B20 | (op & 0xF) * B16 | 614 (i2.imm_ & 0xFFFF)); 615} 616 617// RI2 format: <insn> M1,I2 618// +--------+----+----+------------------+ 619// | OpCode | M1 |OpCd| I2 | 620// +--------+----+----+------------------+ 621// 0 8 12 16 31 622#define RI2_FORM_EMIT(name, op) \ 623 void Assembler::name(Condition m, const Operand& i2) { ri_form(op, m, i2); } 624 625void Assembler::ri_form(Opcode op, Condition m1, const Operand& i2) { 626 DCHECK(is_uint12(op)); 627 DCHECK(is_uint4(m1)); 628 DCHECK(op == BRC ? is_int16(i2.imm_) : is_uint16(i2.imm_)); 629 emit4bytes((op & 0xFF0) * B20 | m1 * B20 | (op & 0xF) * B16 | 630 (i2.imm_ & 0xFFFF)); 631} 632 633// RIE-f format: <insn> R1,R2,I3,I4,I5 634// +--------+----+----+------------------+--------+--------+ 635// | OpCode | R1 | R2 | I3 | I4 | I5 | OpCode | 636// +--------+----+----+------------------+--------+--------+ 637// 0 8 12 16 24 32 40 47 638void Assembler::rie_f_form(Opcode op, Register r1, Register r2, 639 const Operand& i3, const Operand& i4, 640 const Operand& i5) { 641 DCHECK(is_uint16(op)); 642 DCHECK(is_uint8(i3.imm_)); 643 DCHECK(is_uint8(i4.imm_)); 644 DCHECK(is_uint8(i5.imm_)); 645 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 646 (static_cast<uint64_t>(r1.code())) * B36 | 647 (static_cast<uint64_t>(r2.code())) * B32 | 648 (static_cast<uint64_t>(i3.imm_)) * B24 | 649 (static_cast<uint64_t>(i4.imm_)) * B16 | 650 (static_cast<uint64_t>(i5.imm_)) * B8 | 651 (static_cast<uint64_t>(op & 0x00FF)); 652 emit6bytes(code); 653} 654 655// RIE format: <insn> R1,R3,I2 656// +--------+----+----+------------------+--------+--------+ 657// | OpCode | R1 | R3 | I2 |////////| OpCode | 658// +--------+----+----+------------------+--------+--------+ 659// 0 8 12 16 32 40 47 660#define RIE_FORM_EMIT(name, op) \ 661 void Assembler::name(Register r1, Register r3, const Operand& i2) { \ 662 rie_form(op, r1, r3, i2); \ 663 } 664 665void Assembler::rie_form(Opcode op, Register r1, Register r3, 666 const Operand& i2) { 667 DCHECK(is_uint16(op)); 668 DCHECK(is_int16(i2.imm_)); 669 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 670 (static_cast<uint64_t>(r1.code())) * B36 | 671 (static_cast<uint64_t>(r3.code())) * B32 | 672 (static_cast<uint64_t>(i2.imm_ & 0xFFFF)) * B16 | 673 (static_cast<uint64_t>(op & 0x00FF)); 674 emit6bytes(code); 675} 676 677// RS1 format: <insn> R1,R3,D2(B2) 678// +--------+----+----+----+-------------+ 679// | OpCode | R1 | R3 | B2 | D2 | 680// +--------+----+----+----+-------------+ 681// 0 8 12 16 20 31 682#define RS1_FORM_EMIT(name, op) \ 683 void Assembler::name(Register r1, Register r3, Register b2, Disp d2) { \ 684 rs_form(op, r1, r3, b2, d2); \ 685 } \ 686 void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \ 687 name(r1, r3, opnd.getBaseRegister(), opnd.getDisplacement()); \ 688 } 689 690void Assembler::rs_form(Opcode op, Register r1, Register r3, Register b2, 691 const Disp d2) { 692 DCHECK(is_uint12(d2)); 693 emit4bytes(op * B24 | r1.code() * B20 | r3.code() * B16 | b2.code() * B12 | 694 d2); 695} 696 697// RS2 format: <insn> R1,M3,D2(B2) 698// +--------+----+----+----+-------------+ 699// | OpCode | R1 | M3 | B2 | D2 | 700// +--------+----+----+----+-------------+ 701// 0 8 12 16 20 31 702#define RS2_FORM_EMIT(name, op) \ 703 void Assembler::name(Register r1, Condition m3, Register b2, Disp d2) { \ 704 rs_form(op, r1, m3, b2, d2); \ 705 } \ 706 void Assembler::name(Register r1, Condition m3, const MemOperand& opnd) { \ 707 name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement()); \ 708 } 709 710void Assembler::rs_form(Opcode op, Register r1, Condition m3, Register b2, 711 const Disp d2) { 712 DCHECK(is_uint12(d2)); 713 emit4bytes(op * B24 | r1.code() * B20 | m3 * B16 | b2.code() * B12 | d2); 714} 715 716// RSI format: <insn> R1,R3,I2 717// +--------+----+----+------------------+ 718// | OpCode | R1 | R3 | RI2 | 719// +--------+----+----+------------------+ 720// 0 8 12 16 31 721#define RSI_FORM_EMIT(name, op) \ 722 void Assembler::name(Register r1, Register r3, const Operand& i2) { \ 723 rsi_form(op, r1, r3, i2); \ 724 } 725 726void Assembler::rsi_form(Opcode op, Register r1, Register r3, 727 const Operand& i2) { 728 DCHECK(is_uint8(op)); 729 DCHECK(is_uint16(i2.imm_)); 730 emit4bytes(op * B24 | r1.code() * B20 | r3.code() * B16 | (i2.imm_ & 0xFFFF)); 731} 732 733// RSL format: <insn> R1,R3,D2(B2) 734// +--------+----+----+----+-------------+--------+--------+ 735// | OpCode | L1 | | B2 | D2 | | OpCode | 736// +--------+----+----+----+-------------+--------+--------+ 737// 0 8 12 16 20 32 40 47 738#define RSL_FORM_EMIT(name, op) \ 739 void Assembler::name(Length l1, Register b2, Disp d2) { \ 740 rsl_form(op, l1, b2, d2); \ 741 } 742 743void Assembler::rsl_form(Opcode op, Length l1, Register b2, Disp d2) { 744 DCHECK(is_uint16(op)); 745 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 746 (static_cast<uint64_t>(l1)) * B36 | 747 (static_cast<uint64_t>(b2.code())) * B28 | 748 (static_cast<uint64_t>(d2)) * B16 | 749 (static_cast<uint64_t>(op & 0x00FF)); 750 emit6bytes(code); 751} 752 753// RSY1 format: <insn> R1,R3,D2(B2) 754// +--------+----+----+----+-------------+--------+--------+ 755// | OpCode | R1 | R3 | B2 | DL2 | DH2 | OpCode | 756// +--------+----+----+----+-------------+--------+--------+ 757// 0 8 12 16 20 32 40 47 758#define RSY1_FORM_EMIT(name, op) \ 759 void Assembler::name(Register r1, Register r3, Register b2, Disp d2) { \ 760 rsy_form(op, r1, r3, b2, d2); \ 761 } \ 762 void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \ 763 name(r1, r3, opnd.getBaseRegister(), opnd.getDisplacement()); \ 764 } 765 766void Assembler::rsy_form(Opcode op, Register r1, Register r3, Register b2, 767 const Disp d2) { 768 DCHECK(is_int20(d2)); 769 DCHECK(is_uint16(op)); 770 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 771 (static_cast<uint64_t>(r1.code())) * B36 | 772 (static_cast<uint64_t>(r3.code())) * B32 | 773 (static_cast<uint64_t>(b2.code())) * B28 | 774 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | 775 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | 776 (static_cast<uint64_t>(op & 0x00FF)); 777 emit6bytes(code); 778} 779 780// RSY2 format: <insn> R1,M3,D2(B2) 781// +--------+----+----+----+-------------+--------+--------+ 782// | OpCode | R1 | M3 | B2 | DL2 | DH2 | OpCode | 783// +--------+----+----+----+-------------+--------+--------+ 784// 0 8 12 16 20 32 40 47 785#define RSY2_FORM_EMIT(name, op) \ 786 void Assembler::name(Register r1, Condition m3, Register b2, Disp d2) { \ 787 rsy_form(op, r1, m3, b2, d2); \ 788 } \ 789 void Assembler::name(Register r1, Condition m3, const MemOperand& opnd) { \ 790 name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement()); \ 791 } 792 793void Assembler::rsy_form(Opcode op, Register r1, Condition m3, Register b2, 794 const Disp d2) { 795 DCHECK(is_int20(d2)); 796 DCHECK(is_uint16(op)); 797 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 798 (static_cast<uint64_t>(r1.code())) * B36 | 799 (static_cast<uint64_t>(m3)) * B32 | 800 (static_cast<uint64_t>(b2.code())) * B28 | 801 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | 802 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | 803 (static_cast<uint64_t>(op & 0x00FF)); 804 emit6bytes(code); 805} 806 807// RXE format: <insn> R1,D2(X2,B2) 808// +--------+----+----+----+-------------+--------+--------+ 809// | OpCode | R1 | X2 | B2 | D2 |////////| OpCode | 810// +--------+----+----+----+-------------+--------+--------+ 811// 0 8 12 16 20 32 40 47 812#define RXE_FORM_EMIT(name, op) \ 813 void Assembler::name(Register r1, Register x2, Register b2, Disp d2) { \ 814 rxe_form(op, r1, x2, b2, d2); \ 815 } \ 816 void Assembler::name(Register r1, const MemOperand& opnd) { \ 817 name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \ 818 opnd.getDisplacement()); \ 819 } 820 821void Assembler::rxe_form(Opcode op, Register r1, Register x2, Register b2, 822 Disp d2) { 823 DCHECK(is_uint12(d2)); 824 DCHECK(is_uint16(op)); 825 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 826 (static_cast<uint64_t>(r1.code())) * B36 | 827 (static_cast<uint64_t>(x2.code())) * B32 | 828 (static_cast<uint64_t>(b2.code())) * B28 | 829 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | 830 (static_cast<uint64_t>(op & 0x00FF)); 831 emit6bytes(code); 832} 833 834// RRS format: <insn> R1,R2,M3,D4(B4) 835// +--------+----+----+----+-------------+----+---+--------+ 836// | OpCode | R1 | R2 | B4 | D4 | M3 |///| OpCode | 837// +--------+----+----+----+-------------+----+---+--------+ 838// 0 8 12 16 20 32 36 40 47 839#define RRS_FORM_EMIT(name, op) \ 840 void Assembler::name(Register r1, Register r2, Register b4, Disp d4, \ 841 Condition m3) { \ 842 rrs_form(op, r1, r2, b4, d4, m3); \ 843 } \ 844 void Assembler::name(Register r1, Register r2, Condition m3, \ 845 const MemOperand& opnd) { \ 846 name(r1, r2, opnd.getBaseRegister(), opnd.getDisplacement(), m3); \ 847 } 848 849void Assembler::rrs_form(Opcode op, Register r1, Register r2, Register b4, 850 Disp d4, Condition m3) { 851 DCHECK(is_uint12(d4)); 852 DCHECK(is_uint16(op)); 853 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 854 (static_cast<uint64_t>(r1.code())) * B36 | 855 (static_cast<uint64_t>(r2.code())) * B32 | 856 (static_cast<uint64_t>(b4.code())) * B28 | 857 (static_cast<uint64_t>(d4)) * B16 | 858 (static_cast<uint64_t>(m3)) << 12 | 859 (static_cast<uint64_t>(op & 0x00FF)); 860 emit6bytes(code); 861} 862 863// RIS format: <insn> R1,I2,M3,D4(B4) 864// +--------+----+----+----+-------------+--------+--------+ 865// | OpCode | R1 | M3 | B4 | D4 | I2 | OpCode | 866// +--------+----+----+----+-------------+--------+--------+ 867// 0 8 12 16 20 32 40 47 868#define RIS_FORM_EMIT(name, op) \ 869 void Assembler::name(Register r1, Condition m3, Register b4, Disp d4, \ 870 const Operand& i2) { \ 871 ris_form(op, r1, m3, b4, d4, i2); \ 872 } \ 873 void Assembler::name(Register r1, const Operand& i2, Condition m3, \ 874 const MemOperand& opnd) { \ 875 name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement(), i2); \ 876 } 877 878void Assembler::ris_form(Opcode op, Register r1, Condition m3, Register b4, 879 Disp d4, const Operand& i2) { 880 DCHECK(is_uint12(d4)); 881 DCHECK(is_uint16(op)); 882 DCHECK(is_uint8(i2.imm_)); 883 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 884 (static_cast<uint64_t>(r1.code())) * B36 | 885 (static_cast<uint64_t>(m3)) * B32 | 886 (static_cast<uint64_t>(b4.code())) * B28 | 887 (static_cast<uint64_t>(d4)) * B16 | 888 (static_cast<uint64_t>(i2.imm_)) << 8 | 889 (static_cast<uint64_t>(op & 0x00FF)); 890 emit6bytes(code); 891} 892 893// S format: <insn> D2(B2) 894// +------------------+----+-------------+ 895// | OpCode | B2 | D2 | 896// +------------------+----+-------------+ 897// 0 16 20 31 898#define S_FORM_EMIT(name, op) \ 899 void Assembler::name(Register b1, Disp d2) { s_form(op, b1, d2); } \ 900 void Assembler::name(const MemOperand& opnd) { \ 901 name(opnd.getBaseRegister(), opnd.getDisplacement()); \ 902 } 903 904void Assembler::s_form(Opcode op, Register b1, Disp d2) { 905 DCHECK(is_uint12(d2)); 906 emit4bytes(op << 16 | b1.code() * B12 | d2); 907} 908 909// SI format: <insn> D1(B1),I2 910// +--------+---------+----+-------------+ 911// | OpCode | I2 | B1 | D1 | 912// +--------+---------+----+-------------+ 913// 0 8 16 20 31 914#define SI_FORM_EMIT(name, op) \ 915 void Assembler::name(const Operand& i2, Register b1, Disp d1) { \ 916 si_form(op, i2, b1, d1); \ 917 } \ 918 void Assembler::name(const MemOperand& opnd, const Operand& i2) { \ 919 name(i2, opnd.getBaseRegister(), opnd.getDisplacement()); \ 920 } 921 922void Assembler::si_form(Opcode op, const Operand& i2, Register b1, Disp d1) { 923 emit4bytes((op & 0x00FF) << 24 | i2.imm_ * B16 | b1.code() * B12 | d1); 924} 925 926// SIY format: <insn> D1(B1),I2 927// +--------+---------+----+-------------+--------+--------+ 928// | OpCode | I2 | B1 | DL1 | DH1 | OpCode | 929// +--------+---------+----+-------------+--------+--------+ 930// 0 8 16 20 32 36 40 47 931#define SIY_FORM_EMIT(name, op) \ 932 void Assembler::name(const Operand& i2, Register b1, Disp d1) { \ 933 siy_form(op, i2, b1, d1); \ 934 } \ 935 void Assembler::name(const MemOperand& opnd, const Operand& i2) { \ 936 name(i2, opnd.getBaseRegister(), opnd.getDisplacement()); \ 937 } 938 939void Assembler::siy_form(Opcode op, const Operand& i2, Register b1, Disp d1) { 940 DCHECK(is_uint20(d1) || is_int20(d1)); 941 DCHECK(is_uint16(op)); 942 DCHECK(is_uint8(i2.imm_)); 943 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 944 (static_cast<uint64_t>(i2.imm_)) * B32 | 945 (static_cast<uint64_t>(b1.code())) * B28 | 946 (static_cast<uint64_t>(d1 & 0x0FFF)) * B16 | 947 (static_cast<uint64_t>(d1 & 0x0FF000)) >> 4 | 948 (static_cast<uint64_t>(op & 0x00FF)); 949 emit6bytes(code); 950} 951 952// SIL format: <insn> D1(B1),I2 953// +------------------+----+-------------+-----------------+ 954// | OpCode | B1 | D1 | I2 | 955// +------------------+----+-------------+-----------------+ 956// 0 16 20 32 47 957#define SIL_FORM_EMIT(name, op) \ 958 void Assembler::name(Register b1, Disp d1, const Operand& i2) { \ 959 sil_form(op, b1, d1, i2); \ 960 } \ 961 void Assembler::name(const MemOperand& opnd, const Operand& i2) { \ 962 name(opnd.getBaseRegister(), opnd.getDisplacement(), i2); \ 963 } 964 965void Assembler::sil_form(Opcode op, Register b1, Disp d1, const Operand& i2) { 966 DCHECK(is_uint12(d1)); 967 DCHECK(is_uint16(op)); 968 DCHECK(is_uint16(i2.imm_)); 969 uint64_t code = (static_cast<uint64_t>(op)) * B32 | 970 (static_cast<uint64_t>(b1.code())) * B28 | 971 (static_cast<uint64_t>(d1)) * B16 | 972 (static_cast<uint64_t>(i2.imm_)); 973 emit6bytes(code); 974} 975 976// RXF format: <insn> R1,R3,D2(X2,B2) 977// +--------+----+----+----+-------------+----+---+--------+ 978// | OpCode | R3 | X2 | B2 | D2 | R1 |///| OpCode | 979// +--------+----+----+----+-------------+----+---+--------+ 980// 0 8 12 16 20 32 36 40 47 981#define RXF_FORM_EMIT(name, op) \ 982 void Assembler::name(Register r1, Register r3, Register b2, Register x2, \ 983 Disp d2) { \ 984 rxf_form(op, r1, r3, b2, x2, d2); \ 985 } \ 986 void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \ 987 name(r1, r3, opnd.getBaseRegister(), opnd.getIndexRegister(), \ 988 opnd.getDisplacement()); \ 989 } 990 991void Assembler::rxf_form(Opcode op, Register r1, Register r3, Register b2, 992 Register x2, Disp d2) { 993 DCHECK(is_uint12(d2)); 994 DCHECK(is_uint16(op)); 995 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 996 (static_cast<uint64_t>(r3.code())) * B36 | 997 (static_cast<uint64_t>(x2.code())) * B32 | 998 (static_cast<uint64_t>(b2.code())) * B28 | 999 (static_cast<uint64_t>(d2)) * B16 | 1000 (static_cast<uint64_t>(r1.code())) * B12 | 1001 (static_cast<uint64_t>(op & 0x00FF)); 1002 emit6bytes(code); 1003} 1004 1005// SS1 format: <insn> D1(L,B1),D2(B3) 1006// +--------+----+----+----+-------------+----+------------+ 1007// | OpCode | L | B1 | D1 | B2 | D2 | 1008// +--------+----+----+----+-------------+----+------------+ 1009// 0 8 12 16 20 32 36 47 1010#define SS1_FORM_EMIT(name, op) \ 1011 void Assembler::name(Register b1, Disp d1, Register b2, Disp d2, Length l) { \ 1012 ss_form(op, l, b1, d1, b2, d2); \ 1013 } \ 1014 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \ 1015 Length length) { \ 1016 name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \ 1017 opnd2.getBaseRegister(), opnd2.getDisplacement(), length); \ 1018 } 1019 1020void Assembler::ss_form(Opcode op, Length l, Register b1, Disp d1, Register b2, 1021 Disp d2) { 1022 DCHECK(is_uint12(d2)); 1023 DCHECK(is_uint12(d1)); 1024 DCHECK(is_uint8(op)); 1025 DCHECK(is_uint8(l)); 1026 uint64_t code = 1027 (static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l)) * B32 | 1028 (static_cast<uint64_t>(b1.code())) * B28 | 1029 (static_cast<uint64_t>(d1)) * B16 | 1030 (static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2)); 1031 emit6bytes(code); 1032} 1033 1034// SS2 format: <insn> D1(L1,B1), D2(L3,B3) 1035// +--------+----+----+----+-------------+----+------------+ 1036// | OpCode | L1 | L2 | B1 | D1 | B2 | D2 | 1037// +--------+----+----+----+-------------+----+------------+ 1038// 0 8 12 16 20 32 36 47 1039#define SS2_FORM_EMIT(name, op) \ 1040 void Assembler::name(Register b1, Disp d1, Register b2, Disp d2, Length l1, \ 1041 Length l2) { \ 1042 ss_form(op, l1, l2, b1, d1, b2, d2); \ 1043 } \ 1044 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \ 1045 Length length1, Length length2) { \ 1046 name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \ 1047 opnd2.getBaseRegister(), opnd2.getDisplacement(), length1, length2); \ 1048 } 1049 1050void Assembler::ss_form(Opcode op, Length l1, Length l2, Register b1, Disp d1, 1051 Register b2, Disp d2) { 1052 DCHECK(is_uint12(d2)); 1053 DCHECK(is_uint12(d1)); 1054 DCHECK(is_uint8(op)); 1055 DCHECK(is_uint4(l2)); 1056 DCHECK(is_uint4(l1)); 1057 uint64_t code = 1058 (static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l1)) * B36 | 1059 (static_cast<uint64_t>(l2)) * B32 | 1060 (static_cast<uint64_t>(b1.code())) * B28 | 1061 (static_cast<uint64_t>(d1)) * B16 | 1062 (static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2)); 1063 emit6bytes(code); 1064} 1065 1066// SS3 format: <insn> D1(L1,B1), D2(I3,B2) 1067// +--------+----+----+----+-------------+----+------------+ 1068// | OpCode | L1 | I3 | B1 | D1 | B2 | D2 | 1069// +--------+----+----+----+-------------+----+------------+ 1070// 0 8 12 16 20 32 36 47 1071#define SS3_FORM_EMIT(name, op) \ 1072 void Assembler::name(const Operand& i3, Register b1, Disp d1, Register b2, \ 1073 Disp d2, Length l1) { \ 1074 ss_form(op, l1, i3, b1, d1, b2, d2); \ 1075 } \ 1076 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \ 1077 Length length) { \ 1078 DCHECK(false); \ 1079 } 1080void Assembler::ss_form(Opcode op, Length l1, const Operand& i3, Register b1, 1081 Disp d1, Register b2, Disp d2) { 1082 DCHECK(is_uint12(d2)); 1083 DCHECK(is_uint12(d1)); 1084 DCHECK(is_uint8(op)); 1085 DCHECK(is_uint4(l1)); 1086 DCHECK(is_uint4(i3.imm_)); 1087 uint64_t code = 1088 (static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l1)) * B36 | 1089 (static_cast<uint64_t>(i3.imm_)) * B32 | 1090 (static_cast<uint64_t>(b1.code())) * B28 | 1091 (static_cast<uint64_t>(d1)) * B16 | 1092 (static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2)); 1093 emit6bytes(code); 1094} 1095 1096// SS4 format: <insn> D1(R1,B1), D2(R3,B2) 1097// +--------+----+----+----+-------------+----+------------+ 1098// | OpCode | R1 | R3 | B1 | D1 | B2 | D2 | 1099// +--------+----+----+----+-------------+----+------------+ 1100// 0 8 12 16 20 32 36 47 1101#define SS4_FORM_EMIT(name, op) \ 1102 void Assembler::name(Register r1, Register r3, Register b1, Disp d1, \ 1103 Register b2, Disp d2) { \ 1104 ss_form(op, r1, r3, b1, d1, b2, d2); \ 1105 } \ 1106 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \ 1107 DCHECK(false); \ 1108 } 1109void Assembler::ss_form(Opcode op, Register r1, Register r3, Register b1, 1110 Disp d1, Register b2, Disp d2) { 1111 DCHECK(is_uint12(d2)); 1112 DCHECK(is_uint12(d1)); 1113 DCHECK(is_uint8(op)); 1114 uint64_t code = (static_cast<uint64_t>(op)) * B40 | 1115 (static_cast<uint64_t>(r1.code())) * B36 | 1116 (static_cast<uint64_t>(r3.code())) * B32 | 1117 (static_cast<uint64_t>(b1.code())) * B28 | 1118 (static_cast<uint64_t>(d1)) * B16 | 1119 (static_cast<uint64_t>(b2.code())) * B12 | 1120 (static_cast<uint64_t>(d2)); 1121 emit6bytes(code); 1122} 1123 1124// SS5 format: <insn> D1(R1,B1), D2(R3,B2) 1125// +--------+----+----+----+-------------+----+------------+ 1126// | OpCode | R1 | R3 | B2 | D2 | B4 | D4 | 1127// +--------+----+----+----+-------------+----+------------+ 1128// 0 8 12 16 20 32 36 47 1129#define SS5_FORM_EMIT(name, op) \ 1130 void Assembler::name(Register r1, Register r3, Register b2, Disp d2, \ 1131 Register b4, Disp d4) { \ 1132 ss_form(op, r1, r3, b2, d2, b4, d4); /*SS5 use the same form as SS4*/ \ 1133 } \ 1134 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \ 1135 DCHECK(false); \ 1136 } 1137 1138#define SS6_FORM_EMIT(name, op) SS1_FORM_EMIT(name, op) 1139 1140// SSE format: <insn> D1(B1),D2(B2) 1141// +------------------+----+-------------+----+------------+ 1142// | OpCode | B1 | D1 | B2 | D2 | 1143// +------------------+----+-------------+----+------------+ 1144// 0 8 12 16 20 32 36 47 1145#define SSE_FORM_EMIT(name, op) \ 1146 void Assembler::name(Register b1, Disp d1, Register b2, Disp d2) { \ 1147 sse_form(op, b1, d1, b2, d2); \ 1148 } \ 1149 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \ 1150 name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \ 1151 opnd2.getBaseRegister(), opnd2.getDisplacement()); \ 1152 } 1153void Assembler::sse_form(Opcode op, Register b1, Disp d1, Register b2, 1154 Disp d2) { 1155 DCHECK(is_uint12(d2)); 1156 DCHECK(is_uint12(d1)); 1157 DCHECK(is_uint16(op)); 1158 uint64_t code = (static_cast<uint64_t>(op)) * B32 | 1159 (static_cast<uint64_t>(b1.code())) * B28 | 1160 (static_cast<uint64_t>(d1)) * B16 | 1161 (static_cast<uint64_t>(b2.code())) * B12 | 1162 (static_cast<uint64_t>(d2)); 1163 emit6bytes(code); 1164} 1165 1166// SSF format: <insn> R3, D1(B1),D2(B2),R3 1167// +--------+----+----+----+-------------+----+------------+ 1168// | OpCode | R3 |OpCd| B1 | D1 | B2 | D2 | 1169// +--------+----+----+----+-------------+----+------------+ 1170// 0 8 12 16 20 32 36 47 1171#define SSF_FORM_EMIT(name, op) \ 1172 void Assembler::name(Register r3, Register b1, Disp d1, Register b2, \ 1173 Disp d2) { \ 1174 ssf_form(op, r3, b1, d1, b2, d2); \ 1175 } \ 1176 void Assembler::name(Register r3, const MemOperand& opnd1, \ 1177 const MemOperand& opnd2) { \ 1178 name(r3, opnd1.getBaseRegister(), opnd1.getDisplacement(), \ 1179 opnd2.getBaseRegister(), opnd2.getDisplacement()); \ 1180 } 1181 1182void Assembler::ssf_form(Opcode op, Register r3, Register b1, Disp d1, 1183 Register b2, Disp d2) { 1184 DCHECK(is_uint12(d2)); 1185 DCHECK(is_uint12(d1)); 1186 DCHECK(is_uint12(op)); 1187 uint64_t code = (static_cast<uint64_t>(op & 0xFF0)) * B36 | 1188 (static_cast<uint64_t>(r3.code())) * B36 | 1189 (static_cast<uint64_t>(op & 0x00F)) * B32 | 1190 (static_cast<uint64_t>(b1.code())) * B28 | 1191 (static_cast<uint64_t>(d1)) * B16 | 1192 (static_cast<uint64_t>(b2.code())) * B12 | 1193 (static_cast<uint64_t>(d2)); 1194 emit6bytes(code); 1195} 1196 1197// RRF1 format: <insn> R1,R2,R3 1198// +------------------+----+----+----+----+ 1199// | OpCode | R3 | | R1 | R2 | 1200// +------------------+----+----+----+----+ 1201// 0 16 20 24 28 31 1202#define RRF1_FORM_EMIT(name, op) \ 1203 void Assembler::name(Register r1, Register r2, Register r3) { \ 1204 rrf1_form(op << 16 | r3.code() * B12 | r1.code() * B4 | r2.code()); \ 1205 } 1206 1207void Assembler::rrf1_form(Opcode op, Register r1, Register r2, Register r3) { 1208 uint32_t code = op << 16 | r3.code() * B12 | r1.code() * B4 | r2.code(); 1209 emit4bytes(code); 1210} 1211 1212void Assembler::rrf1_form(uint32_t code) { emit4bytes(code); } 1213 1214// RRF2 format: <insn> R1,R2,M3 1215// +------------------+----+----+----+----+ 1216// | OpCode | M3 | | R1 | R2 | 1217// +------------------+----+----+----+----+ 1218// 0 16 20 24 28 31 1219#define RRF2_FORM_EMIT(name, op) \ 1220 void Assembler::name(Condition m3, Register r1, Register r2) { \ 1221 rrf2_form(op << 16 | m3 * B12 | r1.code() * B4 | r2.code()); \ 1222 } 1223 1224void Assembler::rrf2_form(uint32_t code) { emit4bytes(code); } 1225 1226// RRF3 format: <insn> R1,R2,R3,M4 1227// +------------------+----+----+----+----+ 1228// | OpCode | R3 | M4 | R1 | R2 | 1229// +------------------+----+----+----+----+ 1230// 0 16 20 24 28 31 1231#define RRF3_FORM_EMIT(name, op) \ 1232 void Assembler::name(Register r3, Conition m4, Register r1, Register r2) { \ 1233 rrf3_form(op << 16 | r3.code() * B12 | m4 * B8 | r1.code() * B4 | \ 1234 r2.code()); \ 1235 } 1236 1237void Assembler::rrf3_form(uint32_t code) { emit4bytes(code); } 1238 1239// RRF-e format: <insn> R1,M3,R2,M4 1240// +------------------+----+----+----+----+ 1241// | OpCode | M3 | M4 | R1 | R2 | 1242// +------------------+----+----+----+----+ 1243// 0 16 20 24 28 31 1244void Assembler::rrfe_form(Opcode op, Condition m3, Condition m4, Register r1, 1245 Register r2) { 1246 uint32_t code = op << 16 | m3 * B12 | m4 * B8 | r1.code() * B4 | r2.code(); 1247 emit4bytes(code); 1248} 1249 1250// end of S390 Instruction generation 1251 1252// start of S390 instruction 1253SS1_FORM_EMIT(ed, ED) 1254SS1_FORM_EMIT(mvn, MVN) 1255SS1_FORM_EMIT(nc, NC) 1256SI_FORM_EMIT(ni, NI) 1257RI1_FORM_EMIT(nilh, NILH) 1258RI1_FORM_EMIT(nill, NILL) 1259RI1_FORM_EMIT(oill, OILL) 1260RI1_FORM_EMIT(tmll, TMLL) 1261SS1_FORM_EMIT(tr, TR) 1262S_FORM_EMIT(ts, TS) 1263 1264// ------------------------- 1265// Load Address Instructions 1266// ------------------------- 1267// Load Address Relative Long 1268void Assembler::larl(Register r1, Label* l) { 1269 larl(r1, Operand(branch_offset(l))); 1270} 1271 1272// ----------------- 1273// Load Instructions 1274// ----------------- 1275// Load Halfword Immediate (32) 1276void Assembler::lhi(Register r, const Operand& imm) { ri_form(LHI, r, imm); } 1277 1278// Load Halfword Immediate (64) 1279void Assembler::lghi(Register r, const Operand& imm) { ri_form(LGHI, r, imm); } 1280 1281// ------------------------- 1282// Load Logical Instructions 1283// ------------------------- 1284// Load On Condition R-R (32) 1285void Assembler::locr(Condition m3, Register r1, Register r2) { 1286 rrf2_form(LOCR << 16 | m3 * B12 | r1.code() * B4 | r2.code()); 1287} 1288 1289// Load On Condition R-R (64) 1290void Assembler::locgr(Condition m3, Register r1, Register r2) { 1291 rrf2_form(LOCGR << 16 | m3 * B12 | r1.code() * B4 | r2.code()); 1292} 1293 1294// Load On Condition R-M (32) 1295void Assembler::loc(Condition m3, Register r1, const MemOperand& src) { 1296 rsy_form(LOC, r1, m3, src.rb(), src.offset()); 1297} 1298 1299// Load On Condition R-M (64) 1300void Assembler::locg(Condition m3, Register r1, const MemOperand& src) { 1301 rsy_form(LOCG, r1, m3, src.rb(), src.offset()); 1302} 1303 1304// ------------------- 1305// Branch Instructions 1306// ------------------- 1307// Branch on Count (64) 1308// Branch Relative and Save (32) 1309void Assembler::bras(Register r, const Operand& opnd) { 1310 ri_form(BRAS, r, opnd); 1311} 1312 1313// Branch relative on Condition (32) 1314void Assembler::brc(Condition c, const Operand& opnd) { ri_form(BRC, c, opnd); } 1315 1316// Branch On Count (32) 1317void Assembler::brct(Register r1, const Operand& imm) { 1318 // BRCT encodes # of halfwords, so divide by 2. 1319 int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; 1320 Operand halfwordOp = Operand(numHalfwords); 1321 halfwordOp.setBits(16); 1322 ri_form(BRCT, r1, halfwordOp); 1323} 1324 1325// Branch On Count (32) 1326void Assembler::brctg(Register r1, const Operand& imm) { 1327 // BRCTG encodes # of halfwords, so divide by 2. 1328 int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; 1329 Operand halfwordOp = Operand(numHalfwords); 1330 halfwordOp.setBits(16); 1331 ri_form(BRCTG, r1, halfwordOp); 1332} 1333 1334// -------------------- 1335// Compare Instructions 1336// -------------------- 1337// Compare Halfword Immediate (32) 1338void Assembler::chi(Register r, const Operand& opnd) { ri_form(CHI, r, opnd); } 1339 1340// Compare Halfword Immediate (64) 1341void Assembler::cghi(Register r, const Operand& opnd) { 1342 ri_form(CGHI, r, opnd); 1343} 1344 1345// ---------------------------- 1346// Compare Logical Instructions 1347// ---------------------------- 1348// Compare Immediate (Mem - Imm) (8) 1349void Assembler::cli(const MemOperand& opnd, const Operand& imm) { 1350 si_form(CLI, imm, opnd.rb(), opnd.offset()); 1351} 1352 1353// Compare Immediate (Mem - Imm) (8) 1354void Assembler::cliy(const MemOperand& opnd, const Operand& imm) { 1355 siy_form(CLIY, imm, opnd.rb(), opnd.offset()); 1356} 1357 1358// Compare logical - mem to mem operation 1359void Assembler::clc(const MemOperand& opnd1, const MemOperand& opnd2, 1360 Length length) { 1361 ss_form(CLC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(), 1362 opnd2.getBaseRegister(), opnd2.getDisplacement()); 1363} 1364 1365// ---------------------------- 1366// Test Under Mask Instructions 1367// ---------------------------- 1368// Test Under Mask (Mem - Imm) (8) 1369void Assembler::tm(const MemOperand& opnd, const Operand& imm) { 1370 si_form(TM, imm, opnd.rb(), opnd.offset()); 1371} 1372 1373// Test Under Mask (Mem - Imm) (8) 1374void Assembler::tmy(const MemOperand& opnd, const Operand& imm) { 1375 siy_form(TMY, imm, opnd.rb(), opnd.offset()); 1376} 1377 1378// ------------------------------- 1379// Rotate and Insert Selected Bits 1380// ------------------------------- 1381// Rotate-And-Insert-Selected-Bits 1382void Assembler::risbg(Register dst, Register src, const Operand& startBit, 1383 const Operand& endBit, const Operand& shiftAmt, 1384 bool zeroBits) { 1385 // High tag the top bit of I4/EndBit to zero out any unselected bits 1386 if (zeroBits) 1387 rie_f_form(RISBG, dst, src, startBit, Operand(endBit.imm_ | 0x80), 1388 shiftAmt); 1389 else 1390 rie_f_form(RISBG, dst, src, startBit, endBit, shiftAmt); 1391} 1392 1393// Rotate-And-Insert-Selected-Bits 1394void Assembler::risbgn(Register dst, Register src, const Operand& startBit, 1395 const Operand& endBit, const Operand& shiftAmt, 1396 bool zeroBits) { 1397 // High tag the top bit of I4/EndBit to zero out any unselected bits 1398 if (zeroBits) 1399 rie_f_form(RISBGN, dst, src, startBit, Operand(endBit.imm_ | 0x80), 1400 shiftAmt); 1401 else 1402 rie_f_form(RISBGN, dst, src, startBit, endBit, shiftAmt); 1403} 1404 1405// --------------------------- 1406// Move Character Instructions 1407// --------------------------- 1408// Move charactor - mem to mem operation 1409void Assembler::mvc(const MemOperand& opnd1, const MemOperand& opnd2, 1410 uint32_t length) { 1411 ss_form(MVC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(), 1412 opnd2.getBaseRegister(), opnd2.getDisplacement()); 1413} 1414 1415// ----------------------- 1416// 32-bit Add Instructions 1417// ----------------------- 1418// Add Halfword Immediate (32) 1419void Assembler::ahi(Register r1, const Operand& i2) { ri_form(AHI, r1, i2); } 1420 1421// Add Halfword Immediate (32) 1422void Assembler::ahik(Register r1, Register r3, const Operand& i2) { 1423 rie_form(AHIK, r1, r3, i2); 1424} 1425 1426// Add Register-Register-Register (32) 1427void Assembler::ark(Register r1, Register r2, Register r3) { 1428 rrf1_form(ARK, r1, r2, r3); 1429} 1430 1431// Add Storage-Imm (32) 1432void Assembler::asi(const MemOperand& opnd, const Operand& imm) { 1433 DCHECK(is_int8(imm.imm_)); 1434 DCHECK(is_int20(opnd.offset())); 1435 siy_form(ASI, Operand(0xff & imm.imm_), opnd.rb(), 0xfffff & opnd.offset()); 1436} 1437 1438// ----------------------- 1439// 64-bit Add Instructions 1440// ----------------------- 1441// Add Halfword Immediate (64) 1442void Assembler::aghi(Register r1, const Operand& i2) { ri_form(AGHI, r1, i2); } 1443 1444// Add Halfword Immediate (64) 1445void Assembler::aghik(Register r1, Register r3, const Operand& i2) { 1446 rie_form(AGHIK, r1, r3, i2); 1447} 1448 1449// Add Register-Register-Register (64) 1450void Assembler::agrk(Register r1, Register r2, Register r3) { 1451 rrf1_form(AGRK, r1, r2, r3); 1452} 1453 1454// Add Storage-Imm (64) 1455void Assembler::agsi(const MemOperand& opnd, const Operand& imm) { 1456 DCHECK(is_int8(imm.imm_)); 1457 DCHECK(is_int20(opnd.offset())); 1458 siy_form(AGSI, Operand(0xff & imm.imm_), opnd.rb(), 0xfffff & opnd.offset()); 1459} 1460 1461// ------------------------------- 1462// 32-bit Add Logical Instructions 1463// ------------------------------- 1464// Add Logical Register-Register-Register (32) 1465void Assembler::alrk(Register r1, Register r2, Register r3) { 1466 rrf1_form(ALRK, r1, r2, r3); 1467} 1468 1469// ------------------------------- 1470// 64-bit Add Logical Instructions 1471// ------------------------------- 1472// Add Logical Register-Register-Register (64) 1473void Assembler::algrk(Register r1, Register r2, Register r3) { 1474 rrf1_form(ALGRK, r1, r2, r3); 1475} 1476 1477// ---------------------------- 1478// 32-bit Subtract Instructions 1479// ---------------------------- 1480// Subtract Register-Register-Register (32) 1481void Assembler::srk(Register r1, Register r2, Register r3) { 1482 rrf1_form(SRK, r1, r2, r3); 1483} 1484 1485// ---------------------------- 1486// 64-bit Subtract Instructions 1487// ---------------------------- 1488// Subtract Register-Register-Register (64) 1489void Assembler::sgrk(Register r1, Register r2, Register r3) { 1490 rrf1_form(SGRK, r1, r2, r3); 1491} 1492 1493// ------------------------------------ 1494// 32-bit Subtract Logical Instructions 1495// ------------------------------------ 1496// Subtract Logical Register-Register-Register (32) 1497void Assembler::slrk(Register r1, Register r2, Register r3) { 1498 rrf1_form(SLRK, r1, r2, r3); 1499} 1500 1501// ------------------------------------ 1502// 64-bit Subtract Logical Instructions 1503// ------------------------------------ 1504// Subtract Logical Register-Register-Register (64) 1505void Assembler::slgrk(Register r1, Register r2, Register r3) { 1506 rrf1_form(SLGRK, r1, r2, r3); 1507} 1508 1509// ---------------------------- 1510// 32-bit Multiply Instructions 1511// ---------------------------- 1512// Multiply Halfword Immediate (32) 1513void Assembler::mhi(Register r1, const Operand& opnd) { 1514 ri_form(MHI, r1, opnd); 1515} 1516 1517// Multiply Single Register (32) 1518void Assembler::msrkc(Register r1, Register r2, Register r3) { 1519 rrf1_form(MSRKC, r1, r2, r3); 1520} 1521 1522// Multiply Single Register (64) 1523void Assembler::msgrkc(Register r1, Register r2, Register r3) { 1524 rrf1_form(MSGRKC, r1, r2, r3); 1525} 1526 1527// ---------------------------- 1528// 64-bit Multiply Instructions 1529// ---------------------------- 1530// Multiply Halfword Immediate (64) 1531void Assembler::mghi(Register r1, const Operand& opnd) { 1532 ri_form(MGHI, r1, opnd); 1533} 1534 1535// -------------------- 1536// Bitwise Instructions 1537// -------------------- 1538// AND Register-Register-Register (32) 1539void Assembler::nrk(Register r1, Register r2, Register r3) { 1540 rrf1_form(NRK, r1, r2, r3); 1541} 1542 1543// AND Register-Register-Register (64) 1544void Assembler::ngrk(Register r1, Register r2, Register r3) { 1545 rrf1_form(NGRK, r1, r2, r3); 1546} 1547 1548// OR Register-Register-Register (32) 1549void Assembler::ork(Register r1, Register r2, Register r3) { 1550 rrf1_form(ORK, r1, r2, r3); 1551} 1552 1553// OR Register-Register-Register (64) 1554void Assembler::ogrk(Register r1, Register r2, Register r3) { 1555 rrf1_form(OGRK, r1, r2, r3); 1556} 1557 1558// XOR Register-Register-Register (32) 1559void Assembler::xrk(Register r1, Register r2, Register r3) { 1560 rrf1_form(XRK, r1, r2, r3); 1561} 1562 1563// XOR Register-Register-Register (64) 1564void Assembler::xgrk(Register r1, Register r2, Register r3) { 1565 rrf1_form(XGRK, r1, r2, r3); 1566} 1567 1568// XOR Storage-Storage 1569void Assembler::xc(const MemOperand& opnd1, const MemOperand& opnd2, 1570 Length length) { 1571 ss_form(XC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(), 1572 opnd2.getBaseRegister(), opnd2.getDisplacement()); 1573} 1574 1575void Assembler::EnsureSpaceFor(int space_needed) { 1576 if (buffer_space() <= (kGap + space_needed)) { 1577 GrowBuffer(space_needed); 1578 } 1579} 1580 1581// Rotate Left Single Logical (32) 1582void Assembler::rll(Register r1, Register r3, Register opnd) { 1583 DCHECK(!opnd.is(r0)); 1584 rsy_form(RLL, r1, r3, opnd, 0); 1585} 1586 1587// Rotate Left Single Logical (32) 1588void Assembler::rll(Register r1, Register r3, const Operand& opnd) { 1589 rsy_form(RLL, r1, r3, r0, opnd.immediate()); 1590} 1591 1592// Rotate Left Single Logical (32) 1593void Assembler::rll(Register r1, Register r3, Register r2, 1594 const Operand& opnd) { 1595 rsy_form(RLL, r1, r3, r2, opnd.immediate()); 1596} 1597 1598// Rotate Left Single Logical (64) 1599void Assembler::rllg(Register r1, Register r3, Register opnd) { 1600 DCHECK(!opnd.is(r0)); 1601 rsy_form(RLLG, r1, r3, opnd, 0); 1602} 1603 1604// Rotate Left Single Logical (64) 1605void Assembler::rllg(Register r1, Register r3, const Operand& opnd) { 1606 rsy_form(RLLG, r1, r3, r0, opnd.immediate()); 1607} 1608 1609// Rotate Left Single Logical (64) 1610void Assembler::rllg(Register r1, Register r3, Register r2, 1611 const Operand& opnd) { 1612 rsy_form(RLLG, r1, r3, r2, opnd.immediate()); 1613} 1614 1615// Shift Left Single Logical (32) 1616void Assembler::sll(Register r1, Register opnd) { 1617 DCHECK(!opnd.is(r0)); 1618 rs_form(SLL, r1, r0, opnd, 0); 1619} 1620 1621// Shift Left Single Logical (32) 1622void Assembler::sll(Register r1, const Operand& opnd) { 1623 rs_form(SLL, r1, r0, r0, opnd.immediate()); 1624} 1625 1626// Shift Left Single Logical (32) 1627void Assembler::sllk(Register r1, Register r3, Register opnd) { 1628 DCHECK(!opnd.is(r0)); 1629 rsy_form(SLLK, r1, r3, opnd, 0); 1630} 1631 1632// Shift Left Single Logical (32) 1633void Assembler::sllk(Register r1, Register r3, const Operand& opnd) { 1634 rsy_form(SLLK, r1, r3, r0, opnd.immediate()); 1635} 1636 1637// Shift Left Single Logical (64) 1638void Assembler::sllg(Register r1, Register r3, Register opnd) { 1639 DCHECK(!opnd.is(r0)); 1640 rsy_form(SLLG, r1, r3, opnd, 0); 1641} 1642 1643// Shift Left Single Logical (64) 1644void Assembler::sllg(Register r1, Register r3, const Operand& opnd) { 1645 rsy_form(SLLG, r1, r3, r0, opnd.immediate()); 1646} 1647 1648// Shift Left Double Logical (64) 1649void Assembler::sldl(Register r1, Register b2, const Operand& opnd) { 1650 DCHECK(r1.code() % 2 == 0); 1651 rs_form(SLDL, r1, r0, b2, opnd.immediate()); 1652} 1653 1654// Shift Right Single Logical (32) 1655void Assembler::srl(Register r1, Register opnd) { 1656 DCHECK(!opnd.is(r0)); 1657 rs_form(SRL, r1, r0, opnd, 0); 1658} 1659 1660// Shift Right Double Arith (64) 1661void Assembler::srda(Register r1, Register b2, const Operand& opnd) { 1662 DCHECK(r1.code() % 2 == 0); 1663 rs_form(SRDA, r1, r0, b2, opnd.immediate()); 1664} 1665 1666// Shift Right Double Logical (64) 1667void Assembler::srdl(Register r1, Register b2, const Operand& opnd) { 1668 DCHECK(r1.code() % 2 == 0); 1669 rs_form(SRDL, r1, r0, b2, opnd.immediate()); 1670} 1671 1672// Shift Right Single Logical (32) 1673void Assembler::srl(Register r1, const Operand& opnd) { 1674 rs_form(SRL, r1, r0, r0, opnd.immediate()); 1675} 1676 1677// Shift Right Single Logical (32) 1678void Assembler::srlk(Register r1, Register r3, Register opnd) { 1679 DCHECK(!opnd.is(r0)); 1680 rsy_form(SRLK, r1, r3, opnd, 0); 1681} 1682 1683// Shift Right Single Logical (32) 1684void Assembler::srlk(Register r1, Register r3, const Operand& opnd) { 1685 rsy_form(SRLK, r1, r3, r0, opnd.immediate()); 1686} 1687 1688// Shift Right Single Logical (64) 1689void Assembler::srlg(Register r1, Register r3, Register opnd) { 1690 DCHECK(!opnd.is(r0)); 1691 rsy_form(SRLG, r1, r3, opnd, 0); 1692} 1693 1694// Shift Right Single Logical (64) 1695void Assembler::srlg(Register r1, Register r3, const Operand& opnd) { 1696 rsy_form(SRLG, r1, r3, r0, opnd.immediate()); 1697} 1698 1699// Shift Left Single (32) 1700void Assembler::sla(Register r1, Register opnd) { 1701 DCHECK(!opnd.is(r0)); 1702 rs_form(SLA, r1, r0, opnd, 0); 1703} 1704 1705// Shift Left Single (32) 1706void Assembler::sla(Register r1, const Operand& opnd) { 1707 rs_form(SLA, r1, r0, r0, opnd.immediate()); 1708} 1709 1710// Shift Left Single (32) 1711void Assembler::slak(Register r1, Register r3, Register opnd) { 1712 DCHECK(!opnd.is(r0)); 1713 rsy_form(SLAK, r1, r3, opnd, 0); 1714} 1715 1716// Shift Left Single (32) 1717void Assembler::slak(Register r1, Register r3, const Operand& opnd) { 1718 rsy_form(SLAK, r1, r3, r0, opnd.immediate()); 1719} 1720 1721// Shift Left Single (64) 1722void Assembler::slag(Register r1, Register r3, Register opnd) { 1723 DCHECK(!opnd.is(r0)); 1724 rsy_form(SLAG, r1, r3, opnd, 0); 1725} 1726 1727// Shift Left Single (64) 1728void Assembler::slag(Register r1, Register r3, const Operand& opnd) { 1729 rsy_form(SLAG, r1, r3, r0, opnd.immediate()); 1730} 1731 1732// Shift Right Single (32) 1733void Assembler::sra(Register r1, Register opnd) { 1734 DCHECK(!opnd.is(r0)); 1735 rs_form(SRA, r1, r0, opnd, 0); 1736} 1737 1738// Shift Right Single (32) 1739void Assembler::sra(Register r1, const Operand& opnd) { 1740 rs_form(SRA, r1, r0, r0, opnd.immediate()); 1741} 1742 1743// Shift Right Single (32) 1744void Assembler::srak(Register r1, Register r3, Register opnd) { 1745 DCHECK(!opnd.is(r0)); 1746 rsy_form(SRAK, r1, r3, opnd, 0); 1747} 1748 1749// Shift Right Single (32) 1750void Assembler::srak(Register r1, Register r3, const Operand& opnd) { 1751 rsy_form(SRAK, r1, r3, r0, opnd.immediate()); 1752} 1753 1754// Shift Right Single (64) 1755void Assembler::srag(Register r1, Register r3, Register opnd) { 1756 DCHECK(!opnd.is(r0)); 1757 rsy_form(SRAG, r1, r3, opnd, 0); 1758} 1759 1760void Assembler::srag(Register r1, Register r3, const Operand& opnd) { 1761 rsy_form(SRAG, r1, r3, r0, opnd.immediate()); 1762} 1763 1764// Shift Right Double 1765void Assembler::srda(Register r1, const Operand& opnd) { 1766 DCHECK(r1.code() % 2 == 0); 1767 rs_form(SRDA, r1, r0, r0, opnd.immediate()); 1768} 1769 1770// Shift Right Double Logical 1771void Assembler::srdl(Register r1, const Operand& opnd) { 1772 DCHECK(r1.code() % 2 == 0); 1773 rs_form(SRDL, r1, r0, r0, opnd.immediate()); 1774} 1775 1776void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode, 1777 TypeFeedbackId ast_id) { 1778 EnsureSpace ensure_space(this); 1779 1780 int32_t target_index = emit_code_target(target, rmode, ast_id); 1781 brasl(r14, Operand(target_index)); 1782} 1783 1784void Assembler::jump(Handle<Code> target, RelocInfo::Mode rmode, 1785 Condition cond) { 1786 EnsureSpace ensure_space(this); 1787 1788 int32_t target_index = emit_code_target(target, rmode); 1789 brcl(cond, Operand(target_index)); 1790} 1791 1792// 32-bit Load Multiple - short displacement (12-bits unsigned) 1793void Assembler::lm(Register r1, Register r2, const MemOperand& src) { 1794 rs_form(LM, r1, r2, src.rb(), src.offset()); 1795} 1796 1797// 32-bit Load Multiple - long displacement (20-bits signed) 1798void Assembler::lmy(Register r1, Register r2, const MemOperand& src) { 1799 rsy_form(LMY, r1, r2, src.rb(), src.offset()); 1800} 1801 1802// 64-bit Load Multiple - long displacement (20-bits signed) 1803void Assembler::lmg(Register r1, Register r2, const MemOperand& src) { 1804 rsy_form(LMG, r1, r2, src.rb(), src.offset()); 1805} 1806 1807// Move integer (32) 1808void Assembler::mvhi(const MemOperand& opnd1, const Operand& i2) { 1809 sil_form(MVHI, opnd1.getBaseRegister(), opnd1.getDisplacement(), i2); 1810} 1811 1812// Move integer (64) 1813void Assembler::mvghi(const MemOperand& opnd1, const Operand& i2) { 1814 sil_form(MVGHI, opnd1.getBaseRegister(), opnd1.getDisplacement(), i2); 1815} 1816 1817// Insert Immediate (high high) 1818void Assembler::iihh(Register r1, const Operand& opnd) { 1819 ri_form(IIHH, r1, opnd); 1820} 1821 1822// Insert Immediate (high low) 1823void Assembler::iihl(Register r1, const Operand& opnd) { 1824 ri_form(IIHL, r1, opnd); 1825} 1826 1827// Insert Immediate (low high) 1828void Assembler::iilh(Register r1, const Operand& opnd) { 1829 ri_form(IILH, r1, opnd); 1830} 1831 1832// Insert Immediate (low low) 1833void Assembler::iill(Register r1, const Operand& opnd) { 1834 ri_form(IILL, r1, opnd); 1835} 1836 1837// GPR <-> FPR Instructions 1838 1839// Floating point instructions 1840// 1841// Add Register-Storage (LB) 1842void Assembler::adb(DoubleRegister r1, const MemOperand& opnd) { 1843 rxe_form(ADB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), 1844 opnd.offset()); 1845} 1846 1847// Divide Register-Storage (LB) 1848void Assembler::ddb(DoubleRegister r1, const MemOperand& opnd) { 1849 rxe_form(DDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), 1850 opnd.offset()); 1851} 1852 1853// Multiply Register-Storage (LB) 1854void Assembler::mdb(DoubleRegister r1, const MemOperand& opnd) { 1855 rxe_form(MDB, Register::from_code(r1.code()), opnd.rb(), opnd.rx(), 1856 opnd.offset()); 1857} 1858 1859// Subtract Register-Storage (LB) 1860void Assembler::sdb(DoubleRegister r1, const MemOperand& opnd) { 1861 rxe_form(SDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), 1862 opnd.offset()); 1863} 1864 1865void Assembler::ceb(DoubleRegister r1, const MemOperand& opnd) { 1866 rxe_form(CEB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), 1867 opnd.offset()); 1868} 1869 1870void Assembler::cdb(DoubleRegister r1, const MemOperand& opnd) { 1871 rxe_form(CDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), 1872 opnd.offset()); 1873} 1874 1875// Square Root (LB) 1876void Assembler::sqdb(DoubleRegister r1, const MemOperand& opnd) { 1877 rxe_form(SQDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), 1878 opnd.offset()); 1879} 1880 1881// Convert to Fixed point (64<-S) 1882void Assembler::cgebr(Condition m, Register r1, DoubleRegister r2) { 1883 rrfe_form(CGEBR, m, Condition(0), r1, Register::from_code(r2.code())); 1884} 1885 1886// Convert to Fixed point (64<-L) 1887void Assembler::cgdbr(Condition m, Register r1, DoubleRegister r2) { 1888 rrfe_form(CGDBR, m, Condition(0), r1, Register::from_code(r2.code())); 1889} 1890 1891// Convert to Fixed point (32<-L) 1892void Assembler::cfdbr(Condition m, Register r1, DoubleRegister r2) { 1893 rrfe_form(CFDBR, m, Condition(0), r1, Register::from_code(r2.code())); 1894} 1895 1896// Convert to Fixed Logical (64<-L) 1897void Assembler::clgdbr(Condition m3, Condition m4, Register r1, 1898 DoubleRegister r2) { 1899 DCHECK_EQ(m4, Condition(0)); 1900 rrfe_form(CLGDBR, m3, m4, r1, Register::from_code(r2.code())); 1901} 1902 1903// Convert to Fixed Logical (64<-F32) 1904void Assembler::clgebr(Condition m3, Condition m4, Register r1, 1905 DoubleRegister r2) { 1906 DCHECK_EQ(m4, Condition(0)); 1907 rrfe_form(CLGEBR, m3, m4, r1, Register::from_code(r2.code())); 1908} 1909 1910// Convert to Fixed Logical (32<-F64) 1911void Assembler::clfdbr(Condition m3, Condition m4, Register r1, 1912 DoubleRegister r2) { 1913 DCHECK_EQ(m3, Condition(0)); 1914 DCHECK_EQ(m4, Condition(0)); 1915 rrfe_form(CLFDBR, Condition(0), Condition(0), r1, 1916 Register::from_code(r2.code())); 1917} 1918 1919// Convert to Fixed Logical (32<-F32) 1920void Assembler::clfebr(Condition m3, Condition m4, Register r1, 1921 DoubleRegister r2) { 1922 DCHECK_EQ(m4, Condition(0)); 1923 rrfe_form(CLFEBR, m3, Condition(0), r1, Register::from_code(r2.code())); 1924} 1925 1926// Convert from Fixed Logical (L<-64) 1927void Assembler::celgbr(Condition m3, Condition m4, DoubleRegister r1, 1928 Register r2) { 1929 DCHECK_EQ(m3, Condition(0)); 1930 DCHECK_EQ(m4, Condition(0)); 1931 rrfe_form(CELGBR, Condition(0), Condition(0), Register::from_code(r1.code()), 1932 r2); 1933} 1934 1935// Convert from Fixed Logical (F32<-32) 1936void Assembler::celfbr(Condition m3, Condition m4, DoubleRegister r1, 1937 Register r2) { 1938 DCHECK_EQ(m4, Condition(0)); 1939 rrfe_form(CELFBR, m3, Condition(0), Register::from_code(r1.code()), r2); 1940} 1941 1942// Convert from Fixed Logical (L<-64) 1943void Assembler::cdlgbr(Condition m3, Condition m4, DoubleRegister r1, 1944 Register r2) { 1945 DCHECK_EQ(m3, Condition(0)); 1946 DCHECK_EQ(m4, Condition(0)); 1947 rrfe_form(CDLGBR, Condition(0), Condition(0), Register::from_code(r1.code()), 1948 r2); 1949} 1950 1951// Convert from Fixed Logical (L<-32) 1952void Assembler::cdlfbr(Condition m3, Condition m4, DoubleRegister r1, 1953 Register r2) { 1954 DCHECK_EQ(m4, Condition(0)); 1955 rrfe_form(CDLFBR, m3, Condition(0), Register::from_code(r1.code()), r2); 1956} 1957 1958// Convert from Fixed point (S<-32) 1959void Assembler::cefbr(Condition m3, DoubleRegister r1, Register r2) { 1960 rrfe_form(CEFBR, m3, Condition(0), Register::from_code(r1.code()), r2); 1961} 1962 1963// Convert to Fixed point (32<-S) 1964void Assembler::cfebr(Condition m3, Register r1, DoubleRegister r2) { 1965 rrfe_form(CFEBR, m3, Condition(0), r1, Register::from_code(r2.code())); 1966} 1967 1968// Load (L <- S) 1969void Assembler::ldeb(DoubleRegister d1, const MemOperand& opnd) { 1970 rxe_form(LDEB, Register::from_code(d1.code()), opnd.rx(), opnd.rb(), 1971 opnd.offset()); 1972} 1973 1974// Load FP Integer 1975void Assembler::fiebra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3) { 1976 rrf2_form(FIEBRA << 16 | m3 * B12 | d1.code() * B4 | d2.code()); 1977} 1978 1979// Load FP Integer 1980void Assembler::fidbra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3) { 1981 rrf2_form(FIDBRA << 16 | m3 * B12 | d1.code() * B4 | d2.code()); 1982} 1983 1984// end of S390instructions 1985 1986bool Assembler::IsNop(SixByteInstr instr, int type) { 1987 DCHECK((0 == type) || (DEBUG_BREAK_NOP == type)); 1988 if (DEBUG_BREAK_NOP == type) { 1989 return ((instr & 0xffffffff) == 0xa53b0000); // oill r3, 0 1990 } 1991 return ((instr & 0xffff) == 0x1800); // lr r0,r0 1992} 1993 1994// dummy instruction reserved for special use. 1995void Assembler::dumy(int r1, int x2, int b2, int d2) { 1996#if defined(USE_SIMULATOR) 1997 int op = 0xE353; 1998 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | 1999 (static_cast<uint64_t>(r1) & 0xF) * B36 | 2000 (static_cast<uint64_t>(x2) & 0xF) * B32 | 2001 (static_cast<uint64_t>(b2) & 0xF) * B28 | 2002 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | 2003 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | 2004 (static_cast<uint64_t>(op & 0x00FF)); 2005 emit6bytes(code); 2006#endif 2007} 2008 2009void Assembler::GrowBuffer(int needed) { 2010 if (!own_buffer_) FATAL("external code buffer is too small"); 2011 2012 // Compute new buffer size. 2013 CodeDesc desc; // the new buffer 2014 if (buffer_size_ < 4 * KB) { 2015 desc.buffer_size = 4 * KB; 2016 } else if (buffer_size_ < 1 * MB) { 2017 desc.buffer_size = 2 * buffer_size_; 2018 } else { 2019 desc.buffer_size = buffer_size_ + 1 * MB; 2020 } 2021 int space = buffer_space() + (desc.buffer_size - buffer_size_); 2022 if (space < needed) { 2023 desc.buffer_size += needed - space; 2024 } 2025 CHECK_GT(desc.buffer_size, 0); // no overflow 2026 2027 // Set up new buffer. 2028 desc.buffer = NewArray<byte>(desc.buffer_size); 2029 desc.origin = this; 2030 2031 desc.instr_size = pc_offset(); 2032 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); 2033 2034 // Copy the data. 2035 intptr_t pc_delta = desc.buffer - buffer_; 2036 intptr_t rc_delta = 2037 (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); 2038 memmove(desc.buffer, buffer_, desc.instr_size); 2039 memmove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), 2040 desc.reloc_size); 2041 2042 // Switch buffers. 2043 DeleteArray(buffer_); 2044 buffer_ = desc.buffer; 2045 buffer_size_ = desc.buffer_size; 2046 pc_ += pc_delta; 2047 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, 2048 reloc_info_writer.last_pc() + pc_delta); 2049 2050 // None of our relocation types are pc relative pointing outside the code 2051 // buffer nor pc absolute pointing inside the code buffer, so there is no need 2052 // to relocate any emitted relocation entries. 2053} 2054 2055void Assembler::db(uint8_t data) { 2056 CheckBuffer(); 2057 *reinterpret_cast<uint8_t*>(pc_) = data; 2058 pc_ += sizeof(uint8_t); 2059} 2060 2061void Assembler::dd(uint32_t data) { 2062 CheckBuffer(); 2063 *reinterpret_cast<uint32_t*>(pc_) = data; 2064 pc_ += sizeof(uint32_t); 2065} 2066 2067void Assembler::dq(uint64_t value) { 2068 CheckBuffer(); 2069 *reinterpret_cast<uint64_t*>(pc_) = value; 2070 pc_ += sizeof(uint64_t); 2071} 2072 2073void Assembler::dp(uintptr_t data) { 2074 CheckBuffer(); 2075 *reinterpret_cast<uintptr_t*>(pc_) = data; 2076 pc_ += sizeof(uintptr_t); 2077} 2078 2079void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { 2080 if (RelocInfo::IsNone(rmode) || 2081 // Don't record external references unless the heap will be serialized. 2082 (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() && 2083 !emit_debug_code())) { 2084 return; 2085 } 2086 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { 2087 data = RecordedAstId().ToInt(); 2088 ClearRecordedAstId(); 2089 } 2090 DeferredRelocInfo rinfo(pc_offset(), rmode, data); 2091 relocations_.push_back(rinfo); 2092} 2093 2094void Assembler::emit_label_addr(Label* label) { 2095 CheckBuffer(); 2096 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); 2097 int position = link(label); 2098 DCHECK(label->is_bound()); 2099 // Keep internal references relative until EmitRelocations. 2100 dp(position); 2101} 2102 2103void Assembler::EmitRelocations() { 2104 EnsureSpaceFor(relocations_.size() * kMaxRelocSize); 2105 2106 for (std::vector<DeferredRelocInfo>::iterator it = relocations_.begin(); 2107 it != relocations_.end(); it++) { 2108 RelocInfo::Mode rmode = it->rmode(); 2109 Address pc = buffer_ + it->position(); 2110 Code* code = NULL; 2111 RelocInfo rinfo(isolate(), pc, rmode, it->data(), code); 2112 2113 // Fix up internal references now that they are guaranteed to be bound. 2114 if (RelocInfo::IsInternalReference(rmode)) { 2115 // Jump table entry 2116 intptr_t pos = reinterpret_cast<intptr_t>(Memory::Address_at(pc)); 2117 Memory::Address_at(pc) = buffer_ + pos; 2118 } else if (RelocInfo::IsInternalReferenceEncoded(rmode)) { 2119 // mov sequence 2120 intptr_t pos = reinterpret_cast<intptr_t>(target_address_at(pc, code)); 2121 set_target_address_at(isolate(), pc, code, buffer_ + pos, 2122 SKIP_ICACHE_FLUSH); 2123 } 2124 2125 reloc_info_writer.Write(&rinfo); 2126 } 2127} 2128 2129} // namespace internal 2130} // namespace v8 2131#endif // V8_TARGET_ARCH_S390 2132