OLD | NEW |
(Empty) | |
| 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 |
| 51 namespace v8 { |
| 52 namespace internal { |
| 53 |
| 54 // Get the CPU features enabled by the build. |
| 55 static 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. |
| 62 static 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 |
| 117 void 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[1]; |
| 142 facilities[0] = 0; |
| 143 // LHI sets up GPR0 |
| 144 // STFLE is specified as .insn, as opcode is not recognized. |
| 145 // We register the instructions kill r0 (LHI) and the CC (STFLE). |
| 146 asm volatile( |
| 147 "lhi 0,0\n" |
| 148 ".insn s,0xb2b00000,%0\n" |
| 149 : "=Q"(facilities) |
| 150 : |
| 151 : "cc", "r0"); |
| 152 |
| 153 // Test for Distinct Operands Facility - Bit 45 |
| 154 if (facilities[0] & (1lu << (63 - 45))) { |
| 155 supported_ |= (1u << DISTINCT_OPS); |
| 156 } |
| 157 // Test for General Instruction Extension Facility - Bit 34 |
| 158 if (facilities[0] & (1lu << (63 - 34))) { |
| 159 supported_ |= (1u << GENERAL_INSTR_EXT); |
| 160 } |
| 161 // Test for Floating Point Extension Facility - Bit 37 |
| 162 if (facilities[0] & (1lu << (63 - 37))) { |
| 163 supported_ |= (1u << FLOATING_POINT_EXT); |
| 164 } |
| 165 } |
| 166 #else |
| 167 // All distinct ops instructions can be simulated |
| 168 supported_ |= (1u << DISTINCT_OPS); |
| 169 // RISBG can be simulated |
| 170 supported_ |= (1u << GENERAL_INSTR_EXT); |
| 171 |
| 172 supported_ |= (1u << FLOATING_POINT_EXT); |
| 173 USE(performSTFLE); // To avoid assert |
| 174 #endif |
| 175 supported_ |= (1u << FPU); |
| 176 } |
| 177 |
| 178 void CpuFeatures::PrintTarget() { |
| 179 const char* s390_arch = NULL; |
| 180 |
| 181 #if V8_TARGET_ARCH_S390X |
| 182 s390_arch = "s390x"; |
| 183 #else |
| 184 s390_arch = "s390"; |
| 185 #endif |
| 186 |
| 187 printf("target %s\n", s390_arch); |
| 188 } |
| 189 |
| 190 void CpuFeatures::PrintFeatures() { |
| 191 printf("FPU=%d\n", CpuFeatures::IsSupported(FPU)); |
| 192 printf("FPU_EXT=%d\n", CpuFeatures::IsSupported(FLOATING_POINT_EXT)); |
| 193 printf("GENERAL_INSTR=%d\n", CpuFeatures::IsSupported(GENERAL_INSTR_EXT)); |
| 194 printf("DISTINCT_OPS=%d\n", CpuFeatures::IsSupported(DISTINCT_OPS)); |
| 195 } |
| 196 |
| 197 Register ToRegister(int num) { |
| 198 DCHECK(num >= 0 && num < kNumRegisters); |
| 199 const Register kRegisters[] = {r0, r1, r2, r3, r4, r5, r6, r7, |
| 200 r8, r9, r10, fp, ip, r13, r14, sp}; |
| 201 return kRegisters[num]; |
| 202 } |
| 203 |
| 204 // ----------------------------------------------------------------------------- |
| 205 // Implementation of RelocInfo |
| 206 |
| 207 const int RelocInfo::kApplyMask = |
| 208 RelocInfo::kCodeTargetMask | 1 << RelocInfo::INTERNAL_REFERENCE; |
| 209 |
| 210 bool RelocInfo::IsCodedSpecially() { |
| 211 // The deserializer needs to know whether a pointer is specially |
| 212 // coded. Being specially coded on S390 means that it is an iihf/iilf |
| 213 // instruction sequence, and that is always the case inside code |
| 214 // objects. |
| 215 return true; |
| 216 } |
| 217 |
| 218 bool RelocInfo::IsInConstantPool() { return false; } |
| 219 |
| 220 // ----------------------------------------------------------------------------- |
| 221 // Implementation of Operand and MemOperand |
| 222 // See assembler-s390-inl.h for inlined constructors |
| 223 |
| 224 Operand::Operand(Handle<Object> handle) { |
| 225 AllowDeferredHandleDereference using_raw_address; |
| 226 rm_ = no_reg; |
| 227 // Verify all Objects referred by code are NOT in new space. |
| 228 Object* obj = *handle; |
| 229 if (obj->IsHeapObject()) { |
| 230 DCHECK(!HeapObject::cast(obj)->GetHeap()->InNewSpace(obj)); |
| 231 imm_ = reinterpret_cast<intptr_t>(handle.location()); |
| 232 rmode_ = RelocInfo::EMBEDDED_OBJECT; |
| 233 } else { |
| 234 // no relocation needed |
| 235 imm_ = reinterpret_cast<intptr_t>(obj); |
| 236 rmode_ = kRelocInfo_NONEPTR; |
| 237 } |
| 238 } |
| 239 |
| 240 MemOperand::MemOperand(Register rn, int32_t offset) { |
| 241 baseRegister = rn; |
| 242 indexRegister = r0; |
| 243 offset_ = offset; |
| 244 } |
| 245 |
| 246 MemOperand::MemOperand(Register rx, Register rb, int32_t offset) { |
| 247 baseRegister = rb; |
| 248 indexRegister = rx; |
| 249 offset_ = offset; |
| 250 } |
| 251 |
| 252 // ----------------------------------------------------------------------------- |
| 253 // Specific instructions, constants, and masks. |
| 254 |
| 255 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) |
| 256 : AssemblerBase(isolate, buffer, buffer_size), |
| 257 recorded_ast_id_(TypeFeedbackId::None()), |
| 258 code_targets_(100), |
| 259 positions_recorder_(this) { |
| 260 reloc_info_writer.Reposition(buffer_ + buffer_size_, pc_); |
| 261 |
| 262 last_bound_pos_ = 0; |
| 263 ClearRecordedAstId(); |
| 264 relocations_.reserve(128); |
| 265 } |
| 266 |
| 267 void Assembler::GetCode(CodeDesc* desc) { |
| 268 EmitRelocations(); |
| 269 |
| 270 // Set up code descriptor. |
| 271 desc->buffer = buffer_; |
| 272 desc->buffer_size = buffer_size_; |
| 273 desc->instr_size = pc_offset(); |
| 274 desc->reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 275 desc->origin = this; |
| 276 } |
| 277 |
| 278 void Assembler::Align(int m) { |
| 279 DCHECK(m >= 4 && base::bits::IsPowerOfTwo32(m)); |
| 280 while ((pc_offset() & (m - 1)) != 0) { |
| 281 nop(0); |
| 282 } |
| 283 } |
| 284 |
| 285 void Assembler::CodeTargetAlign() { Align(8); } |
| 286 |
| 287 Condition Assembler::GetCondition(Instr instr) { |
| 288 switch (instr & kCondMask) { |
| 289 case BT: |
| 290 return eq; |
| 291 case BF: |
| 292 return ne; |
| 293 default: |
| 294 UNIMPLEMENTED(); |
| 295 } |
| 296 return al; |
| 297 } |
| 298 |
| 299 #if V8_TARGET_ARCH_S390X |
| 300 // This code assumes a FIXED_SEQUENCE for 64bit loads (iihf/iilf) |
| 301 bool Assembler::Is64BitLoadIntoIP(SixByteInstr instr1, SixByteInstr instr2) { |
| 302 // Check the instructions are the iihf/iilf load into ip |
| 303 return (((instr1 >> 32) == 0xC0C8) && ((instr2 >> 32) == 0xC0C9)); |
| 304 } |
| 305 #else |
| 306 // This code assumes a FIXED_SEQUENCE for 32bit loads (iilf) |
| 307 bool Assembler::Is32BitLoadIntoIP(SixByteInstr instr) { |
| 308 // Check the instruction is an iilf load into ip/r12. |
| 309 return ((instr >> 32) == 0xC0C9); |
| 310 } |
| 311 #endif |
| 312 |
| 313 // Labels refer to positions in the (to be) generated code. |
| 314 // There are bound, linked, and unused labels. |
| 315 // |
| 316 // Bound labels refer to known positions in the already |
| 317 // generated code. pos() is the position the label refers to. |
| 318 // |
| 319 // Linked labels refer to unknown positions in the code |
| 320 // to be generated; pos() is the position of the last |
| 321 // instruction using the label. |
| 322 |
| 323 // The link chain is terminated by a negative code position (must be aligned) |
| 324 const int kEndOfChain = -4; |
| 325 |
| 326 // Returns the target address of the relative instructions, typically |
| 327 // of the form: pos + imm (where immediate is in # of halfwords for |
| 328 // BR* and LARL). |
| 329 int Assembler::target_at(int pos) { |
| 330 SixByteInstr instr = instr_at(pos); |
| 331 // check which type of branch this is 16 or 26 bit offset |
| 332 Opcode opcode = Instruction::S390OpcodeValue(buffer_ + pos); |
| 333 |
| 334 if (BRC == opcode || BRCT == opcode || BRCTG == opcode) { |
| 335 int16_t imm16 = SIGN_EXT_IMM16((instr & kImm16Mask)); |
| 336 imm16 <<= 1; // BRC immediate is in # of halfwords |
| 337 if (imm16 == 0) return kEndOfChain; |
| 338 return pos + imm16; |
| 339 } else if (LLILF == opcode || BRCL == opcode || LARL == opcode || |
| 340 BRASL == opcode) { |
| 341 int32_t imm32 = |
| 342 static_cast<int32_t>(instr & (static_cast<uint64_t>(0xffffffff))); |
| 343 if (LLILF != opcode) |
| 344 imm32 <<= 1; // BR* + LARL treat immediate in # of halfwords |
| 345 if (imm32 == 0) return kEndOfChain; |
| 346 return pos + imm32; |
| 347 } |
| 348 |
| 349 // Unknown condition |
| 350 DCHECK(false); |
| 351 return -1; |
| 352 } |
| 353 |
| 354 // Update the target address of the current relative instruction. |
| 355 void Assembler::target_at_put(int pos, int target_pos, bool* is_branch) { |
| 356 SixByteInstr instr = instr_at(pos); |
| 357 Opcode opcode = Instruction::S390OpcodeValue(buffer_ + pos); |
| 358 |
| 359 if (is_branch != nullptr) { |
| 360 *is_branch = (opcode == BRC || opcode == BRCT || opcode == BRCTG || |
| 361 opcode == BRCL || opcode == BRASL); |
| 362 } |
| 363 |
| 364 if (BRC == opcode || BRCT == opcode || BRCTG == opcode) { |
| 365 int16_t imm16 = target_pos - pos; |
| 366 instr &= (~0xffff); |
| 367 CHECK(is_int16(imm16)); |
| 368 instr_at_put<FourByteInstr>(pos, instr | (imm16 >> 1)); |
| 369 return; |
| 370 } else if (BRCL == opcode || LARL == opcode || BRASL == opcode) { |
| 371 // Immediate is in # of halfwords |
| 372 int32_t imm32 = target_pos - pos; |
| 373 instr &= (~static_cast<uint64_t>(0xffffffff)); |
| 374 instr_at_put<SixByteInstr>(pos, instr | (imm32 >> 1)); |
| 375 return; |
| 376 } else if (LLILF == opcode) { |
| 377 CHECK(target_pos == kEndOfChain || target_pos >= 0); |
| 378 // Emitted label constant, not part of a branch. |
| 379 // Make label relative to Code* of generated Code object. |
| 380 int32_t imm32 = target_pos + (Code::kHeaderSize - kHeapObjectTag); |
| 381 instr &= (~static_cast<uint64_t>(0xffffffff)); |
| 382 instr_at_put<SixByteInstr>(pos, instr | imm32); |
| 383 return; |
| 384 } |
| 385 DCHECK(false); |
| 386 } |
| 387 |
| 388 // Returns the maximum number of bits given instruction can address. |
| 389 int Assembler::max_reach_from(int pos) { |
| 390 Opcode opcode = Instruction::S390OpcodeValue(buffer_ + pos); |
| 391 |
| 392 // Check which type of instr. In theory, we can return |
| 393 // the values below + 1, given offset is # of halfwords |
| 394 if (BRC == opcode || BRCT == opcode || BRCTG == opcode) { |
| 395 return 16; |
| 396 } else if (LLILF == opcode || BRCL == opcode || LARL == opcode || |
| 397 BRASL == opcode) { |
| 398 return 31; // Using 31 as workaround instead of 32 as |
| 399 // is_intn(x,32) doesn't work on 32-bit platforms. |
| 400 // llilf: Emitted label constant, not part of |
| 401 // a branch (regexp PushBacktrack). |
| 402 } |
| 403 DCHECK(false); |
| 404 return 16; |
| 405 } |
| 406 |
| 407 void Assembler::bind_to(Label* L, int pos) { |
| 408 DCHECK(0 <= pos && pos <= pc_offset()); // must have a valid binding position |
| 409 bool is_branch = false; |
| 410 while (L->is_linked()) { |
| 411 int fixup_pos = L->pos(); |
| 412 #ifdef DEBUG |
| 413 int32_t offset = pos - fixup_pos; |
| 414 int maxReach = max_reach_from(fixup_pos); |
| 415 #endif |
| 416 next(L); // call next before overwriting link with target at fixup_pos |
| 417 DCHECK(is_intn(offset, maxReach)); |
| 418 target_at_put(fixup_pos, pos, &is_branch); |
| 419 } |
| 420 L->bind_to(pos); |
| 421 |
| 422 // Keep track of the last bound label so we don't eliminate any instructions |
| 423 // before a bound label. |
| 424 if (pos > last_bound_pos_) last_bound_pos_ = pos; |
| 425 } |
| 426 |
| 427 void Assembler::bind(Label* L) { |
| 428 DCHECK(!L->is_bound()); // label can only be bound once |
| 429 bind_to(L, pc_offset()); |
| 430 } |
| 431 |
| 432 void Assembler::next(Label* L) { |
| 433 DCHECK(L->is_linked()); |
| 434 int link = target_at(L->pos()); |
| 435 if (link == kEndOfChain) { |
| 436 L->Unuse(); |
| 437 } else { |
| 438 DCHECK(link >= 0); |
| 439 L->link_to(link); |
| 440 } |
| 441 } |
| 442 |
| 443 bool Assembler::is_near(Label* L, Condition cond) { |
| 444 DCHECK(L->is_bound()); |
| 445 if (L->is_bound() == false) return false; |
| 446 |
| 447 int maxReach = ((cond == al) ? 26 : 16); |
| 448 int offset = L->pos() - pc_offset(); |
| 449 |
| 450 return is_intn(offset, maxReach); |
| 451 } |
| 452 |
| 453 int Assembler::link(Label* L) { |
| 454 int position; |
| 455 if (L->is_bound()) { |
| 456 position = L->pos(); |
| 457 } else { |
| 458 if (L->is_linked()) { |
| 459 position = L->pos(); // L's link |
| 460 } else { |
| 461 // was: target_pos = kEndOfChain; |
| 462 // However, using self to mark the first reference |
| 463 // should avoid most instances of branch offset overflow. See |
| 464 // target_at() for where this is converted back to kEndOfChain. |
| 465 position = pc_offset(); |
| 466 } |
| 467 L->link_to(pc_offset()); |
| 468 } |
| 469 |
| 470 return position; |
| 471 } |
| 472 |
| 473 void Assembler::load_label_offset(Register r1, Label* L) { |
| 474 int target_pos; |
| 475 int constant; |
| 476 if (L->is_bound()) { |
| 477 target_pos = L->pos(); |
| 478 constant = target_pos + (Code::kHeaderSize - kHeapObjectTag); |
| 479 } else { |
| 480 if (L->is_linked()) { |
| 481 target_pos = L->pos(); // L's link |
| 482 } else { |
| 483 // was: target_pos = kEndOfChain; |
| 484 // However, using branch to self to mark the first reference |
| 485 // should avoid most instances of branch offset overflow. See |
| 486 // target_at() for where this is converted back to kEndOfChain. |
| 487 target_pos = pc_offset(); |
| 488 } |
| 489 L->link_to(pc_offset()); |
| 490 |
| 491 constant = target_pos - pc_offset(); |
| 492 } |
| 493 llilf(r1, Operand(constant)); |
| 494 } |
| 495 |
| 496 // Pseudo op - branch on condition |
| 497 void Assembler::branchOnCond(Condition c, int branch_offset, bool is_bound) { |
| 498 int offset = branch_offset; |
| 499 if (is_bound && is_int16(offset)) { |
| 500 brc(c, Operand(offset & 0xFFFF)); // short jump |
| 501 } else { |
| 502 brcl(c, Operand(offset)); // long jump |
| 503 } |
| 504 } |
| 505 |
| 506 // 32-bit Store Multiple - short displacement (12-bits unsigned) |
| 507 void Assembler::stm(Register r1, Register r2, const MemOperand& src) { |
| 508 rs_form(STM, r1, r2, src.rb(), src.offset()); |
| 509 } |
| 510 |
| 511 // 32-bit Store Multiple - long displacement (20-bits signed) |
| 512 void Assembler::stmy(Register r1, Register r2, const MemOperand& src) { |
| 513 rsy_form(STMY, r1, r2, src.rb(), src.offset()); |
| 514 } |
| 515 |
| 516 // 64-bit Store Multiple - long displacement (20-bits signed) |
| 517 void Assembler::stmg(Register r1, Register r2, const MemOperand& src) { |
| 518 rsy_form(STMG, r1, r2, src.rb(), src.offset()); |
| 519 } |
| 520 |
| 521 // Exception-generating instructions and debugging support. |
| 522 // Stops with a non-negative code less than kNumOfWatchedStops support |
| 523 // enabling/disabling and a counter feature. See simulator-s390.h . |
| 524 void Assembler::stop(const char* msg, Condition cond, int32_t code, |
| 525 CRegister cr) { |
| 526 if (cond != al) { |
| 527 Label skip; |
| 528 b(NegateCondition(cond), &skip, Label::kNear); |
| 529 bkpt(0); |
| 530 bind(&skip); |
| 531 } else { |
| 532 bkpt(0); |
| 533 } |
| 534 } |
| 535 |
| 536 void Assembler::bkpt(uint32_t imm16) { |
| 537 // GDB software breakpoint instruction |
| 538 emit2bytes(0x0001); |
| 539 } |
| 540 |
| 541 // Pseudo instructions. |
| 542 void Assembler::nop(int type) { |
| 543 switch (type) { |
| 544 case 0: |
| 545 lr(r0, r0); |
| 546 break; |
| 547 case DEBUG_BREAK_NOP: |
| 548 // TODO(john.yan): Use a better NOP break |
| 549 oill(r3, Operand::Zero()); |
| 550 break; |
| 551 default: |
| 552 UNIMPLEMENTED(); |
| 553 } |
| 554 } |
| 555 |
| 556 // RR format: <insn> R1,R2 |
| 557 // +--------+----+----+ |
| 558 // | OpCode | R1 | R2 | |
| 559 // +--------+----+----+ |
| 560 // 0 8 12 15 |
| 561 #define RR_FORM_EMIT(name, op) \ |
| 562 void Assembler::name(Register r1, Register r2) { rr_form(op, r1, r2); } |
| 563 |
| 564 void Assembler::rr_form(Opcode op, Register r1, Register r2) { |
| 565 DCHECK(is_uint8(op)); |
| 566 emit2bytes(op * B8 | r1.code() * B4 | r2.code()); |
| 567 } |
| 568 |
| 569 void Assembler::rr_form(Opcode op, DoubleRegister r1, DoubleRegister r2) { |
| 570 DCHECK(is_uint8(op)); |
| 571 emit2bytes(op * B8 | r1.code() * B4 | r2.code()); |
| 572 } |
| 573 |
| 574 // RR2 format: <insn> M1,R2 |
| 575 // +--------+----+----+ |
| 576 // | OpCode | M1 | R2 | |
| 577 // +--------+----+----+ |
| 578 // 0 8 12 15 |
| 579 #define RR2_FORM_EMIT(name, op) \ |
| 580 void Assembler::name(Condition m1, Register r2) { rr_form(op, m1, r2); } |
| 581 |
| 582 void Assembler::rr_form(Opcode op, Condition m1, Register r2) { |
| 583 DCHECK(is_uint8(op)); |
| 584 DCHECK(is_uint4(m1)); |
| 585 emit2bytes(op * B8 | m1 * B4 | r2.code()); |
| 586 } |
| 587 |
| 588 // RX format: <insn> R1,D2(X2,B2) |
| 589 // +--------+----+----+----+-------------+ |
| 590 // | OpCode | R1 | X2 | B2 | D2 | |
| 591 // +--------+----+----+----+-------------+ |
| 592 // 0 8 12 16 20 31 |
| 593 #define RX_FORM_EMIT(name, op) \ |
| 594 void Assembler::name(Register r, const MemOperand& opnd) { \ |
| 595 name(r, opnd.getIndexRegister(), opnd.getBaseRegister(), \ |
| 596 opnd.getDisplacement()); \ |
| 597 } \ |
| 598 void Assembler::name(Register r1, Register x2, Register b2, Disp d2) { \ |
| 599 rx_form(op, r1, x2, b2, d2); \ |
| 600 } |
| 601 void Assembler::rx_form(Opcode op, Register r1, Register x2, Register b2, |
| 602 Disp d2) { |
| 603 DCHECK(is_uint8(op)); |
| 604 DCHECK(is_uint12(d2)); |
| 605 emit4bytes(op * B24 | r1.code() * B20 | x2.code() * B16 | b2.code() * B12 | |
| 606 d2); |
| 607 } |
| 608 |
| 609 void Assembler::rx_form(Opcode op, DoubleRegister r1, Register x2, Register b2, |
| 610 Disp d2) { |
| 611 DCHECK(is_uint8(op)); |
| 612 DCHECK(is_uint12(d2)); |
| 613 emit4bytes(op * B24 | r1.code() * B20 | x2.code() * B16 | b2.code() * B12 | |
| 614 d2); |
| 615 } |
| 616 |
| 617 // RI1 format: <insn> R1,I2 |
| 618 // +--------+----+----+------------------+ |
| 619 // | OpCode | R1 |OpCd| I2 | |
| 620 // +--------+----+----+------------------+ |
| 621 // 0 8 12 16 31 |
| 622 #define RI1_FORM_EMIT(name, op) \ |
| 623 void Assembler::name(Register r, const Operand& i2) { ri_form(op, r, i2); } |
| 624 |
| 625 void Assembler::ri_form(Opcode op, Register r1, const Operand& i2) { |
| 626 DCHECK(is_uint12(op)); |
| 627 DCHECK(is_uint16(i2.imm_) || is_int16(i2.imm_)); |
| 628 emit4bytes((op & 0xFF0) * B20 | r1.code() * B20 | (op & 0xF) * B16 | |
| 629 (i2.imm_ & 0xFFFF)); |
| 630 } |
| 631 |
| 632 // RI2 format: <insn> M1,I2 |
| 633 // +--------+----+----+------------------+ |
| 634 // | OpCode | M1 |OpCd| I2 | |
| 635 // +--------+----+----+------------------+ |
| 636 // 0 8 12 16 31 |
| 637 #define RI2_FORM_EMIT(name, op) \ |
| 638 void Assembler::name(Condition m, const Operand& i2) { ri_form(op, m, i2); } |
| 639 |
| 640 void Assembler::ri_form(Opcode op, Condition m1, const Operand& i2) { |
| 641 DCHECK(is_uint12(op)); |
| 642 DCHECK(is_uint4(m1)); |
| 643 DCHECK(is_uint16(i2.imm_)); |
| 644 emit4bytes((op & 0xFF0) * B20 | m1 * B20 | (op & 0xF) * B16 | |
| 645 (i2.imm_ & 0xFFFF)); |
| 646 } |
| 647 |
| 648 // RIE-f format: <insn> R1,R2,I3,I4,I5 |
| 649 // +--------+----+----+------------------+--------+--------+ |
| 650 // | OpCode | R1 | R2 | I3 | I4 | I5 | OpCode | |
| 651 // +--------+----+----+------------------+--------+--------+ |
| 652 // 0 8 12 16 24 32 40 47 |
| 653 void Assembler::rie_f_form(Opcode op, Register r1, Register r2, |
| 654 const Operand& i3, const Operand& i4, |
| 655 const Operand& i5) { |
| 656 DCHECK(is_uint16(op)); |
| 657 DCHECK(is_uint8(i3.imm_)); |
| 658 DCHECK(is_uint8(i4.imm_)); |
| 659 DCHECK(is_uint8(i5.imm_)); |
| 660 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 661 (static_cast<uint64_t>(r1.code())) * B36 | |
| 662 (static_cast<uint64_t>(r2.code())) * B32 | |
| 663 (static_cast<uint64_t>(i3.imm_)) * B24 | |
| 664 (static_cast<uint64_t>(i4.imm_)) * B16 | |
| 665 (static_cast<uint64_t>(i5.imm_)) * B8 | |
| 666 (static_cast<uint64_t>(op & 0x00FF)); |
| 667 emit6bytes(code); |
| 668 } |
| 669 |
| 670 // RIE format: <insn> R1,R3,I2 |
| 671 // +--------+----+----+------------------+--------+--------+ |
| 672 // | OpCode | R1 | R3 | I2 |////////| OpCode | |
| 673 // +--------+----+----+------------------+--------+--------+ |
| 674 // 0 8 12 16 32 40 47 |
| 675 #define RIE_FORM_EMIT(name, op) \ |
| 676 void Assembler::name(Register r1, Register r3, const Operand& i2) { \ |
| 677 rie_form(op, r1, r3, i2); \ |
| 678 } |
| 679 |
| 680 void Assembler::rie_form(Opcode op, Register r1, Register r3, |
| 681 const Operand& i2) { |
| 682 DCHECK(is_uint16(op)); |
| 683 DCHECK(is_int16(i2.imm_)); |
| 684 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 685 (static_cast<uint64_t>(r1.code())) * B36 | |
| 686 (static_cast<uint64_t>(r3.code())) * B32 | |
| 687 (static_cast<uint64_t>(i2.imm_ & 0xFFFF)) * B16 | |
| 688 (static_cast<uint64_t>(op & 0x00FF)); |
| 689 emit6bytes(code); |
| 690 } |
| 691 |
| 692 // RIL1 format: <insn> R1,I2 |
| 693 // +--------+----+----+------------------------------------+ |
| 694 // | OpCode | R1 |OpCd| I2 | |
| 695 // +--------+----+----+------------------------------------+ |
| 696 // 0 8 12 16 47 |
| 697 #define RIL1_FORM_EMIT(name, op) \ |
| 698 void Assembler::name(Register r, const Operand& i2) { ril_form(op, r, i2); } |
| 699 |
| 700 void Assembler::ril_form(Opcode op, Register r1, const Operand& i2) { |
| 701 DCHECK(is_uint12(op)); |
| 702 uint64_t code = (static_cast<uint64_t>(op & 0xFF0)) * B36 | |
| 703 (static_cast<uint64_t>(r1.code())) * B36 | |
| 704 (static_cast<uint64_t>(op & 0x00F)) * B32 | |
| 705 (static_cast<uint64_t>(i2.imm_) & 0xFFFFFFFF); |
| 706 emit6bytes(code); |
| 707 } |
| 708 |
| 709 // RIL2 format: <insn> M1,I2 |
| 710 // +--------+----+----+------------------------------------+ |
| 711 // | OpCode | M1 |OpCd| I2 | |
| 712 // +--------+----+----+------------------------------------+ |
| 713 // 0 8 12 16 47 |
| 714 #define RIL2_FORM_EMIT(name, op) \ |
| 715 void Assembler::name(Condition m1, const Operand& i2) { \ |
| 716 ril_form(op, m1, i2); \ |
| 717 } |
| 718 |
| 719 void Assembler::ril_form(Opcode op, Condition m1, const Operand& i2) { |
| 720 DCHECK(is_uint12(op)); |
| 721 DCHECK(is_uint4(m1)); |
| 722 uint64_t code = (static_cast<uint64_t>(op & 0xFF0)) * B36 | |
| 723 (static_cast<uint64_t>(m1)) * B36 | |
| 724 (static_cast<uint64_t>(op & 0x00F)) * B32 | |
| 725 (static_cast<uint64_t>(i2.imm_ & 0xFFFFFFFF)); |
| 726 emit6bytes(code); |
| 727 } |
| 728 |
| 729 // RRE format: <insn> R1,R2 |
| 730 // +------------------+--------+----+----+ |
| 731 // | OpCode |////////| R1 | R2 | |
| 732 // +------------------+--------+----+----+ |
| 733 // 0 16 24 28 31 |
| 734 #define RRE_FORM_EMIT(name, op) \ |
| 735 void Assembler::name(Register r1, Register r2) { rre_form(op, r1, r2); } |
| 736 |
| 737 void Assembler::rre_form(Opcode op, Register r1, Register r2) { |
| 738 DCHECK(is_uint16(op)); |
| 739 emit4bytes(op << 16 | r1.code() * B4 | r2.code()); |
| 740 } |
| 741 |
| 742 void Assembler::rre_form(Opcode op, DoubleRegister r1, DoubleRegister r2) { |
| 743 DCHECK(is_uint16(op)); |
| 744 emit4bytes(op << 16 | r1.code() * B4 | r2.code()); |
| 745 } |
| 746 |
| 747 // RRD format: <insn> R1,R3, R2 |
| 748 // +------------------+----+----+----+----+ |
| 749 // | OpCode | R1 |////| R3 | R2 | |
| 750 // +------------------+----+----+----+----+ |
| 751 // 0 16 20 24 28 31 |
| 752 #define RRD_FORM_EMIT(name, op) \ |
| 753 void Assembler::name(Register r1, Register r3, Register r2) { \ |
| 754 rrd_form(op, r1, r3, r2); \ |
| 755 } |
| 756 |
| 757 void Assembler::rrd_form(Opcode op, Register r1, Register r3, Register r2) { |
| 758 emit4bytes(op << 16 | r1.code() * B12 | r3.code() * B4 | r2.code()); |
| 759 } |
| 760 |
| 761 // RS1 format: <insn> R1,R3,D2(B2) |
| 762 // +--------+----+----+----+-------------+ |
| 763 // | OpCode | R1 | R3 | B2 | D2 | |
| 764 // +--------+----+----+----+-------------+ |
| 765 // 0 8 12 16 20 31 |
| 766 #define RS1_FORM_EMIT(name, op) \ |
| 767 void Assembler::name(Register r1, Register r3, Register b2, Disp d2) { \ |
| 768 rs_form(op, r1, r3, b2, d2); \ |
| 769 } \ |
| 770 void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \ |
| 771 name(r1, r3, opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 772 } |
| 773 |
| 774 void Assembler::rs_form(Opcode op, Register r1, Register r3, Register b2, |
| 775 const Disp d2) { |
| 776 DCHECK(is_uint12(d2)); |
| 777 emit4bytes(op * B24 | r1.code() * B20 | r3.code() * B16 | b2.code() * B12 | |
| 778 d2); |
| 779 } |
| 780 |
| 781 // RS2 format: <insn> R1,M3,D2(B2) |
| 782 // +--------+----+----+----+-------------+ |
| 783 // | OpCode | R1 | M3 | B2 | D2 | |
| 784 // +--------+----+----+----+-------------+ |
| 785 // 0 8 12 16 20 31 |
| 786 #define RS2_FORM_EMIT(name, op) \ |
| 787 void Assembler::name(Register r1, Condition m3, Register b2, Disp d2) { \ |
| 788 rs_form(op, r1, m3, b2, d2); \ |
| 789 } \ |
| 790 void Assembler::name(Register r1, Condition m3, const MemOperand& opnd) { \ |
| 791 name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 792 } |
| 793 |
| 794 void Assembler::rs_form(Opcode op, Register r1, Condition m3, Register b2, |
| 795 const Disp d2) { |
| 796 DCHECK(is_uint12(d2)); |
| 797 emit4bytes(op * B24 | r1.code() * B20 | m3 * B16 | b2.code() * B12 | d2); |
| 798 } |
| 799 |
| 800 // RSI format: <insn> R1,R3,I2 |
| 801 // +--------+----+----+------------------+ |
| 802 // | OpCode | R1 | R3 | RI2 | |
| 803 // +--------+----+----+------------------+ |
| 804 // 0 8 12 16 31 |
| 805 #define RSI_FORM_EMIT(name, op) \ |
| 806 void Assembler::name(Register r1, Register r3, const Operand& i2) { \ |
| 807 rsi_form(op, r1, r3, i2); \ |
| 808 } |
| 809 |
| 810 void Assembler::rsi_form(Opcode op, Register r1, Register r3, |
| 811 const Operand& i2) { |
| 812 DCHECK(is_uint8(op)); |
| 813 DCHECK(is_uint16(i2.imm_)); |
| 814 emit4bytes(op * B24 | r1.code() * B20 | r3.code() * B16 | (i2.imm_ & 0xFFFF)); |
| 815 } |
| 816 |
| 817 // RSL format: <insn> R1,R3,D2(B2) |
| 818 // +--------+----+----+----+-------------+--------+--------+ |
| 819 // | OpCode | L1 | | B2 | D2 | | OpCode | |
| 820 // +--------+----+----+----+-------------+--------+--------+ |
| 821 // 0 8 12 16 20 32 40 47 |
| 822 #define RSL_FORM_EMIT(name, op) \ |
| 823 void Assembler::name(Length l1, Register b2, Disp d2) { \ |
| 824 rsl_form(op, l1, b2, d2); \ |
| 825 } |
| 826 |
| 827 void Assembler::rsl_form(Opcode op, Length l1, Register b2, Disp d2) { |
| 828 DCHECK(is_uint16(op)); |
| 829 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 830 (static_cast<uint64_t>(l1)) * B36 | |
| 831 (static_cast<uint64_t>(b2.code())) * B28 | |
| 832 (static_cast<uint64_t>(d2)) * B16 | |
| 833 (static_cast<uint64_t>(op & 0x00FF)); |
| 834 emit6bytes(code); |
| 835 } |
| 836 |
| 837 // RSY1 format: <insn> R1,R3,D2(B2) |
| 838 // +--------+----+----+----+-------------+--------+--------+ |
| 839 // | OpCode | R1 | R3 | B2 | DL2 | DH2 | OpCode | |
| 840 // +--------+----+----+----+-------------+--------+--------+ |
| 841 // 0 8 12 16 20 32 40 47 |
| 842 #define RSY1_FORM_EMIT(name, op) \ |
| 843 void Assembler::name(Register r1, Register r3, Register b2, Disp d2) { \ |
| 844 rsy_form(op, r1, r3, b2, d2); \ |
| 845 } \ |
| 846 void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \ |
| 847 name(r1, r3, opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 848 } |
| 849 |
| 850 void Assembler::rsy_form(Opcode op, Register r1, Register r3, Register b2, |
| 851 const Disp d2) { |
| 852 DCHECK(is_int20(d2)); |
| 853 DCHECK(is_uint16(op)); |
| 854 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 855 (static_cast<uint64_t>(r1.code())) * B36 | |
| 856 (static_cast<uint64_t>(r3.code())) * B32 | |
| 857 (static_cast<uint64_t>(b2.code())) * B28 | |
| 858 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | |
| 859 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | |
| 860 (static_cast<uint64_t>(op & 0x00FF)); |
| 861 emit6bytes(code); |
| 862 } |
| 863 |
| 864 // RSY2 format: <insn> R1,M3,D2(B2) |
| 865 // +--------+----+----+----+-------------+--------+--------+ |
| 866 // | OpCode | R1 | M3 | B2 | DL2 | DH2 | OpCode | |
| 867 // +--------+----+----+----+-------------+--------+--------+ |
| 868 // 0 8 12 16 20 32 40 47 |
| 869 #define RSY2_FORM_EMIT(name, op) \ |
| 870 void Assembler::name(Register r1, Condition m3, Register b2, Disp d2) { \ |
| 871 rsy_form(op, r1, m3, b2, d2); \ |
| 872 } \ |
| 873 void Assembler::name(Register r1, Condition m3, const MemOperand& opnd) { \ |
| 874 name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 875 } |
| 876 |
| 877 void Assembler::rsy_form(Opcode op, Register r1, Condition m3, Register b2, |
| 878 const Disp d2) { |
| 879 DCHECK(is_int20(d2)); |
| 880 DCHECK(is_uint16(op)); |
| 881 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 882 (static_cast<uint64_t>(r1.code())) * B36 | |
| 883 (static_cast<uint64_t>(m3)) * B32 | |
| 884 (static_cast<uint64_t>(b2.code())) * B28 | |
| 885 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | |
| 886 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | |
| 887 (static_cast<uint64_t>(op & 0x00FF)); |
| 888 emit6bytes(code); |
| 889 } |
| 890 |
| 891 // RXE format: <insn> R1,D2(X2,B2) |
| 892 // +--------+----+----+----+-------------+--------+--------+ |
| 893 // | OpCode | R1 | X2 | B2 | D2 |////////| OpCode | |
| 894 // +--------+----+----+----+-------------+--------+--------+ |
| 895 // 0 8 12 16 20 32 40 47 |
| 896 #define RXE_FORM_EMIT(name, op) \ |
| 897 void Assembler::name(Register r1, Register x2, Register b2, Disp d2) { \ |
| 898 rxe_form(op, r1, x2, b2, d2); \ |
| 899 } \ |
| 900 void Assembler::name(Register r1, const MemOperand& opnd) { \ |
| 901 name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \ |
| 902 opnd.getDisplacement()); \ |
| 903 } |
| 904 |
| 905 void Assembler::rxe_form(Opcode op, Register r1, Register x2, Register b2, |
| 906 Disp d2) { |
| 907 DCHECK(is_uint12(d2)); |
| 908 DCHECK(is_uint16(op)); |
| 909 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 910 (static_cast<uint64_t>(r1.code())) * B36 | |
| 911 (static_cast<uint64_t>(x2.code())) * B32 | |
| 912 (static_cast<uint64_t>(b2.code())) * B28 | |
| 913 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | |
| 914 (static_cast<uint64_t>(op & 0x00FF)); |
| 915 emit6bytes(code); |
| 916 } |
| 917 |
| 918 // RXY format: <insn> R1,D2(X2,B2) |
| 919 // +--------+----+----+----+-------------+--------+--------+ |
| 920 // | OpCode | R1 | X2 | B2 | DL2 | DH2 | OpCode | |
| 921 // +--------+----+----+----+-------------+--------+--------+ |
| 922 // 0 8 12 16 20 32 36 40 47 |
| 923 #define RXY_FORM_EMIT(name, op) \ |
| 924 void Assembler::name(Register r1, Register x2, Register b2, Disp d2) { \ |
| 925 rxy_form(op, r1, x2, b2, d2); \ |
| 926 } \ |
| 927 void Assembler::name(Register r1, const MemOperand& opnd) { \ |
| 928 name(r1, opnd.getIndexRegister(), opnd.getBaseRegister(), \ |
| 929 opnd.getDisplacement()); \ |
| 930 } |
| 931 |
| 932 void Assembler::rxy_form(Opcode op, Register r1, Register x2, Register b2, |
| 933 Disp d2) { |
| 934 DCHECK(is_int20(d2)); |
| 935 DCHECK(is_uint16(op)); |
| 936 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 937 (static_cast<uint64_t>(r1.code())) * B36 | |
| 938 (static_cast<uint64_t>(x2.code())) * B32 | |
| 939 (static_cast<uint64_t>(b2.code())) * B28 | |
| 940 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | |
| 941 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | |
| 942 (static_cast<uint64_t>(op & 0x00FF)); |
| 943 emit6bytes(code); |
| 944 } |
| 945 |
| 946 void Assembler::rxy_form(Opcode op, DoubleRegister r1, Register x2, Register b2, |
| 947 Disp d2) { |
| 948 DCHECK(is_int20(d2)); |
| 949 DCHECK(is_uint16(op)); |
| 950 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 951 (static_cast<uint64_t>(r1.code())) * B36 | |
| 952 (static_cast<uint64_t>(x2.code())) * B32 | |
| 953 (static_cast<uint64_t>(b2.code())) * B28 | |
| 954 (static_cast<uint64_t>(d2 & 0x0FFF)) * B16 | |
| 955 (static_cast<uint64_t>(d2 & 0x0FF000)) >> 4 | |
| 956 (static_cast<uint64_t>(op & 0x00FF)); |
| 957 emit6bytes(code); |
| 958 } |
| 959 |
| 960 // RRS format: <insn> R1,R2,M3,D4(B4) |
| 961 // +--------+----+----+----+-------------+----+---+--------+ |
| 962 // | OpCode | R1 | R2 | B4 | D4 | M3 |///| OpCode | |
| 963 // +--------+----+----+----+-------------+----+---+--------+ |
| 964 // 0 8 12 16 20 32 36 40 47 |
| 965 #define RRS_FORM_EMIT(name, op) \ |
| 966 void Assembler::name(Register r1, Register r2, Register b4, Disp d4, \ |
| 967 Condition m3) { \ |
| 968 rrs_form(op, r1, r2, b4, d4, m3); \ |
| 969 } \ |
| 970 void Assembler::name(Register r1, Register r2, Condition m3, \ |
| 971 const MemOperand& opnd) { \ |
| 972 name(r1, r2, opnd.getBaseRegister(), opnd.getDisplacement(), m3); \ |
| 973 } |
| 974 |
| 975 void Assembler::rrs_form(Opcode op, Register r1, Register r2, Register b4, |
| 976 Disp d4, Condition m3) { |
| 977 DCHECK(is_uint12(d4)); |
| 978 DCHECK(is_uint16(op)); |
| 979 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 980 (static_cast<uint64_t>(r1.code())) * B36 | |
| 981 (static_cast<uint64_t>(r2.code())) * B32 | |
| 982 (static_cast<uint64_t>(b4.code())) * B28 | |
| 983 (static_cast<uint64_t>(d4)) * B16 | |
| 984 (static_cast<uint64_t>(m3)) << 12 | |
| 985 (static_cast<uint64_t>(op & 0x00FF)); |
| 986 emit6bytes(code); |
| 987 } |
| 988 |
| 989 // RIS format: <insn> R1,I2,M3,D4(B4) |
| 990 // +--------+----+----+----+-------------+--------+--------+ |
| 991 // | OpCode | R1 | M3 | B4 | D4 | I2 | OpCode | |
| 992 // +--------+----+----+----+-------------+--------+--------+ |
| 993 // 0 8 12 16 20 32 40 47 |
| 994 #define RIS_FORM_EMIT(name, op) \ |
| 995 void Assembler::name(Register r1, Condition m3, Register b4, Disp d4, \ |
| 996 const Operand& i2) { \ |
| 997 ris_form(op, r1, m3, b4, d4, i2); \ |
| 998 } \ |
| 999 void Assembler::name(Register r1, const Operand& i2, Condition m3, \ |
| 1000 const MemOperand& opnd) { \ |
| 1001 name(r1, m3, opnd.getBaseRegister(), opnd.getDisplacement(), i2); \ |
| 1002 } |
| 1003 |
| 1004 void Assembler::ris_form(Opcode op, Register r1, Condition m3, Register b4, |
| 1005 Disp d4, const Operand& i2) { |
| 1006 DCHECK(is_uint12(d4)); |
| 1007 DCHECK(is_uint16(op)); |
| 1008 DCHECK(is_uint8(i2.imm_)); |
| 1009 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 1010 (static_cast<uint64_t>(r1.code())) * B36 | |
| 1011 (static_cast<uint64_t>(m3)) * B32 | |
| 1012 (static_cast<uint64_t>(b4.code())) * B28 | |
| 1013 (static_cast<uint64_t>(d4)) * B16 | |
| 1014 (static_cast<uint64_t>(i2.imm_)) << 8 | |
| 1015 (static_cast<uint64_t>(op & 0x00FF)); |
| 1016 emit6bytes(code); |
| 1017 } |
| 1018 |
| 1019 // S format: <insn> D2(B2) |
| 1020 // +------------------+----+-------------+ |
| 1021 // | OpCode | B2 | D2 | |
| 1022 // +------------------+----+-------------+ |
| 1023 // 0 16 20 31 |
| 1024 #define S_FORM_EMIT(name, op) \ |
| 1025 void Assembler::name(Register b1, Disp d2) { s_form(op, b1, d2); } \ |
| 1026 void Assembler::name(const MemOperand& opnd) { \ |
| 1027 name(opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 1028 } |
| 1029 |
| 1030 void Assembler::s_form(Opcode op, Register b1, Disp d2) { |
| 1031 DCHECK(is_uint12(d2)); |
| 1032 emit4bytes(op << 16 | b1.code() * B12 | d2); |
| 1033 } |
| 1034 |
| 1035 // SI format: <insn> D1(B1),I2 |
| 1036 // +--------+---------+----+-------------+ |
| 1037 // | OpCode | I2 | B1 | D1 | |
| 1038 // +--------+---------+----+-------------+ |
| 1039 // 0 8 16 20 31 |
| 1040 #define SI_FORM_EMIT(name, op) \ |
| 1041 void Assembler::name(const Operand& i2, Register b1, Disp d1) { \ |
| 1042 si_form(op, i2, b1, d1); \ |
| 1043 } \ |
| 1044 void Assembler::name(const MemOperand& opnd, const Operand& i2) { \ |
| 1045 name(i2, opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 1046 } |
| 1047 |
| 1048 void Assembler::si_form(Opcode op, const Operand& i2, Register b1, Disp d1) { |
| 1049 emit4bytes((op & 0x00FF) << 24 | i2.imm_ * B16 | b1.code() * B12 | d1); |
| 1050 } |
| 1051 |
| 1052 // SIY format: <insn> D1(B1),I2 |
| 1053 // +--------+---------+----+-------------+--------+--------+ |
| 1054 // | OpCode | I2 | B1 | DL1 | DH1 | OpCode | |
| 1055 // +--------+---------+----+-------------+--------+--------+ |
| 1056 // 0 8 16 20 32 36 40 47 |
| 1057 #define SIY_FORM_EMIT(name, op) \ |
| 1058 void Assembler::name(const Operand& i2, Register b1, Disp d1) { \ |
| 1059 siy_form(op, i2, b1, d1); \ |
| 1060 } \ |
| 1061 void Assembler::name(const MemOperand& opnd, const Operand& i2) { \ |
| 1062 name(i2, opnd.getBaseRegister(), opnd.getDisplacement()); \ |
| 1063 } |
| 1064 |
| 1065 void Assembler::siy_form(Opcode op, const Operand& i2, Register b1, Disp d1) { |
| 1066 DCHECK(is_uint20(d1)); |
| 1067 DCHECK(is_uint16(op)); |
| 1068 DCHECK(is_uint8(i2.imm_)); |
| 1069 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 1070 (static_cast<uint64_t>(i2.imm_)) * B32 | |
| 1071 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1072 (static_cast<uint64_t>(d1 & 0x0FFF)) * B16 | |
| 1073 (static_cast<uint64_t>(d1 & 0x0FF000)) >> 4 | |
| 1074 (static_cast<uint64_t>(op & 0x00FF)); |
| 1075 emit6bytes(code); |
| 1076 } |
| 1077 |
| 1078 // SIL format: <insn> D1(B1),I2 |
| 1079 // +------------------+----+-------------+-----------------+ |
| 1080 // | OpCode | B1 | D1 | I2 | |
| 1081 // +------------------+----+-------------+-----------------+ |
| 1082 // 0 16 20 32 47 |
| 1083 #define SIL_FORM_EMIT(name, op) \ |
| 1084 void Assembler::name(Register b1, Disp d1, const Operand& i2) { \ |
| 1085 sil_form(op, b1, d1, i2); \ |
| 1086 } \ |
| 1087 void Assembler::name(const MemOperand& opnd, const Operand& i2) { \ |
| 1088 name(opnd.getBaseRegister(), opnd.getDisplacement(), i2); \ |
| 1089 } |
| 1090 |
| 1091 void Assembler::sil_form(Opcode op, Register b1, Disp d1, const Operand& i2) { |
| 1092 DCHECK(is_uint12(d1)); |
| 1093 DCHECK(is_uint16(op)); |
| 1094 DCHECK(is_uint16(i2.imm_)); |
| 1095 uint64_t code = (static_cast<uint64_t>(op)) * B32 | |
| 1096 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1097 (static_cast<uint64_t>(d1)) * B16 | |
| 1098 (static_cast<uint64_t>(i2.imm_)); |
| 1099 emit6bytes(code); |
| 1100 } |
| 1101 |
| 1102 // RXF format: <insn> R1,R3,D2(X2,B2) |
| 1103 // +--------+----+----+----+-------------+----+---+--------+ |
| 1104 // | OpCode | R3 | X2 | B2 | D2 | R1 |///| OpCode | |
| 1105 // +--------+----+----+----+-------------+----+---+--------+ |
| 1106 // 0 8 12 16 20 32 36 40 47 |
| 1107 #define RXF_FORM_EMIT(name, op) \ |
| 1108 void Assembler::name(Register r1, Register r3, Register b2, Register x2, \ |
| 1109 Disp d2) { \ |
| 1110 rxf_form(op, r1, r3, b2, x2, d2); \ |
| 1111 } \ |
| 1112 void Assembler::name(Register r1, Register r3, const MemOperand& opnd) { \ |
| 1113 name(r1, r3, opnd.getBaseRegister(), opnd.getIndexRegister(), \ |
| 1114 opnd.getDisplacement()); \ |
| 1115 } |
| 1116 |
| 1117 void Assembler::rxf_form(Opcode op, Register r1, Register r3, Register b2, |
| 1118 Register x2, Disp d2) { |
| 1119 DCHECK(is_uint12(d2)); |
| 1120 DCHECK(is_uint16(op)); |
| 1121 uint64_t code = (static_cast<uint64_t>(op & 0xFF00)) * B32 | |
| 1122 (static_cast<uint64_t>(r3.code())) * B36 | |
| 1123 (static_cast<uint64_t>(x2.code())) * B32 | |
| 1124 (static_cast<uint64_t>(b2.code())) * B28 | |
| 1125 (static_cast<uint64_t>(d2)) * B16 | |
| 1126 (static_cast<uint64_t>(r1.code())) * B12 | |
| 1127 (static_cast<uint64_t>(op & 0x00FF)); |
| 1128 emit6bytes(code); |
| 1129 } |
| 1130 |
| 1131 // SS1 format: <insn> D1(L,B1),D2(B3) |
| 1132 // +--------+----+----+----+-------------+----+------------+ |
| 1133 // | OpCode | L | B1 | D1 | B2 | D2 | |
| 1134 // +--------+----+----+----+-------------+----+------------+ |
| 1135 // 0 8 12 16 20 32 36 47 |
| 1136 #define SS1_FORM_EMIT(name, op) \ |
| 1137 void Assembler::name(Register b1, Disp d1, Register b2, Disp d2, Length l) { \ |
| 1138 ss_form(op, l, b1, d1, b2, d2); \ |
| 1139 } \ |
| 1140 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \ |
| 1141 Length length) { \ |
| 1142 name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \ |
| 1143 opnd2.getBaseRegister(), opnd2.getDisplacement(), length); \ |
| 1144 } |
| 1145 |
| 1146 void Assembler::ss_form(Opcode op, Length l, Register b1, Disp d1, Register b2, |
| 1147 Disp d2) { |
| 1148 DCHECK(is_uint12(d2)); |
| 1149 DCHECK(is_uint12(d1)); |
| 1150 DCHECK(is_uint8(op)); |
| 1151 DCHECK(is_uint8(l)); |
| 1152 uint64_t code = |
| 1153 (static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l)) * B32 | |
| 1154 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1155 (static_cast<uint64_t>(d1)) * B16 | |
| 1156 (static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2)); |
| 1157 emit6bytes(code); |
| 1158 } |
| 1159 |
| 1160 // SS2 format: <insn> D1(L1,B1), D2(L3,B3) |
| 1161 // +--------+----+----+----+-------------+----+------------+ |
| 1162 // | OpCode | L1 | L2 | B1 | D1 | B2 | D2 | |
| 1163 // +--------+----+----+----+-------------+----+------------+ |
| 1164 // 0 8 12 16 20 32 36 47 |
| 1165 #define SS2_FORM_EMIT(name, op) \ |
| 1166 void Assembler::name(Register b1, Disp d1, Register b2, Disp d2, Length l1, \ |
| 1167 Length l2) { \ |
| 1168 ss_form(op, l1, l2, b1, d1, b2, d2); \ |
| 1169 } \ |
| 1170 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \ |
| 1171 Length length1, Length length2) { \ |
| 1172 name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \ |
| 1173 opnd2.getBaseRegister(), opnd2.getDisplacement(), length1, length2); \ |
| 1174 } |
| 1175 |
| 1176 void Assembler::ss_form(Opcode op, Length l1, Length l2, Register b1, Disp d1, |
| 1177 Register b2, Disp d2) { |
| 1178 DCHECK(is_uint12(d2)); |
| 1179 DCHECK(is_uint12(d1)); |
| 1180 DCHECK(is_uint8(op)); |
| 1181 DCHECK(is_uint4(l2)); |
| 1182 DCHECK(is_uint4(l1)); |
| 1183 uint64_t code = |
| 1184 (static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l1)) * B36 | |
| 1185 (static_cast<uint64_t>(l2)) * B32 | |
| 1186 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1187 (static_cast<uint64_t>(d1)) * B16 | |
| 1188 (static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2)); |
| 1189 emit6bytes(code); |
| 1190 } |
| 1191 |
| 1192 // SS3 format: <insn> D1(L1,B1), D2(I3,B2) |
| 1193 // +--------+----+----+----+-------------+----+------------+ |
| 1194 // | OpCode | L1 | I3 | B1 | D1 | B2 | D2 | |
| 1195 // +--------+----+----+----+-------------+----+------------+ |
| 1196 // 0 8 12 16 20 32 36 47 |
| 1197 #define SS3_FORM_EMIT(name, op) \ |
| 1198 void Assembler::name(const Operand& i3, Register b1, Disp d1, Register b2, \ |
| 1199 Disp d2, Length l1) { \ |
| 1200 ss_form(op, l1, i3, b1, d1, b2, d2); \ |
| 1201 } \ |
| 1202 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2, \ |
| 1203 Length length) { \ |
| 1204 DCHECK(false); \ |
| 1205 } |
| 1206 void Assembler::ss_form(Opcode op, Length l1, const Operand& i3, Register b1, |
| 1207 Disp d1, Register b2, Disp d2) { |
| 1208 DCHECK(is_uint12(d2)); |
| 1209 DCHECK(is_uint12(d1)); |
| 1210 DCHECK(is_uint8(op)); |
| 1211 DCHECK(is_uint4(l1)); |
| 1212 DCHECK(is_uint4(i3.imm_)); |
| 1213 uint64_t code = |
| 1214 (static_cast<uint64_t>(op)) * B40 | (static_cast<uint64_t>(l1)) * B36 | |
| 1215 (static_cast<uint64_t>(i3.imm_)) * B32 | |
| 1216 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1217 (static_cast<uint64_t>(d1)) * B16 | |
| 1218 (static_cast<uint64_t>(b2.code())) * B12 | (static_cast<uint64_t>(d2)); |
| 1219 emit6bytes(code); |
| 1220 } |
| 1221 |
| 1222 // SS4 format: <insn> D1(R1,B1), D2(R3,B2) |
| 1223 // +--------+----+----+----+-------------+----+------------+ |
| 1224 // | OpCode | R1 | R3 | B1 | D1 | B2 | D2 | |
| 1225 // +--------+----+----+----+-------------+----+------------+ |
| 1226 // 0 8 12 16 20 32 36 47 |
| 1227 #define SS4_FORM_EMIT(name, op) \ |
| 1228 void Assembler::name(Register r1, Register r3, Register b1, Disp d1, \ |
| 1229 Register b2, Disp d2) { \ |
| 1230 ss_form(op, r1, r3, b1, d1, b2, d2); \ |
| 1231 } \ |
| 1232 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \ |
| 1233 DCHECK(false); \ |
| 1234 } |
| 1235 void Assembler::ss_form(Opcode op, Register r1, Register r3, Register b1, |
| 1236 Disp d1, Register b2, Disp d2) { |
| 1237 DCHECK(is_uint12(d2)); |
| 1238 DCHECK(is_uint12(d1)); |
| 1239 DCHECK(is_uint8(op)); |
| 1240 uint64_t code = (static_cast<uint64_t>(op)) * B40 | |
| 1241 (static_cast<uint64_t>(r1.code())) * B36 | |
| 1242 (static_cast<uint64_t>(r3.code())) * B32 | |
| 1243 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1244 (static_cast<uint64_t>(d1)) * B16 | |
| 1245 (static_cast<uint64_t>(b2.code())) * B12 | |
| 1246 (static_cast<uint64_t>(d2)); |
| 1247 emit6bytes(code); |
| 1248 } |
| 1249 |
| 1250 // SS5 format: <insn> D1(R1,B1), D2(R3,B2) |
| 1251 // +--------+----+----+----+-------------+----+------------+ |
| 1252 // | OpCode | R1 | R3 | B2 | D2 | B4 | D4 | |
| 1253 // +--------+----+----+----+-------------+----+------------+ |
| 1254 // 0 8 12 16 20 32 36 47 |
| 1255 #define SS5_FORM_EMIT(name, op) \ |
| 1256 void Assembler::name(Register r1, Register r3, Register b2, Disp d2, \ |
| 1257 Register b4, Disp d4) { \ |
| 1258 ss_form(op, r1, r3, b2, d2, b4, d4); /*SS5 use the same form as SS4*/ \ |
| 1259 } \ |
| 1260 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \ |
| 1261 DCHECK(false); \ |
| 1262 } |
| 1263 |
| 1264 #define SS6_FORM_EMIT(name, op) SS1_FORM_EMIT(name, op) |
| 1265 |
| 1266 // SSE format: <insn> D1(B1),D2(B2) |
| 1267 // +------------------+----+-------------+----+------------+ |
| 1268 // | OpCode | B1 | D1 | B2 | D2 | |
| 1269 // +------------------+----+-------------+----+------------+ |
| 1270 // 0 8 12 16 20 32 36 47 |
| 1271 #define SSE_FORM_EMIT(name, op) \ |
| 1272 void Assembler::name(Register b1, Disp d1, Register b2, Disp d2) { \ |
| 1273 sse_form(op, b1, d1, b2, d2); \ |
| 1274 } \ |
| 1275 void Assembler::name(const MemOperand& opnd1, const MemOperand& opnd2) { \ |
| 1276 name(opnd1.getBaseRegister(), opnd1.getDisplacement(), \ |
| 1277 opnd2.getBaseRegister(), opnd2.getDisplacement()); \ |
| 1278 } |
| 1279 void Assembler::sse_form(Opcode op, Register b1, Disp d1, Register b2, |
| 1280 Disp d2) { |
| 1281 DCHECK(is_uint12(d2)); |
| 1282 DCHECK(is_uint12(d1)); |
| 1283 DCHECK(is_uint16(op)); |
| 1284 uint64_t code = (static_cast<uint64_t>(op)) * B32 | |
| 1285 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1286 (static_cast<uint64_t>(d1)) * B16 | |
| 1287 (static_cast<uint64_t>(b2.code())) * B12 | |
| 1288 (static_cast<uint64_t>(d2)); |
| 1289 emit6bytes(code); |
| 1290 } |
| 1291 |
| 1292 // SSF format: <insn> R3, D1(B1),D2(B2),R3 |
| 1293 // +--------+----+----+----+-------------+----+------------+ |
| 1294 // | OpCode | R3 |OpCd| B1 | D1 | B2 | D2 | |
| 1295 // +--------+----+----+----+-------------+----+------------+ |
| 1296 // 0 8 12 16 20 32 36 47 |
| 1297 #define SSF_FORM_EMIT(name, op) \ |
| 1298 void Assembler::name(Register r3, Register b1, Disp d1, Register b2, \ |
| 1299 Disp d2) { \ |
| 1300 ssf_form(op, r3, b1, d1, b2, d2); \ |
| 1301 } \ |
| 1302 void Assembler::name(Register r3, const MemOperand& opnd1, \ |
| 1303 const MemOperand& opnd2) { \ |
| 1304 name(r3, opnd1.getBaseRegister(), opnd1.getDisplacement(), \ |
| 1305 opnd2.getBaseRegister(), opnd2.getDisplacement()); \ |
| 1306 } |
| 1307 |
| 1308 void Assembler::ssf_form(Opcode op, Register r3, Register b1, Disp d1, |
| 1309 Register b2, Disp d2) { |
| 1310 DCHECK(is_uint12(d2)); |
| 1311 DCHECK(is_uint12(d1)); |
| 1312 DCHECK(is_uint12(op)); |
| 1313 uint64_t code = (static_cast<uint64_t>(op & 0xFF0)) * B36 | |
| 1314 (static_cast<uint64_t>(r3.code())) * B36 | |
| 1315 (static_cast<uint64_t>(op & 0x00F)) * B32 | |
| 1316 (static_cast<uint64_t>(b1.code())) * B28 | |
| 1317 (static_cast<uint64_t>(d1)) * B16 | |
| 1318 (static_cast<uint64_t>(b2.code())) * B12 | |
| 1319 (static_cast<uint64_t>(d2)); |
| 1320 emit6bytes(code); |
| 1321 } |
| 1322 |
| 1323 // RRF1 format: <insn> R1,R2,R3 |
| 1324 // +------------------+----+----+----+----+ |
| 1325 // | OpCode | R3 | | R1 | R2 | |
| 1326 // +------------------+----+----+----+----+ |
| 1327 // 0 16 20 24 28 31 |
| 1328 #define RRF1_FORM_EMIT(name, op) \ |
| 1329 void Assembler::name(Register r1, Register r2, Register r3) { \ |
| 1330 rrf1_form(op << 16 | r3.code() * B12 | r1.code() * B4 | r2.code()); \ |
| 1331 } |
| 1332 |
| 1333 void Assembler::rrf1_form(Opcode op, Register r1, Register r2, Register r3) { |
| 1334 uint32_t code = op << 16 | r3.code() * B12 | r1.code() * B4 | r2.code(); |
| 1335 emit4bytes(code); |
| 1336 } |
| 1337 |
| 1338 void Assembler::rrf1_form(uint32_t code) { emit4bytes(code); } |
| 1339 |
| 1340 // RRF2 format: <insn> R1,R2,M3 |
| 1341 // +------------------+----+----+----+----+ |
| 1342 // | OpCode | M3 | | R1 | R2 | |
| 1343 // +------------------+----+----+----+----+ |
| 1344 // 0 16 20 24 28 31 |
| 1345 #define RRF2_FORM_EMIT(name, op) \ |
| 1346 void Assembler::name(Condition m3, Register r1, Register r2) { \ |
| 1347 rrf2_form(op << 16 | m3 * B12 | r1.code() * B4 | r2.code()); \ |
| 1348 } |
| 1349 |
| 1350 void Assembler::rrf2_form(uint32_t code) { emit4bytes(code); } |
| 1351 |
| 1352 // RRF3 format: <insn> R1,R2,R3,M4 |
| 1353 // +------------------+----+----+----+----+ |
| 1354 // | OpCode | R3 | M4 | R1 | R2 | |
| 1355 // +------------------+----+----+----+----+ |
| 1356 // 0 16 20 24 28 31 |
| 1357 #define RRF3_FORM_EMIT(name, op) \ |
| 1358 void Assembler::name(Register r3, Conition m4, Register r1, Register r2) { \ |
| 1359 rrf3_form(op << 16 | r3.code() * B12 | m4 * B8 | r1.code() * B4 | \ |
| 1360 r2.code()); \ |
| 1361 } |
| 1362 |
| 1363 void Assembler::rrf3_form(uint32_t code) { emit4bytes(code); } |
| 1364 |
| 1365 // RRF-e format: <insn> R1,M3,R2,M4 |
| 1366 // +------------------+----+----+----+----+ |
| 1367 // | OpCode | M3 | M4 | R1 | R2 | |
| 1368 // +------------------+----+----+----+----+ |
| 1369 // 0 16 20 24 28 31 |
| 1370 void Assembler::rrfe_form(Opcode op, Condition m3, Condition m4, Register r1, |
| 1371 Register r2) { |
| 1372 uint32_t code = op << 16 | m3 * B12 | m4 * B8 | r1.code() * B4 | r2.code(); |
| 1373 emit4bytes(code); |
| 1374 } |
| 1375 |
| 1376 // end of S390 Instruction generation |
| 1377 |
| 1378 // start of S390 instruction |
| 1379 RX_FORM_EMIT(bc, BC) |
| 1380 RR_FORM_EMIT(bctr, BCTR) |
| 1381 RXE_FORM_EMIT(ceb, CEB) |
| 1382 RRE_FORM_EMIT(cefbr, CEFBR) |
| 1383 SS1_FORM_EMIT(ed, ED) |
| 1384 RX_FORM_EMIT(ex, EX) |
| 1385 RRE_FORM_EMIT(flogr, FLOGR) |
| 1386 RRE_FORM_EMIT(lcgr, LCGR) |
| 1387 RR_FORM_EMIT(lcr, LCR) |
| 1388 RX_FORM_EMIT(le_z, LE) |
| 1389 RXY_FORM_EMIT(ley, LEY) |
| 1390 RIL1_FORM_EMIT(llihf, LLIHF) |
| 1391 RIL1_FORM_EMIT(llilf, LLILF) |
| 1392 RRE_FORM_EMIT(lngr, LNGR) |
| 1393 RR_FORM_EMIT(lnr, LNR) |
| 1394 RSY1_FORM_EMIT(loc, LOC) |
| 1395 RXY_FORM_EMIT(lrv, LRV) |
| 1396 RXY_FORM_EMIT(lrvh, LRVH) |
| 1397 SS1_FORM_EMIT(mvn, MVN) |
| 1398 SS1_FORM_EMIT(nc, NC) |
| 1399 SI_FORM_EMIT(ni, NI) |
| 1400 RIL1_FORM_EMIT(nihf, NIHF) |
| 1401 RIL1_FORM_EMIT(nilf, NILF) |
| 1402 RI1_FORM_EMIT(nilh, NILH) |
| 1403 RI1_FORM_EMIT(nill, NILL) |
| 1404 RIL1_FORM_EMIT(oihf, OIHF) |
| 1405 RIL1_FORM_EMIT(oilf, OILF) |
| 1406 RI1_FORM_EMIT(oill, OILL) |
| 1407 RRE_FORM_EMIT(popcnt, POPCNT_Z) |
| 1408 RIL1_FORM_EMIT(slfi, SLFI) |
| 1409 RXY_FORM_EMIT(slgf, SLGF) |
| 1410 RIL1_FORM_EMIT(slgfi, SLGFI) |
| 1411 RXY_FORM_EMIT(strv, STRV) |
| 1412 RI1_FORM_EMIT(tmll, TMLL) |
| 1413 SS1_FORM_EMIT(tr, TR) |
| 1414 S_FORM_EMIT(ts, TS) |
| 1415 RIL1_FORM_EMIT(xihf, XIHF) |
| 1416 RIL1_FORM_EMIT(xilf, XILF) |
| 1417 |
| 1418 // ------------------------- |
| 1419 // Load Address Instructions |
| 1420 // ------------------------- |
| 1421 // Load Address Register-Storage |
| 1422 void Assembler::la(Register r1, const MemOperand& opnd) { |
| 1423 rx_form(LA, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1424 } |
| 1425 |
| 1426 // Load Address Register-Storage |
| 1427 void Assembler::lay(Register r1, const MemOperand& opnd) { |
| 1428 rxy_form(LAY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1429 } |
| 1430 |
| 1431 // Load Address Relative Long |
| 1432 void Assembler::larl(Register r1, const Operand& opnd) { |
| 1433 ril_form(LARL, r1, opnd); |
| 1434 } |
| 1435 |
| 1436 // Load Address Relative Long |
| 1437 void Assembler::larl(Register r1, Label* l) { |
| 1438 larl(r1, Operand(branch_offset(l))); |
| 1439 } |
| 1440 |
| 1441 // ----------------- |
| 1442 // Load Instructions |
| 1443 // ----------------- |
| 1444 // Load Byte Register-Storage (32<-8) |
| 1445 void Assembler::lb(Register r, const MemOperand& src) { |
| 1446 rxy_form(LB, r, src.rx(), src.rb(), src.offset()); |
| 1447 } |
| 1448 |
| 1449 // Load Byte Register-Register (32<-8) |
| 1450 void Assembler::lbr(Register r1, Register r2) { rre_form(LBR, r1, r2); } |
| 1451 |
| 1452 // Load Byte Register-Storage (64<-8) |
| 1453 void Assembler::lgb(Register r, const MemOperand& src) { |
| 1454 rxy_form(LGB, r, src.rx(), src.rb(), src.offset()); |
| 1455 } |
| 1456 |
| 1457 // Load Byte Register-Register (64<-8) |
| 1458 void Assembler::lgbr(Register r1, Register r2) { rre_form(LGBR, r1, r2); } |
| 1459 |
| 1460 // Load Halfword Register-Storage (32<-16) |
| 1461 void Assembler::lh(Register r, const MemOperand& src) { |
| 1462 rx_form(LH, r, src.rx(), src.rb(), src.offset()); |
| 1463 } |
| 1464 |
| 1465 // Load Halfword Register-Storage (32<-16) |
| 1466 void Assembler::lhy(Register r, const MemOperand& src) { |
| 1467 rxy_form(LHY, r, src.rx(), src.rb(), src.offset()); |
| 1468 } |
| 1469 |
| 1470 // Load Halfword Register-Register (32<-16) |
| 1471 void Assembler::lhr(Register r1, Register r2) { rre_form(LHR, r1, r2); } |
| 1472 |
| 1473 // Load Halfword Register-Storage (64<-16) |
| 1474 void Assembler::lgh(Register r, const MemOperand& src) { |
| 1475 rxy_form(LGH, r, src.rx(), src.rb(), src.offset()); |
| 1476 } |
| 1477 |
| 1478 // Load Halfword Register-Register (64<-16) |
| 1479 void Assembler::lghr(Register r1, Register r2) { rre_form(LGHR, r1, r2); } |
| 1480 |
| 1481 // Load Register-Storage (32) |
| 1482 void Assembler::l(Register r, const MemOperand& src) { |
| 1483 rx_form(L, r, src.rx(), src.rb(), src.offset()); |
| 1484 } |
| 1485 |
| 1486 // Load Register-Storage (32) |
| 1487 void Assembler::ly(Register r, const MemOperand& src) { |
| 1488 rxy_form(LY, r, src.rx(), src.rb(), src.offset()); |
| 1489 } |
| 1490 |
| 1491 // Load Register-Register (32) |
| 1492 void Assembler::lr(Register r1, Register r2) { rr_form(LR, r1, r2); } |
| 1493 |
| 1494 // Load Register-Storage (64) |
| 1495 void Assembler::lg(Register r, const MemOperand& src) { |
| 1496 rxy_form(LG, r, src.rx(), src.rb(), src.offset()); |
| 1497 } |
| 1498 |
| 1499 // Load Register-Register (64) |
| 1500 void Assembler::lgr(Register r1, Register r2) { rre_form(LGR, r1, r2); } |
| 1501 |
| 1502 // Load Register-Storage (64<-32) |
| 1503 void Assembler::lgf(Register r, const MemOperand& src) { |
| 1504 rxy_form(LGF, r, src.rx(), src.rb(), src.offset()); |
| 1505 } |
| 1506 |
| 1507 // Load Sign Extended Register-Register (64<-32) |
| 1508 void Assembler::lgfr(Register r1, Register r2) { rre_form(LGFR, r1, r2); } |
| 1509 |
| 1510 // Load Halfword Immediate (32) |
| 1511 void Assembler::lhi(Register r, const Operand& imm) { ri_form(LHI, r, imm); } |
| 1512 |
| 1513 // Load Halfword Immediate (64) |
| 1514 void Assembler::lghi(Register r, const Operand& imm) { ri_form(LGHI, r, imm); } |
| 1515 |
| 1516 // -------------------------- |
| 1517 // Load And Test Instructions |
| 1518 // -------------------------- |
| 1519 // Load and Test Register-Storage (32) |
| 1520 void Assembler::lt_z(Register r1, const MemOperand& opnd) { |
| 1521 rxy_form(LT, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1522 } |
| 1523 |
| 1524 // Load and Test Register-Storage (64) |
| 1525 void Assembler::ltg(Register r1, const MemOperand& opnd) { |
| 1526 rxy_form(LTG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1527 } |
| 1528 |
| 1529 // Load and Test Register-Register (32) |
| 1530 void Assembler::ltr(Register r1, Register r2) { rr_form(LTR, r1, r2); } |
| 1531 |
| 1532 // Load and Test Register-Register (64) |
| 1533 void Assembler::ltgr(Register r1, Register r2) { rre_form(LTGR, r1, r2); } |
| 1534 |
| 1535 // Load and Test Register-Register (64<-32) |
| 1536 void Assembler::ltgfr(Register r1, Register r2) { rre_form(LTGFR, r1, r2); } |
| 1537 |
| 1538 // ------------------------- |
| 1539 // Load Logical Instructions |
| 1540 // ------------------------- |
| 1541 // Load Logical Character (32) - loads a byte and zero ext. |
| 1542 void Assembler::llc(Register r1, const MemOperand& opnd) { |
| 1543 rxy_form(LLC, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1544 } |
| 1545 |
| 1546 // Load Logical Character (64) - loads a byte and zero ext. |
| 1547 void Assembler::llgc(Register r1, const MemOperand& opnd) { |
| 1548 rxy_form(LLGC, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1549 } |
| 1550 |
| 1551 // Load Logical halfword Register-Storage (64<-32) |
| 1552 void Assembler::llgf(Register r1, const MemOperand& opnd) { |
| 1553 rxy_form(LLGF, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1554 } |
| 1555 |
| 1556 // Load Logical Register-Register (64<-32) |
| 1557 void Assembler::llgfr(Register r1, Register r2) { rre_form(LLGFR, r1, r2); } |
| 1558 |
| 1559 // Load Logical halfword Register-Storage (32) |
| 1560 void Assembler::llh(Register r1, const MemOperand& opnd) { |
| 1561 rxy_form(LLH, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1562 } |
| 1563 |
| 1564 // Load Logical halfword Register-Storage (64) |
| 1565 void Assembler::llgh(Register r1, const MemOperand& opnd) { |
| 1566 rxy_form(LLGH, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1567 } |
| 1568 |
| 1569 // Load Logical halfword Register-Register (32) |
| 1570 void Assembler::llhr(Register r1, Register r2) { rre_form(LLHR, r1, r2); } |
| 1571 |
| 1572 // Load Logical halfword Register-Register (64) |
| 1573 void Assembler::llghr(Register r1, Register r2) { rre_form(LLGHR, r1, r2); } |
| 1574 |
| 1575 // ------------------- |
| 1576 // Branch Instructions |
| 1577 // ------------------- |
| 1578 // Branch and Save |
| 1579 void Assembler::basr(Register r1, Register r2) { rr_form(BASR, r1, r2); } |
| 1580 |
| 1581 // Indirect Conditional Branch via register |
| 1582 void Assembler::bcr(Condition m, Register target) { rr_form(BCR, m, target); } |
| 1583 |
| 1584 // Branch on Count (32) |
| 1585 void Assembler::bct(Register r, const MemOperand& opnd) { |
| 1586 rx_form(BCT, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1587 } |
| 1588 |
| 1589 // Branch on Count (64) |
| 1590 void Assembler::bctg(Register r, const MemOperand& opnd) { |
| 1591 rxy_form(BCTG, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1592 } |
| 1593 |
| 1594 // Branch Relative and Save (32) |
| 1595 void Assembler::bras(Register r, const Operand& opnd) { |
| 1596 ri_form(BRAS, r, opnd); |
| 1597 } |
| 1598 |
| 1599 // Branch Relative and Save (64) |
| 1600 void Assembler::brasl(Register r, const Operand& opnd) { |
| 1601 ril_form(BRASL, r, opnd); |
| 1602 } |
| 1603 |
| 1604 // Branch relative on Condition (32) |
| 1605 void Assembler::brc(Condition c, const Operand& opnd) { |
| 1606 // BRC actually encodes # of halfwords, so divide by 2. |
| 1607 int16_t numHalfwords = static_cast<int16_t>(opnd.immediate()) / 2; |
| 1608 Operand halfwordOp = Operand(numHalfwords); |
| 1609 halfwordOp.setBits(16); |
| 1610 ri_form(BRC, c, halfwordOp); |
| 1611 } |
| 1612 |
| 1613 // Branch Relative on Condition (64) |
| 1614 void Assembler::brcl(Condition c, const Operand& opnd, bool isCodeTarget) { |
| 1615 Operand halfwordOp = opnd; |
| 1616 // Operand for code targets will be index to code_targets_ |
| 1617 if (!isCodeTarget) { |
| 1618 // BRCL actually encodes # of halfwords, so divide by 2. |
| 1619 int32_t numHalfwords = static_cast<int32_t>(opnd.immediate()) / 2; |
| 1620 halfwordOp = Operand(numHalfwords); |
| 1621 } |
| 1622 ril_form(BRCL, c, halfwordOp); |
| 1623 } |
| 1624 |
| 1625 // Branch On Count (32) |
| 1626 void Assembler::brct(Register r1, const Operand& imm) { |
| 1627 // BRCT encodes # of halfwords, so divide by 2. |
| 1628 int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; |
| 1629 Operand halfwordOp = Operand(numHalfwords); |
| 1630 halfwordOp.setBits(16); |
| 1631 ri_form(BRCT, r1, halfwordOp); |
| 1632 } |
| 1633 |
| 1634 // Branch On Count (32) |
| 1635 void Assembler::brctg(Register r1, const Operand& imm) { |
| 1636 // BRCTG encodes # of halfwords, so divide by 2. |
| 1637 int16_t numHalfwords = static_cast<int16_t>(imm.immediate()) / 2; |
| 1638 Operand halfwordOp = Operand(numHalfwords); |
| 1639 halfwordOp.setBits(16); |
| 1640 ri_form(BRCTG, r1, halfwordOp); |
| 1641 } |
| 1642 |
| 1643 // -------------------- |
| 1644 // Compare Instructions |
| 1645 // -------------------- |
| 1646 // Compare Register-Storage (32) |
| 1647 void Assembler::c(Register r, const MemOperand& opnd) { |
| 1648 rx_form(C, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1649 } |
| 1650 |
| 1651 // Compare Register-Storage (32) |
| 1652 void Assembler::cy(Register r, const MemOperand& opnd) { |
| 1653 rxy_form(CY, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1654 } |
| 1655 |
| 1656 // Compare Register-Register (32) |
| 1657 void Assembler::cr_z(Register r1, Register r2) { rr_form(CR, r1, r2); } |
| 1658 |
| 1659 // Compare Register-Storage (64) |
| 1660 void Assembler::cg(Register r, const MemOperand& opnd) { |
| 1661 rxy_form(CG, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1662 } |
| 1663 |
| 1664 // Compare Register-Register (64) |
| 1665 void Assembler::cgr(Register r1, Register r2) { rre_form(CGR, r1, r2); } |
| 1666 |
| 1667 // Compare Halfword Register-Storage (32) |
| 1668 void Assembler::ch(Register r, const MemOperand& opnd) { |
| 1669 rx_form(CH, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1670 } |
| 1671 |
| 1672 // Compare Halfword Register-Storage (32) |
| 1673 void Assembler::chy(Register r, const MemOperand& opnd) { |
| 1674 rxy_form(CHY, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1675 } |
| 1676 |
| 1677 // Compare Halfword Immediate (32) |
| 1678 void Assembler::chi(Register r, const Operand& opnd) { ri_form(CHI, r, opnd); } |
| 1679 |
| 1680 // Compare Halfword Immediate (64) |
| 1681 void Assembler::cghi(Register r, const Operand& opnd) { |
| 1682 ri_form(CGHI, r, opnd); |
| 1683 } |
| 1684 |
| 1685 // Compare Immediate (32) |
| 1686 void Assembler::cfi(Register r, const Operand& opnd) { ril_form(CFI, r, opnd); } |
| 1687 |
| 1688 // Compare Immediate (64) |
| 1689 void Assembler::cgfi(Register r, const Operand& opnd) { |
| 1690 ril_form(CGFI, r, opnd); |
| 1691 } |
| 1692 |
| 1693 // ---------------------------- |
| 1694 // Compare Logical Instructions |
| 1695 // ---------------------------- |
| 1696 // Compare Logical Register-Storage (32) |
| 1697 void Assembler::cl(Register r, const MemOperand& opnd) { |
| 1698 rx_form(CL, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1699 } |
| 1700 |
| 1701 // Compare Logical Register-Storage (32) |
| 1702 void Assembler::cly(Register r, const MemOperand& opnd) { |
| 1703 rxy_form(CLY, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1704 } |
| 1705 |
| 1706 // Compare Logical Register-Register (32) |
| 1707 void Assembler::clr(Register r1, Register r2) { rr_form(CLR, r1, r2); } |
| 1708 |
| 1709 // Compare Logical Register-Storage (64) |
| 1710 void Assembler::clg(Register r, const MemOperand& opnd) { |
| 1711 rxy_form(CLG, r, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1712 } |
| 1713 |
| 1714 // Compare Logical Register-Register (64) |
| 1715 void Assembler::clgr(Register r1, Register r2) { rre_form(CLGR, r1, r2); } |
| 1716 |
| 1717 // Compare Logical Immediate (32) |
| 1718 void Assembler::clfi(Register r1, const Operand& i2) { ril_form(CLFI, r1, i2); } |
| 1719 |
| 1720 // Compare Logical Immediate (64<32) |
| 1721 void Assembler::clgfi(Register r1, const Operand& i2) { |
| 1722 ril_form(CLGFI, r1, i2); |
| 1723 } |
| 1724 |
| 1725 // Compare Immediate (Mem - Imm) (8) |
| 1726 void Assembler::cli(const MemOperand& opnd, const Operand& imm) { |
| 1727 si_form(CLI, imm, opnd.rb(), opnd.offset()); |
| 1728 } |
| 1729 |
| 1730 // Compare Immediate (Mem - Imm) (8) |
| 1731 void Assembler::cliy(const MemOperand& opnd, const Operand& imm) { |
| 1732 siy_form(CLIY, imm, opnd.rb(), opnd.offset()); |
| 1733 } |
| 1734 |
| 1735 // Compare logical - mem to mem operation |
| 1736 void Assembler::clc(const MemOperand& opnd1, const MemOperand& opnd2, |
| 1737 Length length) { |
| 1738 ss_form(CLC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(), |
| 1739 opnd2.getBaseRegister(), opnd2.getDisplacement()); |
| 1740 } |
| 1741 |
| 1742 // ---------------------------- |
| 1743 // Test Under Mask Instructions |
| 1744 // ---------------------------- |
| 1745 // Test Under Mask (Mem - Imm) (8) |
| 1746 void Assembler::tm(const MemOperand& opnd, const Operand& imm) { |
| 1747 si_form(TM, imm, opnd.rb(), opnd.offset()); |
| 1748 } |
| 1749 |
| 1750 // Test Under Mask (Mem - Imm) (8) |
| 1751 void Assembler::tmy(const MemOperand& opnd, const Operand& imm) { |
| 1752 siy_form(TMY, imm, opnd.rb(), opnd.offset()); |
| 1753 } |
| 1754 |
| 1755 // ------------------------------- |
| 1756 // Rotate and Insert Selected Bits |
| 1757 // ------------------------------- |
| 1758 // Rotate-And-Insert-Selected-Bits |
| 1759 void Assembler::risbg(Register dst, Register src, const Operand& startBit, |
| 1760 const Operand& endBit, const Operand& shiftAmt, |
| 1761 bool zeroBits) { |
| 1762 // High tag the top bit of I4/EndBit to zero out any unselected bits |
| 1763 if (zeroBits) |
| 1764 rie_f_form(RISBG, dst, src, startBit, Operand(endBit.imm_ | 0x80), |
| 1765 shiftAmt); |
| 1766 else |
| 1767 rie_f_form(RISBG, dst, src, startBit, endBit, shiftAmt); |
| 1768 } |
| 1769 |
| 1770 // Rotate-And-Insert-Selected-Bits |
| 1771 void Assembler::risbgn(Register dst, Register src, const Operand& startBit, |
| 1772 const Operand& endBit, const Operand& shiftAmt, |
| 1773 bool zeroBits) { |
| 1774 // High tag the top bit of I4/EndBit to zero out any unselected bits |
| 1775 if (zeroBits) |
| 1776 rie_f_form(RISBGN, dst, src, startBit, Operand(endBit.imm_ | 0x80), |
| 1777 shiftAmt); |
| 1778 else |
| 1779 rie_f_form(RISBGN, dst, src, startBit, endBit, shiftAmt); |
| 1780 } |
| 1781 |
| 1782 // --------------------------- |
| 1783 // Move Character Instructions |
| 1784 // --------------------------- |
| 1785 // Move charactor - mem to mem operation |
| 1786 void Assembler::mvc(const MemOperand& opnd1, const MemOperand& opnd2, |
| 1787 uint32_t length) { |
| 1788 ss_form(MVC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(), |
| 1789 opnd2.getBaseRegister(), opnd2.getDisplacement()); |
| 1790 } |
| 1791 |
| 1792 // ----------------------- |
| 1793 // 32-bit Add Instructions |
| 1794 // ----------------------- |
| 1795 // Add Register-Storage (32) |
| 1796 void Assembler::a(Register r1, const MemOperand& opnd) { |
| 1797 rx_form(A, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1798 } |
| 1799 |
| 1800 // Add Register-Storage (32) |
| 1801 void Assembler::ay(Register r1, const MemOperand& opnd) { |
| 1802 rxy_form(AY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1803 } |
| 1804 |
| 1805 // Add Immediate (32) |
| 1806 void Assembler::afi(Register r1, const Operand& opnd) { |
| 1807 ril_form(ALFI, r1, opnd); |
| 1808 } |
| 1809 |
| 1810 // Add Halfword Register-Storage (32) |
| 1811 void Assembler::ah(Register r1, const MemOperand& opnd) { |
| 1812 rx_form(AH, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1813 } |
| 1814 |
| 1815 // Add Halfword Register-Storage (32) |
| 1816 void Assembler::ahy(Register r1, const MemOperand& opnd) { |
| 1817 rxy_form(AHY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1818 } |
| 1819 |
| 1820 // Add Halfword Immediate (32) |
| 1821 void Assembler::ahi(Register r1, const Operand& i2) { ri_form(AHI, r1, i2); } |
| 1822 |
| 1823 // Add Halfword Immediate (32) |
| 1824 void Assembler::ahik(Register r1, Register r3, const Operand& i2) { |
| 1825 rie_form(AHIK, r1, r3, i2); |
| 1826 } |
| 1827 |
| 1828 // Add Register (32) |
| 1829 void Assembler::ar(Register r1, Register r2) { rr_form(AR, r1, r2); } |
| 1830 |
| 1831 // Add Register-Register-Register (32) |
| 1832 void Assembler::ark(Register r1, Register r2, Register r3) { |
| 1833 rrf1_form(ARK, r1, r2, r3); |
| 1834 } |
| 1835 |
| 1836 // Add Storage-Imm (32) |
| 1837 void Assembler::asi(const MemOperand& opnd, const Operand& imm) { |
| 1838 DCHECK(is_int8(imm.imm_)); |
| 1839 DCHECK(is_int20(opnd.offset())); |
| 1840 siy_form(ASI, Operand(0xff & imm.imm_), opnd.rb(), 0xfffff & opnd.offset()); |
| 1841 } |
| 1842 |
| 1843 // ----------------------- |
| 1844 // 64-bit Add Instructions |
| 1845 // ----------------------- |
| 1846 // Add Register-Storage (64) |
| 1847 void Assembler::ag(Register r1, const MemOperand& opnd) { |
| 1848 rxy_form(AG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1849 } |
| 1850 |
| 1851 // Add Register-Storage (64<-32) |
| 1852 void Assembler::agf(Register r1, const MemOperand& opnd) { |
| 1853 rxy_form(AGF, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1854 } |
| 1855 |
| 1856 // Add Immediate (64) |
| 1857 void Assembler::agfi(Register r1, const Operand& opnd) { |
| 1858 ril_form(ALFI, r1, opnd); |
| 1859 } |
| 1860 |
| 1861 // Add Register-Register (64<-32) |
| 1862 void Assembler::agfr(Register r1, Register r2) { rre_form(AGFR, r1, r2); } |
| 1863 |
| 1864 // Add Halfword Immediate (64) |
| 1865 void Assembler::aghi(Register r1, const Operand& i2) { ri_form(AGHI, r1, i2); } |
| 1866 |
| 1867 // Add Halfword Immediate (64) |
| 1868 void Assembler::aghik(Register r1, Register r3, const Operand& i2) { |
| 1869 rie_form(AGHIK, r1, r3, i2); |
| 1870 } |
| 1871 |
| 1872 // Add Register (64) |
| 1873 void Assembler::agr(Register r1, Register r2) { rre_form(AGR, r1, r2); } |
| 1874 |
| 1875 // Add Register-Register-Register (64) |
| 1876 void Assembler::agrk(Register r1, Register r2, Register r3) { |
| 1877 rrf1_form(AGRK, r1, r2, r3); |
| 1878 } |
| 1879 |
| 1880 // Add Storage-Imm (64) |
| 1881 void Assembler::agsi(const MemOperand& opnd, const Operand& imm) { |
| 1882 DCHECK(is_int8(imm.imm_)); |
| 1883 DCHECK(is_int20(opnd.offset())); |
| 1884 siy_form(AGSI, Operand(0xff & imm.imm_), opnd.rb(), 0xfffff & opnd.offset()); |
| 1885 } |
| 1886 |
| 1887 // ------------------------------- |
| 1888 // 32-bit Add Logical Instructions |
| 1889 // ------------------------------- |
| 1890 // Add Logical Register-Storage (32) |
| 1891 void Assembler::al_z(Register r1, const MemOperand& opnd) { |
| 1892 rx_form(AL, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1893 } |
| 1894 |
| 1895 // Add Logical Register-Storage (32) |
| 1896 void Assembler::aly(Register r1, const MemOperand& opnd) { |
| 1897 rxy_form(ALY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1898 } |
| 1899 |
| 1900 // Add Logical Immediate (32) |
| 1901 void Assembler::alfi(Register r1, const Operand& opnd) { |
| 1902 ril_form(ALFI, r1, opnd); |
| 1903 } |
| 1904 |
| 1905 // Add Logical Register-Register (32) |
| 1906 void Assembler::alr(Register r1, Register r2) { rr_form(ALR, r1, r2); } |
| 1907 |
| 1908 // Add Logical Register-Register-Register (32) |
| 1909 void Assembler::alrk(Register r1, Register r2, Register r3) { |
| 1910 rrf1_form(ALRK, r1, r2, r3); |
| 1911 } |
| 1912 |
| 1913 // ------------------------------- |
| 1914 // 64-bit Add Logical Instructions |
| 1915 // ------------------------------- |
| 1916 // Add Logical Register-Storage (64) |
| 1917 void Assembler::alg(Register r1, const MemOperand& opnd) { |
| 1918 rxy_form(ALG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1919 } |
| 1920 |
| 1921 // Add Logical Immediate (64) |
| 1922 void Assembler::algfi(Register r1, const Operand& opnd) { |
| 1923 ril_form(ALFI, r1, opnd); |
| 1924 } |
| 1925 |
| 1926 // Add Logical Register-Register (64) |
| 1927 void Assembler::algr(Register r1, Register r2) { rre_form(ALGR, r1, r2); } |
| 1928 |
| 1929 // Add Logical Register-Register-Register (64) |
| 1930 void Assembler::algrk(Register r1, Register r2, Register r3) { |
| 1931 rrf1_form(ALGRK, r1, r2, r3); |
| 1932 } |
| 1933 |
| 1934 // ---------------------------- |
| 1935 // 32-bit Subtract Instructions |
| 1936 // ---------------------------- |
| 1937 // Subtract Register-Storage (32) |
| 1938 void Assembler::s(Register r1, const MemOperand& opnd) { |
| 1939 rx_form(S, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1940 } |
| 1941 |
| 1942 // Subtract Register-Storage (32) |
| 1943 void Assembler::sy(Register r1, const MemOperand& opnd) { |
| 1944 rxy_form(SY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1945 } |
| 1946 |
| 1947 // Subtract Halfword Register-Storage (32) |
| 1948 void Assembler::sh(Register r1, const MemOperand& opnd) { |
| 1949 rx_form(SH, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1950 } |
| 1951 |
| 1952 // Subtract Halfword Register-Storage (32) |
| 1953 void Assembler::shy(Register r1, const MemOperand& opnd) { |
| 1954 rxy_form(SHY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1955 } |
| 1956 |
| 1957 // Subtract Register (32) |
| 1958 void Assembler::sr(Register r1, Register r2) { rr_form(SR, r1, r2); } |
| 1959 |
| 1960 // Subtract Register-Register-Register (32) |
| 1961 void Assembler::srk(Register r1, Register r2, Register r3) { |
| 1962 rrf1_form(SRK, r1, r2, r3); |
| 1963 } |
| 1964 |
| 1965 // ---------------------------- |
| 1966 // 64-bit Subtract Instructions |
| 1967 // ---------------------------- |
| 1968 // Subtract Register-Storage (64) |
| 1969 void Assembler::sg(Register r1, const MemOperand& opnd) { |
| 1970 rxy_form(SG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1971 } |
| 1972 |
| 1973 // Subtract Register-Storage (64<-32) |
| 1974 void Assembler::sgf(Register r1, const MemOperand& opnd) { |
| 1975 rxy_form(SGF, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1976 } |
| 1977 |
| 1978 // Subtract Register (64) |
| 1979 void Assembler::sgr(Register r1, Register r2) { rre_form(SGR, r1, r2); } |
| 1980 |
| 1981 // Subtract Register (64<-32) |
| 1982 void Assembler::sgfr(Register r1, Register r2) { rre_form(SGFR, r1, r2); } |
| 1983 |
| 1984 // Subtract Register-Register-Register (64) |
| 1985 void Assembler::sgrk(Register r1, Register r2, Register r3) { |
| 1986 rrf1_form(SGRK, r1, r2, r3); |
| 1987 } |
| 1988 |
| 1989 // ------------------------------------ |
| 1990 // 32-bit Subtract Logical Instructions |
| 1991 // ------------------------------------ |
| 1992 // Subtract Logical Register-Storage (32) |
| 1993 void Assembler::sl(Register r1, const MemOperand& opnd) { |
| 1994 rx_form(SL, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 1995 } |
| 1996 |
| 1997 // Subtract Logical Register-Storage (32) |
| 1998 void Assembler::sly(Register r1, const MemOperand& opnd) { |
| 1999 rxy_form(SLY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2000 } |
| 2001 |
| 2002 // Subtract Logical Register-Register (32) |
| 2003 void Assembler::slr(Register r1, Register r2) { rr_form(SLR, r1, r2); } |
| 2004 |
| 2005 // Subtract Logical Register-Register-Register (32) |
| 2006 void Assembler::slrk(Register r1, Register r2, Register r3) { |
| 2007 rrf1_form(SLRK, r1, r2, r3); |
| 2008 } |
| 2009 |
| 2010 // ------------------------------------ |
| 2011 // 64-bit Subtract Logical Instructions |
| 2012 // ------------------------------------ |
| 2013 // Subtract Logical Register-Storage (64) |
| 2014 void Assembler::slg(Register r1, const MemOperand& opnd) { |
| 2015 rxy_form(SLG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2016 } |
| 2017 |
| 2018 // Subtract Logical Register-Register (64) |
| 2019 void Assembler::slgr(Register r1, Register r2) { rre_form(SLGR, r1, r2); } |
| 2020 |
| 2021 // Subtract Logical Register-Register-Register (64) |
| 2022 void Assembler::slgrk(Register r1, Register r2, Register r3) { |
| 2023 rrf1_form(SLGRK, r1, r2, r3); |
| 2024 } |
| 2025 |
| 2026 // ---------------------------- |
| 2027 // 32-bit Multiply Instructions |
| 2028 // ---------------------------- |
| 2029 // Multiply Register-Storage (64<32) |
| 2030 void Assembler::m(Register r1, const MemOperand& opnd) { |
| 2031 rx_form(M, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2032 } |
| 2033 |
| 2034 // Multiply Register (64<32) |
| 2035 void Assembler::mr_z(Register r1, Register r2) { |
| 2036 DCHECK(r1.code() % 2 == 0); |
| 2037 rr_form(MR, r1, r2); |
| 2038 } |
| 2039 |
| 2040 // Multiply Logical Register-Storage (64<32) |
| 2041 void Assembler::ml(Register r1, const MemOperand& opnd) { |
| 2042 rxy_form(ML, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2043 } |
| 2044 |
| 2045 // Multiply Logical Register (64<32) |
| 2046 void Assembler::mlr(Register r1, Register r2) { |
| 2047 DCHECK(r1.code() % 2 == 0); |
| 2048 rre_form(MLR, r1, r2); |
| 2049 } |
| 2050 |
| 2051 // Multiply Single Register-Storage (32) |
| 2052 void Assembler::ms(Register r1, const MemOperand& opnd) { |
| 2053 rx_form(MS, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2054 } |
| 2055 |
| 2056 // Multiply Single Register-Storage (32) |
| 2057 void Assembler::msy(Register r1, const MemOperand& opnd) { |
| 2058 rxy_form(MSY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2059 } |
| 2060 |
| 2061 // Multiply Single Immediate (32) |
| 2062 void Assembler::msfi(Register r1, const Operand& opnd) { |
| 2063 ril_form(MSFI, r1, opnd); |
| 2064 } |
| 2065 |
| 2066 // Multiply Single Register (64<32) |
| 2067 void Assembler::msr(Register r1, Register r2) { rre_form(MSR, r1, r2); } |
| 2068 |
| 2069 // Multiply Halfword Register-Storage (32) |
| 2070 void Assembler::mh(Register r1, const MemOperand& opnd) { |
| 2071 rx_form(MH, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2072 } |
| 2073 |
| 2074 // Multiply Halfword Register-Storage (32) |
| 2075 void Assembler::mhy(Register r1, const MemOperand& opnd) { |
| 2076 rxy_form(MHY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2077 } |
| 2078 |
| 2079 // Multiply Halfword Immediate (32) |
| 2080 void Assembler::mhi(Register r1, const Operand& opnd) { |
| 2081 ri_form(MHI, r1, opnd); |
| 2082 } |
| 2083 |
| 2084 // ---------------------------- |
| 2085 // 64-bit Multiply Instructions |
| 2086 // ---------------------------- |
| 2087 // Multiply Logical Register-Storage (128<64) |
| 2088 void Assembler::mlg(Register r1, const MemOperand& opnd) { |
| 2089 rxy_form(MLG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2090 } |
| 2091 |
| 2092 // Multiply Register (128<64) |
| 2093 void Assembler::mlgr(Register r1, Register r2) { rre_form(MLGR, r1, r2); } |
| 2094 |
| 2095 // Multiply Halfword Immediate (64) |
| 2096 void Assembler::mghi(Register r1, const Operand& opnd) { |
| 2097 ri_form(MGHI, r1, opnd); |
| 2098 } |
| 2099 |
| 2100 // Multiply Single Immediate (64) |
| 2101 void Assembler::msgfi(Register r1, const Operand& opnd) { |
| 2102 ril_form(MSGFI, r1, opnd); |
| 2103 } |
| 2104 |
| 2105 // Multiply Single Register-Storage (64) |
| 2106 void Assembler::msg(Register r1, const MemOperand& opnd) { |
| 2107 rxy_form(MSG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2108 } |
| 2109 |
| 2110 // Multiply Single Register-Register (64) |
| 2111 void Assembler::msgr(Register r1, Register r2) { rre_form(MSGR, r1, r2); } |
| 2112 |
| 2113 // -------------------------- |
| 2114 // 32-bit Divide Instructions |
| 2115 // -------------------------- |
| 2116 // Divide Register-Storage (32<-64) |
| 2117 void Assembler::d(Register r1, const MemOperand& opnd) { |
| 2118 rx_form(D, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2119 } |
| 2120 |
| 2121 // Divide Register (32<-64) |
| 2122 void Assembler::dr(Register r1, Register r2) { |
| 2123 DCHECK(r1.code() % 2 == 0); |
| 2124 rr_form(DR, r1, r2); |
| 2125 } |
| 2126 |
| 2127 // Divide Logical Register-Storage (32<-64) |
| 2128 void Assembler::dl(Register r1, const MemOperand& opnd) { |
| 2129 rx_form(DL, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2130 } |
| 2131 |
| 2132 // Divide Logical Register (32<-64) |
| 2133 void Assembler::dlr(Register r1, Register r2) { rre_form(DLR, r1, r2); } |
| 2134 |
| 2135 // -------------------------- |
| 2136 // 64-bit Divide Instructions |
| 2137 // -------------------------- |
| 2138 // Divide Logical Register (64<-128) |
| 2139 void Assembler::dlgr(Register r1, Register r2) { rre_form(DLGR, r1, r2); } |
| 2140 |
| 2141 // Divide Single Register (64<-32) |
| 2142 void Assembler::dsgr(Register r1, Register r2) { rre_form(DSGR, r1, r2); } |
| 2143 |
| 2144 // -------------------- |
| 2145 // Bitwise Instructions |
| 2146 // -------------------- |
| 2147 // AND Register-Storage (32) |
| 2148 void Assembler::n(Register r1, const MemOperand& opnd) { |
| 2149 rx_form(N, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2150 } |
| 2151 |
| 2152 // AND Register-Storage (32) |
| 2153 void Assembler::ny(Register r1, const MemOperand& opnd) { |
| 2154 rxy_form(NY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2155 } |
| 2156 |
| 2157 // AND Register (32) |
| 2158 void Assembler::nr(Register r1, Register r2) { rr_form(NR, r1, r2); } |
| 2159 |
| 2160 // AND Register-Register-Register (32) |
| 2161 void Assembler::nrk(Register r1, Register r2, Register r3) { |
| 2162 rrf1_form(NRK, r1, r2, r3); |
| 2163 } |
| 2164 |
| 2165 // AND Register-Storage (64) |
| 2166 void Assembler::ng(Register r1, const MemOperand& opnd) { |
| 2167 rxy_form(NG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2168 } |
| 2169 |
| 2170 // AND Register (64) |
| 2171 void Assembler::ngr(Register r1, Register r2) { rre_form(NGR, r1, r2); } |
| 2172 |
| 2173 // AND Register-Register-Register (64) |
| 2174 void Assembler::ngrk(Register r1, Register r2, Register r3) { |
| 2175 rrf1_form(NGRK, r1, r2, r3); |
| 2176 } |
| 2177 |
| 2178 // OR Register-Storage (32) |
| 2179 void Assembler::o(Register r1, const MemOperand& opnd) { |
| 2180 rx_form(O, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2181 } |
| 2182 |
| 2183 // OR Register-Storage (32) |
| 2184 void Assembler::oy(Register r1, const MemOperand& opnd) { |
| 2185 rxy_form(OY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2186 } |
| 2187 |
| 2188 // OR Register (32) |
| 2189 void Assembler::or_z(Register r1, Register r2) { rr_form(OR, r1, r2); } |
| 2190 |
| 2191 // OR Register-Register-Register (32) |
| 2192 void Assembler::ork(Register r1, Register r2, Register r3) { |
| 2193 rrf1_form(ORK, r1, r2, r3); |
| 2194 } |
| 2195 |
| 2196 // OR Register-Storage (64) |
| 2197 void Assembler::og(Register r1, const MemOperand& opnd) { |
| 2198 rxy_form(OG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2199 } |
| 2200 |
| 2201 // OR Register (64) |
| 2202 void Assembler::ogr(Register r1, Register r2) { rre_form(OGR, r1, r2); } |
| 2203 |
| 2204 // OR Register-Register-Register (64) |
| 2205 void Assembler::ogrk(Register r1, Register r2, Register r3) { |
| 2206 rrf1_form(OGRK, r1, r2, r3); |
| 2207 } |
| 2208 |
| 2209 // XOR Register-Storage (32) |
| 2210 void Assembler::x(Register r1, const MemOperand& opnd) { |
| 2211 rx_form(X, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2212 } |
| 2213 |
| 2214 // XOR Register-Storage (32) |
| 2215 void Assembler::xy(Register r1, const MemOperand& opnd) { |
| 2216 rxy_form(XY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2217 } |
| 2218 |
| 2219 // XOR Register (32) |
| 2220 void Assembler::xr(Register r1, Register r2) { rr_form(XR, r1, r2); } |
| 2221 |
| 2222 // XOR Register-Register-Register (32) |
| 2223 void Assembler::xrk(Register r1, Register r2, Register r3) { |
| 2224 rrf1_form(XRK, r1, r2, r3); |
| 2225 } |
| 2226 |
| 2227 // XOR Register-Storage (64) |
| 2228 void Assembler::xg(Register r1, const MemOperand& opnd) { |
| 2229 rxy_form(XG, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2230 } |
| 2231 |
| 2232 // XOR Register (64) |
| 2233 void Assembler::xgr(Register r1, Register r2) { rre_form(XGR, r1, r2); } |
| 2234 |
| 2235 // XOR Register-Register-Register (64) |
| 2236 void Assembler::xgrk(Register r1, Register r2, Register r3) { |
| 2237 rrf1_form(XGRK, r1, r2, r3); |
| 2238 } |
| 2239 |
| 2240 // XOR Storage-Storage |
| 2241 void Assembler::xc(const MemOperand& opnd1, const MemOperand& opnd2, |
| 2242 Length length) { |
| 2243 ss_form(XC, length - 1, opnd1.getBaseRegister(), opnd1.getDisplacement(), |
| 2244 opnd2.getBaseRegister(), opnd2.getDisplacement()); |
| 2245 } |
| 2246 |
| 2247 // ------------------------------------------- |
| 2248 // Bitwise GPR <-> FPR Conversion Instructions |
| 2249 // ------------------------------------------- |
| 2250 // Load GR from FPR (64 <- L) |
| 2251 void Assembler::lgdr(Register r1, DoubleRegister f2) { |
| 2252 rre_form(LGDR, r1, Register::from_code(f2.code())); |
| 2253 } |
| 2254 |
| 2255 // Load FPR from FR (L <- 64) |
| 2256 void Assembler::ldgr(DoubleRegister f1, Register r2) { |
| 2257 rre_form(LDGR, Register::from_code(f1.code()), r2); |
| 2258 } |
| 2259 |
| 2260 void Assembler::EnsureSpaceFor(int space_needed) { |
| 2261 if (buffer_space() <= (kGap + space_needed)) { |
| 2262 GrowBuffer(space_needed); |
| 2263 } |
| 2264 } |
| 2265 |
| 2266 // Rotate Left Single Logical (32) |
| 2267 void Assembler::rll(Register r1, Register r3, Register opnd) { |
| 2268 DCHECK(!opnd.is(r0)); |
| 2269 rsy_form(RLL, r1, r3, opnd, 0); |
| 2270 } |
| 2271 |
| 2272 // Rotate Left Single Logical (32) |
| 2273 void Assembler::rll(Register r1, Register r3, const Operand& opnd) { |
| 2274 rsy_form(RLL, r1, r3, r0, opnd.immediate()); |
| 2275 } |
| 2276 |
| 2277 // Rotate Left Single Logical (32) |
| 2278 void Assembler::rll(Register r1, Register r3, Register r2, |
| 2279 const Operand& opnd) { |
| 2280 rsy_form(RLL, r1, r3, r2, opnd.immediate()); |
| 2281 } |
| 2282 |
| 2283 // Rotate Left Single Logical (64) |
| 2284 void Assembler::rllg(Register r1, Register r3, Register opnd) { |
| 2285 DCHECK(!opnd.is(r0)); |
| 2286 rsy_form(RLLG, r1, r3, opnd, 0); |
| 2287 } |
| 2288 |
| 2289 // Rotate Left Single Logical (64) |
| 2290 void Assembler::rllg(Register r1, Register r3, const Operand& opnd) { |
| 2291 rsy_form(RLLG, r1, r3, r0, opnd.immediate()); |
| 2292 } |
| 2293 |
| 2294 // Rotate Left Single Logical (64) |
| 2295 void Assembler::rllg(Register r1, Register r3, Register r2, |
| 2296 const Operand& opnd) { |
| 2297 rsy_form(RLLG, r1, r3, r2, opnd.immediate()); |
| 2298 } |
| 2299 |
| 2300 // Shift Left Single Logical (32) |
| 2301 void Assembler::sll(Register r1, Register opnd) { |
| 2302 DCHECK(!opnd.is(r0)); |
| 2303 rs_form(SLL, r1, r0, opnd, 0); |
| 2304 } |
| 2305 |
| 2306 // Shift Left Single Logical (32) |
| 2307 void Assembler::sll(Register r1, const Operand& opnd) { |
| 2308 rs_form(SLL, r1, r0, r0, opnd.immediate()); |
| 2309 } |
| 2310 |
| 2311 // Shift Left Single Logical (32) |
| 2312 void Assembler::sllk(Register r1, Register r3, Register opnd) { |
| 2313 DCHECK(!opnd.is(r0)); |
| 2314 rsy_form(SLLK, r1, r3, opnd, 0); |
| 2315 } |
| 2316 |
| 2317 // Shift Left Single Logical (32) |
| 2318 void Assembler::sllk(Register r1, Register r3, const Operand& opnd) { |
| 2319 rsy_form(SLLK, r1, r3, r0, opnd.immediate()); |
| 2320 } |
| 2321 |
| 2322 // Shift Left Single Logical (64) |
| 2323 void Assembler::sllg(Register r1, Register r3, Register opnd) { |
| 2324 DCHECK(!opnd.is(r0)); |
| 2325 rsy_form(SLLG, r1, r3, opnd, 0); |
| 2326 } |
| 2327 |
| 2328 // Shift Left Single Logical (64) |
| 2329 void Assembler::sllg(Register r1, Register r3, const Operand& opnd) { |
| 2330 rsy_form(SLLG, r1, r3, r0, opnd.immediate()); |
| 2331 } |
| 2332 |
| 2333 // Shift Right Single Logical (32) |
| 2334 void Assembler::srl(Register r1, Register opnd) { |
| 2335 DCHECK(!opnd.is(r0)); |
| 2336 rs_form(SRL, r1, r0, opnd, 0); |
| 2337 } |
| 2338 |
| 2339 // Shift Right Single Logical (32) |
| 2340 void Assembler::srl(Register r1, const Operand& opnd) { |
| 2341 rs_form(SRL, r1, r0, r0, opnd.immediate()); |
| 2342 } |
| 2343 |
| 2344 // Shift Right Single Logical (32) |
| 2345 void Assembler::srlk(Register r1, Register r3, Register opnd) { |
| 2346 DCHECK(!opnd.is(r0)); |
| 2347 rsy_form(SRLK, r1, r3, opnd, 0); |
| 2348 } |
| 2349 |
| 2350 // Shift Right Single Logical (32) |
| 2351 void Assembler::srlk(Register r1, Register r3, const Operand& opnd) { |
| 2352 rsy_form(SRLK, r1, r3, r0, opnd.immediate()); |
| 2353 } |
| 2354 |
| 2355 // Shift Right Single Logical (64) |
| 2356 void Assembler::srlg(Register r1, Register r3, Register opnd) { |
| 2357 DCHECK(!opnd.is(r0)); |
| 2358 rsy_form(SRLG, r1, r3, opnd, 0); |
| 2359 } |
| 2360 |
| 2361 // Shift Right Single Logical (64) |
| 2362 void Assembler::srlg(Register r1, Register r3, const Operand& opnd) { |
| 2363 rsy_form(SRLG, r1, r3, r0, opnd.immediate()); |
| 2364 } |
| 2365 |
| 2366 // Shift Left Single (32) |
| 2367 void Assembler::sla(Register r1, Register opnd) { |
| 2368 DCHECK(!opnd.is(r0)); |
| 2369 rs_form(SLA, r1, r0, opnd, 0); |
| 2370 } |
| 2371 |
| 2372 // Shift Left Single (32) |
| 2373 void Assembler::sla(Register r1, const Operand& opnd) { |
| 2374 rs_form(SLA, r1, r0, r0, opnd.immediate()); |
| 2375 } |
| 2376 |
| 2377 // Shift Left Single (32) |
| 2378 void Assembler::slak(Register r1, Register r3, Register opnd) { |
| 2379 DCHECK(!opnd.is(r0)); |
| 2380 rsy_form(SLAK, r1, r3, opnd, 0); |
| 2381 } |
| 2382 |
| 2383 // Shift Left Single (32) |
| 2384 void Assembler::slak(Register r1, Register r3, const Operand& opnd) { |
| 2385 rsy_form(SLAK, r1, r3, r0, opnd.immediate()); |
| 2386 } |
| 2387 |
| 2388 // Shift Left Single (64) |
| 2389 void Assembler::slag(Register r1, Register r3, Register opnd) { |
| 2390 DCHECK(!opnd.is(r0)); |
| 2391 rsy_form(SLAG, r1, r3, opnd, 0); |
| 2392 } |
| 2393 |
| 2394 // Shift Left Single (64) |
| 2395 void Assembler::slag(Register r1, Register r3, const Operand& opnd) { |
| 2396 rsy_form(SLAG, r1, r3, r0, opnd.immediate()); |
| 2397 } |
| 2398 |
| 2399 // Shift Right Single (32) |
| 2400 void Assembler::sra(Register r1, Register opnd) { |
| 2401 DCHECK(!opnd.is(r0)); |
| 2402 rs_form(SRA, r1, r0, opnd, 0); |
| 2403 } |
| 2404 |
| 2405 // Shift Right Single (32) |
| 2406 void Assembler::sra(Register r1, const Operand& opnd) { |
| 2407 rs_form(SRA, r1, r0, r0, opnd.immediate()); |
| 2408 } |
| 2409 |
| 2410 // Shift Right Single (32) |
| 2411 void Assembler::srak(Register r1, Register r3, Register opnd) { |
| 2412 DCHECK(!opnd.is(r0)); |
| 2413 rsy_form(SRAK, r1, r3, opnd, 0); |
| 2414 } |
| 2415 |
| 2416 // Shift Right Single (32) |
| 2417 void Assembler::srak(Register r1, Register r3, const Operand& opnd) { |
| 2418 rsy_form(SRAK, r1, r3, r0, opnd.immediate()); |
| 2419 } |
| 2420 |
| 2421 // Shift Right Single (64) |
| 2422 void Assembler::srag(Register r1, Register r3, Register opnd) { |
| 2423 DCHECK(!opnd.is(r0)); |
| 2424 rsy_form(SRAG, r1, r3, opnd, 0); |
| 2425 } |
| 2426 |
| 2427 void Assembler::srag(Register r1, Register r3, const Operand& opnd) { |
| 2428 rsy_form(SRAG, r1, r3, r0, opnd.immediate()); |
| 2429 } |
| 2430 |
| 2431 // Shift Right Double |
| 2432 void Assembler::srda(Register r1, const Operand& opnd) { |
| 2433 DCHECK(r1.code() % 2 == 0); |
| 2434 rs_form(SRDA, r1, r0, r0, opnd.immediate()); |
| 2435 } |
| 2436 |
| 2437 // Shift Right Double Logical |
| 2438 void Assembler::srdl(Register r1, const Operand& opnd) { |
| 2439 DCHECK(r1.code() % 2 == 0); |
| 2440 rs_form(SRDL, r1, r0, r0, opnd.immediate()); |
| 2441 } |
| 2442 |
| 2443 void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode, |
| 2444 TypeFeedbackId ast_id) { |
| 2445 positions_recorder()->WriteRecordedPositions(); |
| 2446 EnsureSpace ensure_space(this); |
| 2447 |
| 2448 int32_t target_index = emit_code_target(target, rmode, ast_id); |
| 2449 brasl(r14, Operand(target_index)); |
| 2450 } |
| 2451 |
| 2452 void Assembler::jump(Handle<Code> target, RelocInfo::Mode rmode, |
| 2453 Condition cond) { |
| 2454 EnsureSpace ensure_space(this); |
| 2455 |
| 2456 int32_t target_index = emit_code_target(target, rmode); |
| 2457 brcl(cond, Operand(target_index), true); |
| 2458 } |
| 2459 |
| 2460 // Store (32) |
| 2461 void Assembler::st(Register src, const MemOperand& dst) { |
| 2462 rx_form(ST, src, dst.rx(), dst.rb(), dst.offset()); |
| 2463 } |
| 2464 |
| 2465 // Store (32) |
| 2466 void Assembler::sty(Register src, const MemOperand& dst) { |
| 2467 rxy_form(STY, src, dst.rx(), dst.rb(), dst.offset()); |
| 2468 } |
| 2469 |
| 2470 // Store Halfword |
| 2471 void Assembler::sth(Register src, const MemOperand& dst) { |
| 2472 rx_form(STH, src, dst.rx(), dst.rb(), dst.offset()); |
| 2473 } |
| 2474 |
| 2475 // Store Halfword |
| 2476 void Assembler::sthy(Register src, const MemOperand& dst) { |
| 2477 rxy_form(STHY, src, dst.rx(), dst.rb(), dst.offset()); |
| 2478 } |
| 2479 |
| 2480 // Store Character |
| 2481 void Assembler::stc(Register src, const MemOperand& dst) { |
| 2482 rx_form(STC, src, dst.rx(), dst.rb(), dst.offset()); |
| 2483 } |
| 2484 |
| 2485 // Store Character |
| 2486 void Assembler::stcy(Register src, const MemOperand& dst) { |
| 2487 rxy_form(STCY, src, dst.rx(), dst.rb(), dst.offset()); |
| 2488 } |
| 2489 |
| 2490 // 32-bit Load Multiple - short displacement (12-bits unsigned) |
| 2491 void Assembler::lm(Register r1, Register r2, const MemOperand& src) { |
| 2492 rs_form(LM, r1, r2, src.rb(), src.offset()); |
| 2493 } |
| 2494 |
| 2495 // 32-bit Load Multiple - long displacement (20-bits signed) |
| 2496 void Assembler::lmy(Register r1, Register r2, const MemOperand& src) { |
| 2497 rsy_form(LMY, r1, r2, src.rb(), src.offset()); |
| 2498 } |
| 2499 |
| 2500 // 64-bit Load Multiple - long displacement (20-bits signed) |
| 2501 void Assembler::lmg(Register r1, Register r2, const MemOperand& src) { |
| 2502 rsy_form(LMG, r1, r2, src.rb(), src.offset()); |
| 2503 } |
| 2504 |
| 2505 // Move integer (32) |
| 2506 void Assembler::mvhi(const MemOperand& opnd1, const Operand& i2) { |
| 2507 sil_form(MVHI, opnd1.getBaseRegister(), opnd1.getDisplacement(), i2); |
| 2508 } |
| 2509 |
| 2510 // Move integer (64) |
| 2511 void Assembler::mvghi(const MemOperand& opnd1, const Operand& i2) { |
| 2512 sil_form(MVGHI, opnd1.getBaseRegister(), opnd1.getDisplacement(), i2); |
| 2513 } |
| 2514 |
| 2515 // Store Register (64) |
| 2516 void Assembler::stg(Register src, const MemOperand& dst) { |
| 2517 rxy_form(STG, src, dst.rx(), dst.rb(), dst.offset()); |
| 2518 } |
| 2519 |
| 2520 // Insert Character |
| 2521 void Assembler::ic_z(Register r1, const MemOperand& opnd) { |
| 2522 rx_form(IC_z, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2523 } |
| 2524 |
| 2525 // Insert Character |
| 2526 void Assembler::icy(Register r1, const MemOperand& opnd) { |
| 2527 rxy_form(ICY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2528 } |
| 2529 |
| 2530 // Insert Immediate (High) |
| 2531 void Assembler::iihf(Register r1, const Operand& opnd) { |
| 2532 ril_form(IIHF, r1, opnd); |
| 2533 } |
| 2534 |
| 2535 // Insert Immediate (low) |
| 2536 void Assembler::iilf(Register r1, const Operand& opnd) { |
| 2537 ril_form(IILF, r1, opnd); |
| 2538 } |
| 2539 |
| 2540 // Insert Immediate (high high) |
| 2541 void Assembler::iihh(Register r1, const Operand& opnd) { |
| 2542 ri_form(IIHH, r1, opnd); |
| 2543 } |
| 2544 |
| 2545 // Insert Immediate (high low) |
| 2546 void Assembler::iihl(Register r1, const Operand& opnd) { |
| 2547 ri_form(IIHL, r1, opnd); |
| 2548 } |
| 2549 |
| 2550 // Insert Immediate (low high) |
| 2551 void Assembler::iilh(Register r1, const Operand& opnd) { |
| 2552 ri_form(IILH, r1, opnd); |
| 2553 } |
| 2554 |
| 2555 // Insert Immediate (low low) |
| 2556 void Assembler::iill(Register r1, const Operand& opnd) { |
| 2557 ri_form(IILL, r1, opnd); |
| 2558 } |
| 2559 |
| 2560 // GPR <-> FPR Instructions |
| 2561 |
| 2562 // Floating point instructions |
| 2563 // |
| 2564 // Load zero Register (64) |
| 2565 void Assembler::lzdr(DoubleRegister r1) { |
| 2566 rre_form(LZDR, Register::from_code(r1.code()), Register::from_code(0)); |
| 2567 } |
| 2568 |
| 2569 // Add Register-Register (LB) |
| 2570 void Assembler::aebr(DoubleRegister r1, DoubleRegister r2) { |
| 2571 rre_form(AEBR, Register::from_code(r1.code()), |
| 2572 Register::from_code(r2.code())); |
| 2573 } |
| 2574 |
| 2575 // Add Register-Storage (LB) |
| 2576 void Assembler::adb(DoubleRegister r1, const MemOperand& opnd) { |
| 2577 rxe_form(ADB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), |
| 2578 opnd.offset()); |
| 2579 } |
| 2580 |
| 2581 // Add Register-Register (LB) |
| 2582 void Assembler::adbr(DoubleRegister r1, DoubleRegister r2) { |
| 2583 rre_form(ADBR, Register::from_code(r1.code()), |
| 2584 Register::from_code(r2.code())); |
| 2585 } |
| 2586 |
| 2587 // Compare Register-Register (LB) |
| 2588 void Assembler::cebr(DoubleRegister r1, DoubleRegister r2) { |
| 2589 rre_form(CEBR, Register::from_code(r1.code()), |
| 2590 Register::from_code(r2.code())); |
| 2591 } |
| 2592 |
| 2593 // Compare Register-Storage (LB) |
| 2594 void Assembler::cdb(DoubleRegister r1, const MemOperand& opnd) { |
| 2595 rx_form(CD, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), |
| 2596 opnd.offset()); |
| 2597 } |
| 2598 |
| 2599 // Compare Register-Register (LB) |
| 2600 void Assembler::cdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2601 rre_form(CDBR, Register::from_code(r1.code()), |
| 2602 Register::from_code(r2.code())); |
| 2603 } |
| 2604 |
| 2605 // Divide Register-Register (LB) |
| 2606 void Assembler::debr(DoubleRegister r1, DoubleRegister r2) { |
| 2607 rre_form(DEBR, Register::from_code(r1.code()), |
| 2608 Register::from_code(r2.code())); |
| 2609 } |
| 2610 |
| 2611 // Divide Register-Storage (LB) |
| 2612 void Assembler::ddb(DoubleRegister r1, const MemOperand& opnd) { |
| 2613 rxe_form(DDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), |
| 2614 opnd.offset()); |
| 2615 } |
| 2616 |
| 2617 // Divide Register-Register (LB) |
| 2618 void Assembler::ddbr(DoubleRegister r1, DoubleRegister r2) { |
| 2619 rre_form(DDBR, Register::from_code(r1.code()), |
| 2620 Register::from_code(r2.code())); |
| 2621 } |
| 2622 |
| 2623 // Multiply Register-Register (LB) |
| 2624 void Assembler::meebr(DoubleRegister r1, DoubleRegister r2) { |
| 2625 rre_form(MEEBR, Register::from_code(r1.code()), |
| 2626 Register::from_code(r2.code())); |
| 2627 } |
| 2628 |
| 2629 // Multiply Register-Storage (LB) |
| 2630 void Assembler::mdb(DoubleRegister r1, const MemOperand& opnd) { |
| 2631 rxe_form(MDB, Register::from_code(r1.code()), opnd.rb(), opnd.rx(), |
| 2632 opnd.offset()); |
| 2633 } |
| 2634 |
| 2635 // Multiply Register-Register (LB) |
| 2636 void Assembler::mdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2637 rre_form(MDBR, Register::from_code(r1.code()), |
| 2638 Register::from_code(r2.code())); |
| 2639 } |
| 2640 |
| 2641 // Subtract Register-Register (LB) |
| 2642 void Assembler::sebr(DoubleRegister r1, DoubleRegister r2) { |
| 2643 rre_form(SEBR, Register::from_code(r1.code()), |
| 2644 Register::from_code(r2.code())); |
| 2645 } |
| 2646 |
| 2647 // Subtract Register-Storage (LB) |
| 2648 void Assembler::sdb(DoubleRegister r1, const MemOperand& opnd) { |
| 2649 rxe_form(SDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), |
| 2650 opnd.offset()); |
| 2651 } |
| 2652 |
| 2653 // Subtract Register-Register (LB) |
| 2654 void Assembler::sdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2655 rre_form(SDBR, Register::from_code(r1.code()), |
| 2656 Register::from_code(r2.code())); |
| 2657 } |
| 2658 |
| 2659 // Square Root (LB) |
| 2660 void Assembler::sqdb(DoubleRegister r1, const MemOperand& opnd) { |
| 2661 rxe_form(SQDB, Register::from_code(r1.code()), opnd.rx(), opnd.rb(), |
| 2662 opnd.offset()); |
| 2663 } |
| 2664 |
| 2665 // Square Root Register-Register (LB) |
| 2666 void Assembler::sqebr(DoubleRegister r1, DoubleRegister r2) { |
| 2667 rre_form(SQEBR, Register::from_code(r1.code()), |
| 2668 Register::from_code(r2.code())); |
| 2669 } |
| 2670 |
| 2671 // Square Root Register-Register (LB) |
| 2672 void Assembler::sqdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2673 rre_form(SQDBR, Register::from_code(r1.code()), |
| 2674 Register::from_code(r2.code())); |
| 2675 } |
| 2676 |
| 2677 // Load Rounded (double -> float) |
| 2678 void Assembler::ledbr(DoubleRegister r1, DoubleRegister r2) { |
| 2679 rre_form(LEDBR, Register::from_code(r1.code()), |
| 2680 Register::from_code(r2.code())); |
| 2681 } |
| 2682 |
| 2683 // Load Lengthen (float -> double) |
| 2684 void Assembler::ldebr(DoubleRegister r1, DoubleRegister r2) { |
| 2685 rre_form(LDEBR, Register::from_code(r1.code()), |
| 2686 Register::from_code(r2.code())); |
| 2687 } |
| 2688 |
| 2689 // Load Complement Register-Register (LB) |
| 2690 void Assembler::lcdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2691 rre_form(LCDBR, Register::from_code(r1.code()), |
| 2692 Register::from_code(r2.code())); |
| 2693 } |
| 2694 |
| 2695 // Load Positive Register-Register (LB) |
| 2696 void Assembler::lpebr(DoubleRegister r1, DoubleRegister r2) { |
| 2697 rre_form(LPEBR, Register::from_code(r1.code()), |
| 2698 Register::from_code(r2.code())); |
| 2699 } |
| 2700 |
| 2701 // Load Positive Register-Register (LB) |
| 2702 void Assembler::lpdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2703 rre_form(LPDBR, Register::from_code(r1.code()), |
| 2704 Register::from_code(r2.code())); |
| 2705 } |
| 2706 |
| 2707 // Store Double (64) |
| 2708 void Assembler::std(DoubleRegister r1, const MemOperand& opnd) { |
| 2709 rx_form(STD, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2710 } |
| 2711 |
| 2712 // Store Double (64) |
| 2713 void Assembler::stdy(DoubleRegister r1, const MemOperand& opnd) { |
| 2714 rxy_form(STDY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2715 } |
| 2716 |
| 2717 // Store Float (32) |
| 2718 void Assembler::ste(DoubleRegister r1, const MemOperand& opnd) { |
| 2719 rx_form(STE, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2720 } |
| 2721 |
| 2722 // Store Float (32) |
| 2723 void Assembler::stey(DoubleRegister r1, const MemOperand& opnd) { |
| 2724 rxy_form(STEY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2725 } |
| 2726 |
| 2727 // Load Double (64) |
| 2728 void Assembler::ld(DoubleRegister r1, const MemOperand& opnd) { |
| 2729 DCHECK(is_uint12(opnd.offset())); |
| 2730 rx_form(LD, r1, opnd.rx(), opnd.rb(), opnd.offset() & 0xfff); |
| 2731 } |
| 2732 |
| 2733 // Load Double (64) |
| 2734 void Assembler::ldy(DoubleRegister r1, const MemOperand& opnd) { |
| 2735 DCHECK(is_int20(opnd.offset())); |
| 2736 rxy_form(LDY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2737 } |
| 2738 |
| 2739 // Load Float (32) |
| 2740 void Assembler::le_z(DoubleRegister r1, const MemOperand& opnd) { |
| 2741 DCHECK(is_uint12(opnd.offset())); |
| 2742 rx_form(LE, r1, opnd.rx(), opnd.rb(), opnd.offset() & 0xfff); |
| 2743 } |
| 2744 |
| 2745 // Load Float (32) |
| 2746 void Assembler::ley(DoubleRegister r1, const MemOperand& opnd) { |
| 2747 DCHECK(is_int20(opnd.offset())); |
| 2748 rxy_form(LEY, r1, opnd.rx(), opnd.rb(), opnd.offset()); |
| 2749 } |
| 2750 |
| 2751 // Load Double Register-Register (64) |
| 2752 void Assembler::ldr(DoubleRegister r1, DoubleRegister r2) { |
| 2753 rr_form(LDR, r1, r2); |
| 2754 } |
| 2755 |
| 2756 // Load And Test Register-Register (L) |
| 2757 void Assembler::ltebr(DoubleRegister r1, DoubleRegister r2) { |
| 2758 rre_form(LTEBR, r1, r2); |
| 2759 } |
| 2760 |
| 2761 // Load And Test Register-Register (L) |
| 2762 void Assembler::ltdbr(DoubleRegister r1, DoubleRegister r2) { |
| 2763 rre_form(LTDBR, r1, r2); |
| 2764 } |
| 2765 |
| 2766 // Convert to Fixed point (64<-S) |
| 2767 void Assembler::cgebr(Condition m, Register r1, DoubleRegister r2) { |
| 2768 rrfe_form(CGEBR, m, Condition(0), r1, Register::from_code(r2.code())); |
| 2769 } |
| 2770 |
| 2771 // Convert to Fixed point (64<-L) |
| 2772 void Assembler::cgdbr(Condition m, Register r1, DoubleRegister r2) { |
| 2773 rrfe_form(CGDBR, m, Condition(0), r1, Register::from_code(r2.code())); |
| 2774 } |
| 2775 |
| 2776 // Convert to Fixed point (32<-L) |
| 2777 void Assembler::cfdbr(Condition m, Register r1, DoubleRegister r2) { |
| 2778 rrfe_form(CFDBR, m, Condition(0), r1, Register::from_code(r2.code())); |
| 2779 } |
| 2780 |
| 2781 // Convert from Fixed point (L<-64) |
| 2782 void Assembler::cegbr(DoubleRegister r1, Register r2) { |
| 2783 rre_form(CEGBR, Register::from_code(r1.code()), r2); |
| 2784 } |
| 2785 |
| 2786 // Convert from Fixed point (L<-64) |
| 2787 void Assembler::cdgbr(DoubleRegister r1, Register r2) { |
| 2788 rre_form(CDGBR, Register::from_code(r1.code()), r2); |
| 2789 } |
| 2790 |
| 2791 // Convert from Fixed point (L<-32) |
| 2792 void Assembler::cdfbr(DoubleRegister r1, Register r2) { |
| 2793 rre_form(CDFBR, Register::from_code(r1.code()), r2); |
| 2794 } |
| 2795 |
| 2796 // Convert to Fixed Logical (64<-L) |
| 2797 void Assembler::clgdbr(Condition m3, Condition m4, Register r1, |
| 2798 DoubleRegister r2) { |
| 2799 DCHECK_EQ(m4, Condition(0)); |
| 2800 rrfe_form(CLGDBR, m3, m4, r1, Register::from_code(r2.code())); |
| 2801 } |
| 2802 |
| 2803 // Convert to Fixed Logical (64<-F32) |
| 2804 void Assembler::clgebr(Condition m3, Condition m4, Register r1, |
| 2805 DoubleRegister r2) { |
| 2806 DCHECK_EQ(m4, Condition(0)); |
| 2807 rrfe_form(CLGEBR, m3, m4, r1, Register::from_code(r2.code())); |
| 2808 } |
| 2809 |
| 2810 // Convert to Fixed Logical (32<-F64) |
| 2811 void Assembler::clfdbr(Condition m3, Condition m4, Register r1, |
| 2812 DoubleRegister r2) { |
| 2813 DCHECK_EQ(m3, Condition(0)); |
| 2814 DCHECK_EQ(m4, Condition(0)); |
| 2815 rrfe_form(CLFDBR, Condition(0), Condition(0), r1, |
| 2816 Register::from_code(r2.code())); |
| 2817 } |
| 2818 |
| 2819 // Convert to Fixed Logical (32<-F32) |
| 2820 void Assembler::clfebr(Condition m3, Condition m4, Register r1, |
| 2821 DoubleRegister r2) { |
| 2822 DCHECK_EQ(m4, Condition(0)); |
| 2823 rrfe_form(CLFEBR, m3, Condition(0), r1, Register::from_code(r2.code())); |
| 2824 } |
| 2825 |
| 2826 // Convert from Fixed Logical (L<-64) |
| 2827 void Assembler::celgbr(Condition m3, Condition m4, DoubleRegister r1, |
| 2828 Register r2) { |
| 2829 DCHECK_EQ(m3, Condition(0)); |
| 2830 DCHECK_EQ(m4, Condition(0)); |
| 2831 rrfe_form(CELGBR, Condition(0), Condition(0), Register::from_code(r1.code()), |
| 2832 r2); |
| 2833 } |
| 2834 |
| 2835 // Convert from Fixed Logical (F32<-32) |
| 2836 void Assembler::celfbr(Condition m3, Condition m4, DoubleRegister r1, |
| 2837 Register r2) { |
| 2838 DCHECK_EQ(m3, Condition(0)); |
| 2839 DCHECK_EQ(m4, Condition(0)); |
| 2840 rrfe_form(CELFBR, Condition(0), Condition(0), Register::from_code(r1.code()), |
| 2841 r2); |
| 2842 } |
| 2843 |
| 2844 // Convert from Fixed Logical (L<-64) |
| 2845 void Assembler::cdlgbr(Condition m3, Condition m4, DoubleRegister r1, |
| 2846 Register r2) { |
| 2847 DCHECK_EQ(m3, Condition(0)); |
| 2848 DCHECK_EQ(m4, Condition(0)); |
| 2849 rrfe_form(CDLGBR, Condition(0), Condition(0), Register::from_code(r1.code()), |
| 2850 r2); |
| 2851 } |
| 2852 |
| 2853 // Convert from Fixed Logical (L<-32) |
| 2854 void Assembler::cdlfbr(Condition m3, Condition m4, DoubleRegister r1, |
| 2855 Register r2) { |
| 2856 DCHECK_EQ(m4, Condition(0)); |
| 2857 rrfe_form(CDLFBR, m3, Condition(0), Register::from_code(r1.code()), r2); |
| 2858 } |
| 2859 |
| 2860 // Convert from Fixed point (S<-32) |
| 2861 void Assembler::cefbr(DoubleRegister r1, Register r2) { |
| 2862 rre_form(CEFBR, Register::from_code(r1.code()), r2); |
| 2863 } |
| 2864 |
| 2865 // Convert to Fixed point (32<-S) |
| 2866 void Assembler::cfebr(Condition m3, Register r1, DoubleRegister r2) { |
| 2867 rrfe_form(CFEBR, m3, Condition(0), r1, Register::from_code(r2.code())); |
| 2868 } |
| 2869 |
| 2870 // Load (L <- S) |
| 2871 void Assembler::ldeb(DoubleRegister d1, const MemOperand& opnd) { |
| 2872 rxe_form(LDEB, Register::from_code(d1.code()), opnd.rx(), opnd.rb(), |
| 2873 opnd.offset()); |
| 2874 } |
| 2875 |
| 2876 // Load FP Integer |
| 2877 void Assembler::fiebra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3) { |
| 2878 rrf2_form(FIEBRA << 16 | m3 * B12 | d1.code() * B4 | d2.code()); |
| 2879 } |
| 2880 |
| 2881 // Load FP Integer |
| 2882 void Assembler::fidbra(DoubleRegister d1, DoubleRegister d2, FIDBRA_MASK3 m3) { |
| 2883 rrf2_form(FIDBRA << 16 | m3 * B12 | d1.code() * B4 | d2.code()); |
| 2884 } |
| 2885 |
| 2886 // Multiply and Add - MADBR R1, R3, R2 |
| 2887 // R1 = R3 * R2 + R1 |
| 2888 void Assembler::madbr(DoubleRegister d1, DoubleRegister d3, DoubleRegister d2) { |
| 2889 rrd_form(MADBR, Register::from_code(d1.code()), |
| 2890 Register::from_code(d3.code()), Register::from_code(d2.code())); |
| 2891 } |
| 2892 |
| 2893 // Multiply and Subtract - MSDBR R1, R3, R2 |
| 2894 // R1 = R3 * R2 - R1 |
| 2895 void Assembler::msdbr(DoubleRegister d1, DoubleRegister d3, DoubleRegister d2) { |
| 2896 rrd_form(MSDBR, Register::from_code(d1.code()), |
| 2897 Register::from_code(d3.code()), Register::from_code(d2.code())); |
| 2898 } |
| 2899 |
| 2900 // end of S390instructions |
| 2901 |
| 2902 bool Assembler::IsNop(SixByteInstr instr, int type) { |
| 2903 DCHECK((0 == type) || (DEBUG_BREAK_NOP == type)); |
| 2904 if (DEBUG_BREAK_NOP == type) { |
| 2905 return ((instr & 0xffffffff) == 0xa53b0000); // oill r3, 0 |
| 2906 } |
| 2907 return ((instr & 0xffff) == 0x1800); // lr r0,r0 |
| 2908 } |
| 2909 |
| 2910 void Assembler::GrowBuffer(int needed) { |
| 2911 if (!own_buffer_) FATAL("external code buffer is too small"); |
| 2912 |
| 2913 // Compute new buffer size. |
| 2914 CodeDesc desc; // the new buffer |
| 2915 if (buffer_size_ < 4 * KB) { |
| 2916 desc.buffer_size = 4 * KB; |
| 2917 } else if (buffer_size_ < 1 * MB) { |
| 2918 desc.buffer_size = 2 * buffer_size_; |
| 2919 } else { |
| 2920 desc.buffer_size = buffer_size_ + 1 * MB; |
| 2921 } |
| 2922 int space = buffer_space() + (desc.buffer_size - buffer_size_); |
| 2923 if (space < needed) { |
| 2924 desc.buffer_size += needed - space; |
| 2925 } |
| 2926 CHECK_GT(desc.buffer_size, 0); // no overflow |
| 2927 |
| 2928 // Set up new buffer. |
| 2929 desc.buffer = NewArray<byte>(desc.buffer_size); |
| 2930 desc.origin = this; |
| 2931 |
| 2932 desc.instr_size = pc_offset(); |
| 2933 desc.reloc_size = (buffer_ + buffer_size_) - reloc_info_writer.pos(); |
| 2934 |
| 2935 // Copy the data. |
| 2936 intptr_t pc_delta = desc.buffer - buffer_; |
| 2937 intptr_t rc_delta = |
| 2938 (desc.buffer + desc.buffer_size) - (buffer_ + buffer_size_); |
| 2939 memmove(desc.buffer, buffer_, desc.instr_size); |
| 2940 memmove(reloc_info_writer.pos() + rc_delta, reloc_info_writer.pos(), |
| 2941 desc.reloc_size); |
| 2942 |
| 2943 // Switch buffers. |
| 2944 DeleteArray(buffer_); |
| 2945 buffer_ = desc.buffer; |
| 2946 buffer_size_ = desc.buffer_size; |
| 2947 pc_ += pc_delta; |
| 2948 reloc_info_writer.Reposition(reloc_info_writer.pos() + rc_delta, |
| 2949 reloc_info_writer.last_pc() + pc_delta); |
| 2950 |
| 2951 // None of our relocation types are pc relative pointing outside the code |
| 2952 // buffer nor pc absolute pointing inside the code buffer, so there is no need |
| 2953 // to relocate any emitted relocation entries. |
| 2954 } |
| 2955 |
| 2956 void Assembler::db(uint8_t data) { |
| 2957 CheckBuffer(); |
| 2958 *reinterpret_cast<uint8_t*>(pc_) = data; |
| 2959 pc_ += sizeof(uint8_t); |
| 2960 } |
| 2961 |
| 2962 void Assembler::dd(uint32_t data) { |
| 2963 CheckBuffer(); |
| 2964 *reinterpret_cast<uint32_t*>(pc_) = data; |
| 2965 pc_ += sizeof(uint32_t); |
| 2966 } |
| 2967 |
| 2968 void Assembler::dq(uint64_t value) { |
| 2969 CheckBuffer(); |
| 2970 *reinterpret_cast<uint64_t*>(pc_) = value; |
| 2971 pc_ += sizeof(uint64_t); |
| 2972 } |
| 2973 |
| 2974 void Assembler::dp(uintptr_t data) { |
| 2975 CheckBuffer(); |
| 2976 *reinterpret_cast<uintptr_t*>(pc_) = data; |
| 2977 pc_ += sizeof(uintptr_t); |
| 2978 } |
| 2979 |
| 2980 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
| 2981 if (RelocInfo::IsNone(rmode) || |
| 2982 // Don't record external references unless the heap will be serialized. |
| 2983 (rmode == RelocInfo::EXTERNAL_REFERENCE && !serializer_enabled() && |
| 2984 !emit_debug_code())) { |
| 2985 return; |
| 2986 } |
| 2987 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { |
| 2988 data = RecordedAstId().ToInt(); |
| 2989 ClearRecordedAstId(); |
| 2990 } |
| 2991 DeferredRelocInfo rinfo(pc_offset(), rmode, data); |
| 2992 relocations_.push_back(rinfo); |
| 2993 } |
| 2994 |
| 2995 void Assembler::emit_label_addr(Label* label) { |
| 2996 CheckBuffer(); |
| 2997 RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
| 2998 int position = link(label); |
| 2999 DCHECK(label->is_bound()); |
| 3000 // Keep internal references relative until EmitRelocations. |
| 3001 dp(position); |
| 3002 } |
| 3003 |
| 3004 void Assembler::EmitRelocations() { |
| 3005 EnsureSpaceFor(relocations_.size() * kMaxRelocSize); |
| 3006 |
| 3007 for (std::vector<DeferredRelocInfo>::iterator it = relocations_.begin(); |
| 3008 it != relocations_.end(); it++) { |
| 3009 RelocInfo::Mode rmode = it->rmode(); |
| 3010 Address pc = buffer_ + it->position(); |
| 3011 Code* code = NULL; |
| 3012 RelocInfo rinfo(isolate(), pc, rmode, it->data(), code); |
| 3013 |
| 3014 // Fix up internal references now that they are guaranteed to be bound. |
| 3015 if (RelocInfo::IsInternalReference(rmode)) { |
| 3016 // Jump table entry |
| 3017 intptr_t pos = reinterpret_cast<intptr_t>(Memory::Address_at(pc)); |
| 3018 Memory::Address_at(pc) = buffer_ + pos; |
| 3019 } else if (RelocInfo::IsInternalReferenceEncoded(rmode)) { |
| 3020 // mov sequence |
| 3021 intptr_t pos = reinterpret_cast<intptr_t>(target_address_at(pc, code)); |
| 3022 set_target_address_at(isolate(), pc, code, buffer_ + pos, |
| 3023 SKIP_ICACHE_FLUSH); |
| 3024 } |
| 3025 |
| 3026 reloc_info_writer.Write(&rinfo); |
| 3027 } |
| 3028 |
| 3029 reloc_info_writer.Finish(); |
| 3030 } |
| 3031 |
| 3032 } // namespace internal |
| 3033 } // namespace v8 |
| 3034 #endif // V8_TARGET_ARCH_S390 |
OLD | NEW |