143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin/* 243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Copyright (C) 2011 The Android Open Source Project 343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Licensed under the Apache License, Version 2.0 (the "License"); 543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * you may not use this file except in compliance with the License. 643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * You may obtain a copy of the License at 743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * http://www.apache.org/licenses/LICENSE-2.0 943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 1043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Unless required by applicable law or agreed to in writing, software 1143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * distributed under the License is distributed on an "AS IS" BASIS, 1243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * See the License for the specific language governing permissions and 1443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * limitations under the License. 1543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */ 1643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 1743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin#include "codegen_arm64.h" 180b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe 190b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "arm64_lir.h" 200b9203e7996ee1856f620f95d95d8a273c43a3dfAndreas Gampe#include "base/logging.h" 2143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin#include "dex/quick/mir_to_lir-inl.h" 22b5860fb459f1ed71f39d8a87b45bee6727d79fe8buzbee#include "dex/reg_storage_eq.h" 2343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 2443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinnamespace art { 2543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 26e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin/* This file contains codegen for the A64 ISA. */ 27e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 282eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescuint32_t Arm64Mir2Lir::EncodeImmSingle(uint32_t bits) { 29e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin /* 30e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * Valid values will have the form: 31e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 32e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * aBbb.bbbc.defg.h000.0000.0000.0000.0000 33e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 34e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * where B = not(b). In other words, if b == 1, then B == 0 and viceversa. 35e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin */ 36e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 37e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bits[19..0] are cleared. 38e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if ((bits & 0x0007ffff) != 0) 3943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return -1; 40e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 41e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bits[29..25] are all set or all cleared. 42e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t b_pattern = (bits >> 16) & 0x3e00; 43e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (b_pattern != 0 && b_pattern != 0x3e00) 44e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return -1; 45e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 46e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit[30] and bit[29] are opposite. 47e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (((bits ^ (bits << 1)) & 0x40000000) == 0) 48e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return -1; 49e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 50e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bits: aBbb.bbbc.defg.h000.0000.0000.0000.0000 51e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit7: a000.0000 52e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t bit7 = ((bits >> 31) & 0x1) << 7; 53e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit6: 0b00.0000 54e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t bit6 = ((bits >> 29) & 0x1) << 6; 55e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit5_to_0: 00cd.efgh 56e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t bit5_to_0 = (bits >> 19) & 0x3f; 57e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return (bit7 | bit6 | bit5_to_0); 5843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 5943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 602eba1fa7e9e5f91e18ae3778d529520bd2c78d55Serban Constantinescuint32_t Arm64Mir2Lir::EncodeImmDouble(uint64_t bits) { 61e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin /* 62e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * Valid values will have the form: 63e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 64e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000 65e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 0000.0000.0000.0000.0000.0000.0000.0000 66e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 67e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * where B = not(b). 68e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin */ 69e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 70e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bits[47..0] are cleared. 71e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if ((bits & UINT64_C(0xffffffffffff)) != 0) 7243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return -1; 73e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 74e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bits[61..54] are all set or all cleared. 75e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t b_pattern = (bits >> 48) & 0x3fc0; 76e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (b_pattern != 0 && b_pattern != 0x3fc0) 77e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return -1; 78e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 79e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit[62] and bit[61] are opposite. 80e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (((bits ^ (bits << 1)) & UINT64_C(0x4000000000000000)) == 0) 81e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return -1; 82e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 83e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit7: a000.0000 84e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t bit7 = ((bits >> 63) & 0x1) << 7; 85e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit6: 0b00.0000 86e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t bit6 = ((bits >> 61) & 0x1) << 6; 87e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bit5_to_0: 00cd.efgh 88e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint32_t bit5_to_0 = (bits >> 48) & 0x3f; 89e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return (bit7 | bit6 | bit5_to_0); 9043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 9143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 9263999683329612292d534e6be09dbde9480f1250Serban Constantinescusize_t Arm64Mir2Lir::GetLoadStoreSize(LIR* lir) { 9363999683329612292d534e6be09dbde9480f1250Serban Constantinescu bool opcode_is_wide = IS_WIDE(lir->opcode); 944163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = UNWIDE(lir->opcode); 9563999683329612292d534e6be09dbde9480f1250Serban Constantinescu DCHECK(!IsPseudoLirOp(opcode)); 964163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin const A64EncodingMap *encoder = &EncodingMap[opcode]; 9763999683329612292d534e6be09dbde9480f1250Serban Constantinescu uint32_t bits = opcode_is_wide ? encoder->xskeleton : encoder->wskeleton; 9863999683329612292d534e6be09dbde9480f1250Serban Constantinescu return (bits >> 30); 9963999683329612292d534e6be09dbde9480f1250Serban Constantinescu} 10063999683329612292d534e6be09dbde9480f1250Serban Constantinescu 10163999683329612292d534e6be09dbde9480f1250Serban Constantinescusize_t Arm64Mir2Lir::GetInstructionOffset(LIR* lir) { 10263999683329612292d534e6be09dbde9480f1250Serban Constantinescu size_t offset = lir->operands[2]; 10363999683329612292d534e6be09dbde9480f1250Serban Constantinescu uint64_t check_flags = GetTargetInstFlags(lir->opcode); 10463999683329612292d534e6be09dbde9480f1250Serban Constantinescu DCHECK((check_flags & IS_LOAD) || (check_flags & IS_STORE)); 10563999683329612292d534e6be09dbde9480f1250Serban Constantinescu if (check_flags & SCALED_OFFSET_X0) { 10663999683329612292d534e6be09dbde9480f1250Serban Constantinescu DCHECK(check_flags & IS_TERTIARY_OP); 10763999683329612292d534e6be09dbde9480f1250Serban Constantinescu offset = offset * (1 << GetLoadStoreSize(lir)); 10863999683329612292d534e6be09dbde9480f1250Serban Constantinescu } 10963999683329612292d534e6be09dbde9480f1250Serban Constantinescu return offset; 11063999683329612292d534e6be09dbde9480f1250Serban Constantinescu} 11163999683329612292d534e6be09dbde9480f1250Serban Constantinescu 112c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo FranchinLIR* Arm64Mir2Lir::LoadFPConstantValue(RegStorage r_dest, int32_t value) { 113c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(r_dest.IsSingle()); 11443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (value == 0) { 115c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return NewLIR2(kA64Fmov2sw, r_dest.GetReg(), rwzr); 11643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } else { 117e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int32_t encoded_imm = EncodeImmSingle((uint32_t)value); 11843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (encoded_imm >= 0) { 119c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return NewLIR2(kA64Fmov2fI, r_dest.GetReg(), encoded_imm); 12043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 12143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 122e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 12343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LIR* data_target = ScanLiteralPool(literal_list_, value, 0); 1242cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (data_target == nullptr) { 125f987927a68d0489970c1eca6a32fd02ca9913357Andreas Gampe // Wide, as we need 8B alignment. 126f987927a68d0489970c1eca6a32fd02ca9913357Andreas Gampe data_target = AddWideData(&literal_list_, value, 0); 12743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 128e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 1298dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 130e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kA64Ldr2fp, 131c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin r_dest.GetReg(), 0, 0, 0, 0, data_target); 13243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin AppendLIR(load_pc_rel); 13343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return load_pc_rel; 13443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 13543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 136c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo FranchinLIR* Arm64Mir2Lir::LoadFPConstantValueWide(RegStorage r_dest, int64_t value) { 137c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(r_dest.IsDouble()); 138e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (value == 0) { 139c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return NewLIR2(kA64Fmov2Sx, r_dest.GetReg(), rxzr); 140e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 141e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int32_t encoded_imm = EncodeImmDouble(value); 142e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (encoded_imm >= 0) { 1434163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin return NewLIR2(WIDE(kA64Fmov2fI), r_dest.GetReg(), encoded_imm); 14443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 145e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 146e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 147e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // No short form - load from the literal pool. 148e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int32_t val_lo = Low32Bits(value); 149e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int32_t val_hi = High32Bits(value); 150e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi); 1512cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (data_target == nullptr) { 152e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin data_target = AddWideData(&literal_list_, val_lo, val_hi); 153e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 154e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 1558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 1564163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin LIR* load_pc_rel = RawLIR(current_dalvik_offset_, WIDE(kA64Ldr2fp), 157c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin r_dest.GetReg(), 0, 0, 0, 0, data_target); 158e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin AppendLIR(load_pc_rel); 159e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return load_pc_rel; 16043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 16143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 162e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinstatic int CountLeadingZeros(bool is_wide, uint64_t value) { 163c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return (is_wide) ? __builtin_clzll(value) : __builtin_clz((uint32_t)value); 164e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin} 165e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 166e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinstatic int CountTrailingZeros(bool is_wide, uint64_t value) { 167c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return (is_wide) ? __builtin_ctzll(value) : __builtin_ctz((uint32_t)value); 168e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin} 169e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 170e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinstatic int CountSetBits(bool is_wide, uint64_t value) { 171e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return ((is_wide) ? 172e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu __builtin_popcountll(value) : __builtin_popcount((uint32_t)value)); 173e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin} 174e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 175e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin/** 176e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @brief Try encoding an immediate in the form required by logical instructions. 177e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 178e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @param is_wide Whether @p value is a 64-bit (as opposed to 32-bit) value. 179e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @param value An integer to be encoded. This is interpreted as 64-bit if @p is_wide is true and as 180e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * 32-bit if @p is_wide is false. 181e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @return A non-negative integer containing the encoded immediate or -1 if the encoding failed. 182e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * @note This is the inverse of Arm64Mir2Lir::DecodeLogicalImmediate(). 18343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */ 184e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinint Arm64Mir2Lir::EncodeLogicalImmediate(bool is_wide, uint64_t value) { 185e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned n, imm_s, imm_r; 186e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 187e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Logical immediates are encoded using parameters n, imm_s and imm_r using 188e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // the following table: 189e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 190e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // N imms immr size S R 191e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) 192e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) 193e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) 194e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) 195e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) 196e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 0 11110s xxxxxr 2 UInt(s) UInt(r) 197e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // (s bits must not be all set) 198e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 199e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // A pattern is constructed of size bits, where the least significant S+1 200e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // bits are set. The pattern is rotated right by R, and repeated across a 201e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 32 or 64-bit value, depending on destination register width. 202e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 203e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // To test if an arbitary immediate can be encoded using this scheme, an 204e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // iterative algorithm is used. 205e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 206e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 207e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 1. If the value has all set or all clear bits, it can't be encoded. 208e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (value == 0 || value == ~UINT64_C(0) || 209e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin (!is_wide && (uint32_t)value == ~UINT32_C(0))) { 210e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return -1; 211e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 212e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 213e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned lead_zero = CountLeadingZeros(is_wide, value); 214e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned lead_one = CountLeadingZeros(is_wide, ~value); 215e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned trail_zero = CountTrailingZeros(is_wide, value); 216e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned trail_one = CountTrailingZeros(is_wide, ~value); 217e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned set_bits = CountSetBits(is_wide, value); 218e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 219e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // The fixed bits in the immediate s field. 220e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // If width == 64 (X reg), start at 0xFFFFFF80. 221e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit 222e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // widths won't be executed. 223e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin unsigned width = (is_wide) ? 64 : 32; 224e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int imm_s_fixed = (is_wide) ? -128 : -64; 225e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int imm_s_mask = 0x3f; 226e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 227e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin for (;;) { 228e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 2. If the value is two bits wide, it can be encoded. 229e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (width == 2) { 230e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin n = 0; 231e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin imm_s = 0x3C; 232e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin imm_r = (value & 3) - 1; 233e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin break; 234e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 235e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 236e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin n = (width == 64) ? 1 : 0; 237e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask); 238e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if ((lead_zero + set_bits) == width) { 239e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin imm_r = 0; 240e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 241e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one; 242e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 243e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 244e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 3. If the sum of leading zeros, trailing zeros and set bits is 245e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // equal to the bit width of the value, it can be encoded. 246e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (lead_zero + trail_zero + set_bits == width) { 247e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin break; 248e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 249e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 250e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 4. If the sum of leading ones, trailing ones and unset bits in the 251e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // value is equal to the bit width of the value, it can be encoded. 252e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (lead_one + trail_one + (width - set_bits) == width) { 253e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin break; 254e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 255e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 256e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 5. If the most-significant half of the bitwise value is equal to 257e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // the least-significant half, return to step 2 using the 258e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // least-significant half of the value. 259e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint64_t mask = (UINT64_C(1) << (width >> 1)) - 1; 260e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if ((value & mask) == ((value >> (width >> 1)) & mask)) { 261e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin width >>= 1; 262e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin set_bits >>= 1; 263e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin imm_s_fixed >>= 1; 264e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin continue; 265e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 266e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 267e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 6. Otherwise, the value can't be encoded. 268e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return -1; 269e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 270e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 271e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return (n << 12 | imm_r << 6 | imm_s); 27243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 27343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 274c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// Maximum number of instructions to use for encoding the immediate. 275c763e350da562b0c6bebf10599588d4901140e45Matteo Franchinstatic const int max_num_ops_per_const_load = 2; 276c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin 277c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin/** 278c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @brief Return the number of fast halfwords in the given uint64_t integer. 279c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @details The input integer is split into 4 halfwords (bits 0-15, 16-31, 32-47, 48-63). The 280c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * number of fast halfwords (halfwords that are either 0 or 0xffff) is returned. See below for 281c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * a more accurate description. 282c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @param value The input 64-bit integer. 283c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * @return Return @c retval such that (retval & 0x7) is the maximum between n and m, where n is 284c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * the number of halfwords with all bits unset (0) and m is the number of halfwords with all bits 285c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin * set (0xffff). Additionally (retval & 0x8) is set when m > n. 286c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin */ 287c763e350da562b0c6bebf10599588d4901140e45Matteo Franchinstatic int GetNumFastHalfWords(uint64_t value) { 288c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin unsigned int num_0000_halfwords = 0; 289c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin unsigned int num_ffff_halfwords = 0; 290c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin for (int shift = 0; shift < 64; shift += 16) { 291c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin uint16_t halfword = static_cast<uint16_t>(value >> shift); 292c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (halfword == 0) 293c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin num_0000_halfwords++; 294c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin else if (halfword == UINT16_C(0xffff)) 295c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin num_ffff_halfwords++; 296c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 297c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (num_0000_halfwords >= num_ffff_halfwords) { 298c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin DCHECK_LE(num_0000_halfwords, 4U); 299c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return num_0000_halfwords; 300c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } else { 301c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin DCHECK_LE(num_ffff_halfwords, 4U); 302c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return num_ffff_halfwords | 0x8; 303c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 304c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin} 305c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin 306c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// The InexpensiveConstantXXX variants below are used in the promotion algorithm to determine how a 307c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// constant is considered for promotion. If the constant is "inexpensive" then the promotion 308c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// algorithm will give it a low priority for promotion, even when it is referenced many times in 309c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// the code. 310c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin 3116a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersbool Arm64Mir2Lir::InexpensiveConstantInt(int32_t value ATTRIBUTE_UNUSED) { 312c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // A 32-bit int can always be loaded with 2 instructions (and without using the literal pool). 313c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // We therefore return true and give it a low priority for promotion. 314c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return true; 31543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 31643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 31743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantFloat(int32_t value) { 31843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return EncodeImmSingle(value) >= 0; 31943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 32043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 32143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantLong(int64_t value) { 322c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin int num_slow_halfwords = 4 - (GetNumFastHalfWords(value) & 0x7); 323c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (num_slow_halfwords <= max_num_ops_per_const_load) { 324c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return true; 325c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 326c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return (EncodeLogicalImmediate(/*is_wide=*/true, value) >= 0); 32743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 32843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 32943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantDouble(int64_t value) { 33043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return EncodeImmDouble(value) >= 0; 33143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 33243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 333c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// The InexpensiveConstantXXX variants below are used to determine which A64 instructions to use 334c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin// when one of the operands is an immediate (e.g. register version or immediate version of add). 335c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin 336c763e350da562b0c6bebf10599588d4901140e45Matteo Franchinbool Arm64Mir2Lir::InexpensiveConstantInt(int32_t value, Instruction::Code opcode) { 337c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin switch (opcode) { 338c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::IF_EQ: 339c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::IF_NE: 340c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::IF_LT: 341c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::IF_GE: 342c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::IF_GT: 343c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::IF_LE: 344c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::ADD_INT: 345c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::ADD_INT_2ADDR: 346c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::SUB_INT: 347c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::SUB_INT_2ADDR: 348c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // The code below is consistent with the implementation of OpRegRegImm(). 349c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin { 350b504d2f89fdd5c01816bcbad752797cb78de0e99buzbee uint32_t abs_value = (value == INT_MIN) ? value : std::abs(value); 351c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (abs_value < 0x1000) { 352c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return true; 353c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) { 354c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return true; 355c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 356c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return false; 357c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 358c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::SHL_INT: 359c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::SHL_INT_2ADDR: 360c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::SHR_INT: 361c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::SHR_INT_2ADDR: 362c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::USHR_INT: 363c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::USHR_INT_2ADDR: 364c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return true; 365c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::AND_INT: 366c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::AND_INT_2ADDR: 367c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::AND_INT_LIT16: 368c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::AND_INT_LIT8: 369c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::OR_INT: 370c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::OR_INT_2ADDR: 371c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::OR_INT_LIT16: 372c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::OR_INT_LIT8: 373c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::XOR_INT: 374c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::XOR_INT_2ADDR: 375c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::XOR_INT_LIT16: 376c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case Instruction::XOR_INT_LIT8: 377c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (value == 0 || value == INT32_C(-1)) { 378c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return true; 379c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 380c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return (EncodeLogicalImmediate(/*is_wide=*/false, value) >= 0); 381c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin default: 382c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return false; 383c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 384c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin} 385c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin 38643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin/* 387e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * Load a immediate using one single instruction when possible; otherwise 388e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin * use a pair of movz and movk instructions. 38943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 39043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * No additional register clobbering operation performed. Use this version when 39143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 1) r_dest is freshly returned from AllocTemp or 39243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * 2) The codegen is under fixed register usage 39343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */ 39443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::LoadConstantNoClobber(RegStorage r_dest, int value) { 39543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LIR* res; 39643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 39743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (r_dest.IsFloat()) { 398c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return LoadFPConstantValue(r_dest, value); 399c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 400c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 401c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin if (r_dest.Is64Bit()) { 402c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return LoadConstantWide(r_dest, value); 40343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 40443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 405e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Loading SP/ZR with an immediate is not supported. 406c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(!A64_REG_IS_SP(r_dest.GetReg())); 407c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(!A64_REG_IS_ZR(r_dest.GetReg())); 408e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 409e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Compute how many movk, movz instructions are needed to load the value. 410e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint16_t high_bits = High16Bits(value); 411e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint16_t low_bits = Low16Bits(value); 412e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 413e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin bool low_fast = ((uint16_t)(low_bits + 1) <= 1); 414e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin bool high_fast = ((uint16_t)(high_bits + 1) <= 1); 415e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 416e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (LIKELY(low_fast || high_fast)) { 417e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // 1 instruction is enough to load the immediate. 418e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (LIKELY(low_bits == high_bits)) { 419e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Value is either 0 or -1: we can just use wzr. 4204163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = LIKELY(low_bits == 0) ? kA64Mov2rr : kA64Mvn2rr; 421e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin res = NewLIR2(opcode, r_dest.GetReg(), rwzr); 422e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 423e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uint16_t uniform_bits, useful_bits; 424e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int shift; 425e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 426e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (LIKELY(high_fast)) { 427e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin shift = 0; 428e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uniform_bits = high_bits; 429e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin useful_bits = low_bits; 430e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 431e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin shift = 1; 432e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin uniform_bits = low_bits; 433e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin useful_bits = high_bits; 434e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 435e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 436e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (UNLIKELY(uniform_bits != 0)) { 437e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin res = NewLIR3(kA64Movn3rdM, r_dest.GetReg(), ~useful_bits, shift); 438e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 439e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin res = NewLIR3(kA64Movz3rdM, r_dest.GetReg(), useful_bits, shift); 440e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 441e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 442e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 443e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // movk, movz require 2 instructions. Try detecting logical immediates. 444e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int log_imm = EncodeLogicalImmediate(/*is_wide=*/false, value); 445e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (log_imm >= 0) { 446e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin res = NewLIR3(kA64Orr3Rrl, r_dest.GetReg(), rwzr, log_imm); 447e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 448e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Use 2 instructions. 449e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin res = NewLIR3(kA64Movz3rdM, r_dest.GetReg(), low_bits, 0); 450e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin NewLIR3(kA64Movk3rdM, r_dest.GetReg(), high_bits, 1); 451e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 45243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 453e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 45443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return res; 45543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 45643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 457c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin// TODO: clean up the names. LoadConstantWide() should really be LoadConstantNoClobberWide(). 458c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo FranchinLIR* Arm64Mir2Lir::LoadConstantWide(RegStorage r_dest, int64_t value) { 459c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin if (r_dest.IsFloat()) { 460c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return LoadFPConstantValueWide(r_dest, value); 461c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 462c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 463c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(r_dest.Is64Bit()); 464c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 465c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // Loading SP/ZR with an immediate is not supported. 466c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(!A64_REG_IS_SP(r_dest.GetReg())); 467c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin DCHECK(!A64_REG_IS_ZR(r_dest.GetReg())); 468c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 469c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin if (LIKELY(value == INT64_C(0) || value == INT64_C(-1))) { 470c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // value is either 0 or -1: we can just use xzr. 4714163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = LIKELY(value == 0) ? WIDE(kA64Mov2rr) : WIDE(kA64Mvn2rr); 472c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return NewLIR2(opcode, r_dest.GetReg(), rxzr); 473c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 474c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 475c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // At least one in value's halfwords is not 0x0, nor 0xffff: find out how many. 476c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin uint64_t uvalue = static_cast<uint64_t>(value); 477c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin int num_fast_halfwords = GetNumFastHalfWords(uvalue); 478c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin int num_slow_halfwords = 4 - (num_fast_halfwords & 0x7); 479c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin bool more_ffff_halfwords = (num_fast_halfwords & 0x8) != 0; 480c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 481c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (num_slow_halfwords > 1) { 482c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // A single movz/movn is not enough. Try the logical immediate route. 483c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin int log_imm = EncodeLogicalImmediate(/*is_wide=*/true, value); 484c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin if (log_imm >= 0) { 485c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return NewLIR3(WIDE(kA64Orr3Rrl), r_dest.GetReg(), rxzr, log_imm); 486c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 487c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 488c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 489c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (num_slow_halfwords <= max_num_ops_per_const_load) { 490c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // We can encode the number using a movz/movn followed by one or more movk. 4914163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode op; 492c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin uint16_t background; 493c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin LIR* res = nullptr; 494c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 495c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // Decide whether to use a movz or a movn. 496c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (more_ffff_halfwords) { 497c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin op = WIDE(kA64Movn3rdM); 498c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin background = 0xffff; 499c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } else { 500c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin op = WIDE(kA64Movz3rdM); 501c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin background = 0; 502c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 503c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 504c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // Emit the first instruction (movz, movn). 505c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin int shift; 506c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin for (shift = 0; shift < 4; shift++) { 507c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin uint16_t halfword = static_cast<uint16_t>(uvalue >> (shift << 4)); 508c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin if (halfword != background) { 509c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin res = NewLIR3(op, r_dest.GetReg(), halfword ^ background, shift); 510c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin break; 511c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 512c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 513c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 514c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // Emit the movk instructions. 515c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin for (shift++; shift < 4; shift++) { 516c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin uint16_t halfword = static_cast<uint16_t>(uvalue >> (shift << 4)); 517c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin if (halfword != background) { 518c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin NewLIR3(WIDE(kA64Movk3rdM), r_dest.GetReg(), halfword, shift); 519c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 520c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 521c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return res; 522c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 523c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 524c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin // Use the literal pool. 525c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin int32_t val_lo = Low32Bits(value); 526c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin int32_t val_hi = High32Bits(value); 527c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi); 5282cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (data_target == nullptr) { 529c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin data_target = AddWideData(&literal_list_, val_lo, val_hi); 530c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin } 531c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 532c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin ScopedMemRefType mem_ref_type(this, ResourceMask::kLiteral); 533c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin LIR *res = RawLIR(current_dalvik_offset_, WIDE(kA64Ldr2rp), 534c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin r_dest.GetReg(), 0, 0, 0, 0, data_target); 535c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin AppendLIR(res); 536c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin return res; 537c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin} 538c41e6dc89ec6593e9af9af524f2ec7be6e2d24a4Matteo Franchin 53943ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpUnconditionalBranch(LIR* target) { 540e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LIR* res = NewLIR1(kA64B1t, 0 /* offset to be patched during assembly */); 54143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin res->target = target; 54243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return res; 54343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 54443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 54543ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpCondBranch(ConditionCode cc, LIR* target) { 546e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LIR* branch = NewLIR2(kA64B2ct, ArmConditionEncoding(cc), 547e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 0 /* offset to be patched */); 54843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin branch->target = target; 54943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return branch; 55043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 55143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 55243ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpReg(OpKind op, RegStorage r_dest_src) { 5534163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 55443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin switch (op) { 55543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpBlx: 556e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Blr1x; 55743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 55843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 55943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad opcode " << op; 56043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 56143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return NewLIR1(opcode, r_dest_src.GetReg()); 56243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 56343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 564bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo FranchinLIR* Arm64Mir2Lir::OpRegRegShift(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, int shift) { 5654163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode wide = (r_dest_src1.Is64Bit()) ? WIDE(0) : UNWIDE(0); 566bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin CHECK_EQ(r_dest_src1.Is64Bit(), r_src2.Is64Bit()); 5674163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 568e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 569bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin switch (op) { 57043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpCmn: 571bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin opcode = kA64Cmn3rro; 57243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 57343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpCmp: 574bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin opcode = kA64Cmp3rro; 57543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 57643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpMov: 577e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Mov2rr; 57843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 57943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpMvn: 580e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Mvn2rr; 58143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 58243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpNeg: 583e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Neg3rro; 58443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 58543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpTst: 586e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Tst3rro; 58743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 58843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpRev: 58943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin DCHECK_EQ(shift, 0); 590e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Binary, but rm is encoded twice. 591169489b4f4be8c5dd880ba6f152948324d22ff79Serban Constantinescu return NewLIR2(kA64Rev2rr | wide, r_dest_src1.GetReg(), r_src2.GetReg()); 59243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpRevsh: 593e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Binary, but rm is encoded twice. 594a3fe7422d7ce8bfb01f95decef45f91a44d39264Zheng Xu NewLIR2(kA64Rev162rr | wide, r_dest_src1.GetReg(), r_src2.GetReg()); 595a3fe7422d7ce8bfb01f95decef45f91a44d39264Zheng Xu // "sxth r1, r2" is "sbfm r1, r2, #0, #15" 596a3fe7422d7ce8bfb01f95decef45f91a44d39264Zheng Xu return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_dest_src1.GetReg(), 0, 15); 59743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOp2Byte: 598e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(shift, ENCODE_NO_SHIFT); 599e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // "sbfx r1, r2, #imm1, #imm2" is "sbfm r1, r2, #imm1, #(imm1 + imm2 - 1)". 600e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // For now we use sbfm directly. 601bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 7); 60243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOp2Short: 603e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(shift, ENCODE_NO_SHIFT); 604e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // For now we use sbfm rather than its alias, sbfx. 605bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin return NewLIR4(kA64Sbfm4rrdd | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 15); 60643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOp2Char: 607e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // "ubfx r1, r2, #imm1, #imm2" is "ubfm r1, r2, #imm1, #(imm1 + imm2 - 1)". 608e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // For now we use ubfm directly. 609e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(shift, ENCODE_NO_SHIFT); 610bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin return NewLIR4(kA64Ubfm4rrdd | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 0, 15); 61143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 612ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu return OpRegRegRegShift(op, r_dest_src1, r_dest_src1, r_src2, shift); 61343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 614e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 61543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin DCHECK(!IsPseudoLirOp(opcode)); 61643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (EncodingMap[opcode].flags & IS_BINARY_OP) { 617e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(shift, ENCODE_NO_SHIFT); 618bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin return NewLIR2(opcode | wide, r_dest_src1.GetReg(), r_src2.GetReg()); 61943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) { 6204163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64EncodingKind kind = EncodingMap[opcode].field_loc[2].kind; 621bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin if (kind == kFmtShift) { 622bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin return NewLIR3(opcode | wide, r_dest_src1.GetReg(), r_src2.GetReg(), shift); 62343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 62443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 625e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 626e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LOG(FATAL) << "Unexpected encoding operand count"; 6272cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return nullptr; 62843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 62943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 630cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng XuLIR* Arm64Mir2Lir::OpRegRegExtend(OpKind op, RegStorage r_dest_src1, RegStorage r_src2, 631cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu A64RegExtEncodings ext, uint8_t amount) { 6324163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode wide = (r_dest_src1.Is64Bit()) ? WIDE(0) : UNWIDE(0); 6334163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 634f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith 635f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith switch (op) { 636f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith case kOpCmn: 637f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith opcode = kA64Cmn3Rre; 638f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith break; 639f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith case kOpCmp: 640f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith opcode = kA64Cmp3Rre; 641f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith break; 642cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu case kOpAdd: 643cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu // Note: intentional fallthrough 644cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu case kOpSub: 645cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu return OpRegRegRegExtend(op, r_dest_src1, r_dest_src1, r_src2, ext, amount); 646f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith default: 647f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith LOG(FATAL) << "Bad Opcode: " << opcode; 64865b798ea10dd716c1bb3dda029f9bf255435af72Andreas Gampe UNREACHABLE(); 649f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith } 650f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith 651f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith DCHECK(!IsPseudoLirOp(opcode)); 652f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith if (EncodingMap[opcode].flags & IS_TERTIARY_OP) { 6534163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64EncodingKind kind = EncodingMap[opcode].field_loc[2].kind; 654f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith if (kind == kFmtExtend) { 655cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu return NewLIR3(opcode | wide, r_dest_src1.GetReg(), r_src2.GetReg(), 656cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu EncodeExtend(ext, amount)); 657f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith } 658f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith } 659f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith 660f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith LOG(FATAL) << "Unexpected encoding operand count"; 6612cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier return nullptr; 662f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith} 663f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith 66443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegReg(OpKind op, RegStorage r_dest_src1, RegStorage r_src2) { 665f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith /* RegReg operations with SP in first parameter need extended register instruction form. 666cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu * Only CMN, CMP, ADD & SUB instructions are implemented. 667f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith */ 668baa7c88a34fdfd230a2a383c2e388945f4d907b6Zheng Xu if (r_dest_src1 == rs_sp) { 669cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu return OpRegRegExtend(op, r_dest_src1, r_src2, kA64Uxtx, 0); 670f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith } else { 671f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith return OpRegRegShift(op, r_dest_src1, r_src2, ENCODE_NO_SHIFT); 672f8ec48e8eff0050de1451fc8e9c3a71c26d5ce7eStuart Monteith } 67343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 67443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 6756a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersLIR* Arm64Mir2Lir::OpMovRegMem(RegStorage r_dest, RegStorage r_base, int offset, 6766a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers MoveType move_type) { 6776a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(r_dest, r_base, offset, move_type); 67843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin UNIMPLEMENTED(FATAL); 6796a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 68043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 68143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 6826a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersLIR* Arm64Mir2Lir::OpMovMemReg(RegStorage r_base, int offset, RegStorage r_src, 6836a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers MoveType move_type) { 6846a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(r_base, offset, r_src, move_type); 68543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin UNIMPLEMENTED(FATAL); 68643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return nullptr; 68743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 68843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 68943ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpCondRegReg(OpKind op, ConditionCode cc, RegStorage r_dest, RegStorage r_src) { 6906a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(op, cc, r_dest, r_src); 691e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LOG(FATAL) << "Unexpected use of OpCondRegReg for Arm64"; 6926a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 69343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 69443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 695ed65c5e982705defdb597d94d1aa3f2997239c9bSerban ConstantinescuLIR* Arm64Mir2Lir::OpRegRegRegShift(OpKind op, RegStorage r_dest, RegStorage r_src1, 696ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu RegStorage r_src2, int shift) { 6974163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 698e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 699bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin switch (op) { 70043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAdd: 701e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Add4rrro; 70243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 70343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpSub: 704e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Sub4rrro; 70543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 706e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // case kOpRsub: 707e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // opcode = kA64RsubWWW; 708e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // break; 70943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAdc: 710e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Adc3rrr; 71143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 71243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAnd: 713e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64And4rrro; 71443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 71543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpXor: 716e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Eor4rrro; 71743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 71843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpMul: 719e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Mul3rrr; 72043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 72143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpDiv: 722e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Sdiv3rrr; 72343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 72443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpOr: 725e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Orr4rrro; 72643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 72743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpSbc: 728e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Sbc3rrr; 72943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 73043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpLsl: 731e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Lsl3rrr; 73243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 73343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpLsr: 734e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Lsr3rrr; 73543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 73643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAsr: 737e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Asr3rrr; 73843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 73943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpRor: 740e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ror3rrr; 74143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 74243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 74343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad opcode: " << op; 74443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 74543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 746e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 747e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // The instructions above belong to two kinds: 748e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // - 4-operands instructions, where the last operand is a shift/extend immediate, 749e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // - 3-operands instructions with no shift/extend. 7504163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode widened_opcode = r_dest.Is64Bit() ? WIDE(opcode) : opcode; 751ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu CHECK_EQ(r_dest.Is64Bit(), r_src1.Is64Bit()); 752ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu CHECK_EQ(r_dest.Is64Bit(), r_src2.Is64Bit()); 75343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (EncodingMap[opcode].flags & IS_QUAD_OP) { 7540955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(!IsExtendEncoding(shift)); 755ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu return NewLIR4(widened_opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), shift); 75643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } else { 75743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP); 758e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(shift, ENCODE_NO_SHIFT); 759ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu return NewLIR3(widened_opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg()); 76043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 76143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 76243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 76347b31aa855379471c06735b738396fa76e7c1988Andreas GampeLIR* Arm64Mir2Lir::OpRegRegRegExtend(OpKind op, RegStorage r_dest, RegStorage r_src1, 76447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe RegStorage r_src2, A64RegExtEncodings ext, uint8_t amount) { 7654163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 76647b31aa855379471c06735b738396fa76e7c1988Andreas Gampe 76747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe switch (op) { 76847b31aa855379471c06735b738396fa76e7c1988Andreas Gampe case kOpAdd: 76947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe opcode = kA64Add4RRre; 77047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe break; 77147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe case kOpSub: 77247b31aa855379471c06735b738396fa76e7c1988Andreas Gampe opcode = kA64Sub4RRre; 77347b31aa855379471c06735b738396fa76e7c1988Andreas Gampe break; 77447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe default: 7752c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNIMPLEMENTED(FATAL) << "Unimplemented opcode: " << op; 7762c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers UNREACHABLE(); 77747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe } 7784163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode widened_opcode = r_dest.Is64Bit() ? WIDE(opcode) : opcode; 77947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe 78047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe if (r_dest.Is64Bit()) { 78147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe CHECK(r_src1.Is64Bit()); 78247b31aa855379471c06735b738396fa76e7c1988Andreas Gampe 78347b31aa855379471c06735b738396fa76e7c1988Andreas Gampe // dest determines whether the op is wide or not. Up-convert src2 when necessary. 78447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe // Note: this is not according to aarch64 specifications, but our encoding. 78547b31aa855379471c06735b738396fa76e7c1988Andreas Gampe if (!r_src2.Is64Bit()) { 78647b31aa855379471c06735b738396fa76e7c1988Andreas Gampe r_src2 = As64BitReg(r_src2); 78747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe } 78847b31aa855379471c06735b738396fa76e7c1988Andreas Gampe } else { 78947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe CHECK(!r_src1.Is64Bit()); 79047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe CHECK(!r_src2.Is64Bit()); 79147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe } 79247b31aa855379471c06735b738396fa76e7c1988Andreas Gampe 79347b31aa855379471c06735b738396fa76e7c1988Andreas Gampe // Sanity checks. 79447b31aa855379471c06735b738396fa76e7c1988Andreas Gampe // 1) Amount is in the range 0..4 79547b31aa855379471c06735b738396fa76e7c1988Andreas Gampe CHECK_LE(amount, 4); 79647b31aa855379471c06735b738396fa76e7c1988Andreas Gampe 79747b31aa855379471c06735b738396fa76e7c1988Andreas Gampe return NewLIR4(widened_opcode, r_dest.GetReg(), r_src1.GetReg(), r_src2.GetReg(), 79847b31aa855379471c06735b738396fa76e7c1988Andreas Gampe EncodeExtend(ext, amount)); 79947b31aa855379471c06735b738396fa76e7c1988Andreas Gampe} 80047b31aa855379471c06735b738396fa76e7c1988Andreas Gampe 80143ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegRegReg(OpKind op, RegStorage r_dest, RegStorage r_src1, RegStorage r_src2) { 802ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu return OpRegRegRegShift(op, r_dest, r_src1, r_src2, ENCODE_NO_SHIFT); 80343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 80443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 80543ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegRegImm(OpKind op, RegStorage r_dest, RegStorage r_src1, int value) { 806e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu return OpRegRegImm64(op, r_dest, r_src1, static_cast<int64_t>(value)); 807e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu} 808e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu 809e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng XuLIR* Arm64Mir2Lir::OpRegRegImm64(OpKind op, RegStorage r_dest, RegStorage r_src1, int64_t value) { 81043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LIR* res; 81143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin bool neg = (value < 0); 812b504d2f89fdd5c01816bcbad752797cb78de0e99buzbee uint64_t abs_value = (neg & !(value == LLONG_MIN)) ? -value : value; 8134163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 8144163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode alt_opcode = kA64Brk1d; 815c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin bool is_logical = false; 816bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin bool is_wide = r_dest.Is64Bit(); 8174163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode wide = (is_wide) ? WIDE(0) : UNWIDE(0); 8189f975bfe091e9592a1b6b5b46d224ec04b1183b6Andreas Gampe int info = 0; 81943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 820bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin switch (op) { 821e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kOpLsl: { 822e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // "lsl w1, w2, #imm" is an alias of "ubfm w1, w2, #(-imm MOD 32), #(31-imm)" 8232d41a655f4f0e4b2178bbd7e93901a5ed6eae4a6Zheng Xu // and "lsl x1, x2, #imm" of "ubfm x1, x2, #(-imm MOD 64), #(63-imm)". 824e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // For now, we just use ubfm directly. 8252d41a655f4f0e4b2178bbd7e93901a5ed6eae4a6Zheng Xu int max_value = (is_wide) ? 63 : 31; 826e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR4(kA64Ubfm4rrdd | wide, r_dest.GetReg(), r_src1.GetReg(), 8272d41a655f4f0e4b2178bbd7e93901a5ed6eae4a6Zheng Xu (-value) & max_value, max_value - value); 828e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 82943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpLsr: 830e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR3(kA64Lsr3rrd | wide, r_dest.GetReg(), r_src1.GetReg(), value); 83143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAsr: 832e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR3(kA64Asr3rrd | wide, r_dest.GetReg(), r_src1.GetReg(), value); 83343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpRor: 834e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // "ror r1, r2, #imm" is an alias of "extr r1, r2, r2, #imm". 835e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // For now, we just use extr directly. 836e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR4(kA64Extr4rrrd | wide, r_dest.GetReg(), r_src1.GetReg(), r_src1.GetReg(), 837e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin value); 83843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAdd: 839e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin neg = !neg; 840fc787ecd91127b2c8458afd94e5148e2ae51a1f5Ian Rogers FALLTHROUGH_INTENDED; 84143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpSub: 842e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // Add and sub below read/write sp rather than xzr. 843e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (abs_value < 0x1000) { 844e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = (neg) ? kA64Add4RRdT : kA64Sub4RRdT; 845e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR4(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), abs_value, 0); 846e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) { 847e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = (neg) ? kA64Add4RRdT : kA64Sub4RRdT; 848e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR4(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), abs_value >> 12, 1); 84943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } else { 850903989dae724ec0b186ec98c2afd1e074ed41d4dVladimir Marko alt_opcode = (op == kOpAdd) ? kA64Add4RRre : kA64Sub4RRre; 85147b31aa855379471c06735b738396fa76e7c1988Andreas Gampe info = EncodeExtend(is_wide ? kA64Uxtx : kA64Uxtw, 0); 85243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 85343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 85443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAdc: 855e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin alt_opcode = kA64Adc3rrr; 85643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 85743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpSbc: 858e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin alt_opcode = kA64Sbc3rrr; 85943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 86043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpOr: 861c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin is_logical = true; 862e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Orr3Rrl; 863e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin alt_opcode = kA64Orr4rrro; 86443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 86543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAnd: 866c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin is_logical = true; 867e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64And3Rrl; 868e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin alt_opcode = kA64And4rrro; 86943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 87043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpXor: 871c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin is_logical = true; 872e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Eor3Rrl; 873e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin alt_opcode = kA64Eor4rrro; 87443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 87543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpMul: 87643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin // TUNING: power of 2, shift & add 877e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin alt_opcode = kA64Mul3rrr; 87843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 87943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 88043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad opcode: " << op; 88143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 88243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 883c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (is_logical) { 884c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin int log_imm = EncodeLogicalImmediate(is_wide, value); 885c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (log_imm >= 0) { 886c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return NewLIR3(opcode | wide, r_dest.GetReg(), r_src1.GetReg(), log_imm); 887e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu } else { 888c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // When the immediate is either 0 or ~0, the logical operation can be trivially reduced 889c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // to a - possibly negated - assignment. 890c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (value == 0) { 891c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin switch (op) { 892c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case kOpOr: 893c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case kOpXor: 894c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // Or/Xor by zero reduces to an assignment. 895c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return NewLIR2(kA64Mov2rr | wide, r_dest.GetReg(), r_src1.GetReg()); 896c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin default: 897c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // And by zero reduces to a `mov rdest, xzr'. 898c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin DCHECK(op == kOpAnd); 899c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return NewLIR2(kA64Mov2rr | wide, r_dest.GetReg(), (is_wide) ? rxzr : rwzr); 900c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 901c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } else if (value == INT64_C(-1) 902c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin || (!is_wide && static_cast<uint32_t>(value) == ~UINT32_C(0))) { 903c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin switch (op) { 904c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case kOpAnd: 905c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // And by -1 reduces to an assignment. 906c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return NewLIR2(kA64Mov2rr | wide, r_dest.GetReg(), r_src1.GetReg()); 907c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin case kOpXor: 908c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // Xor by -1 reduces to an `mvn rdest, rsrc'. 909c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return NewLIR2(kA64Mvn2rr | wide, r_dest.GetReg(), r_src1.GetReg()); 910c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin default: 911c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin // Or by -1 reduces to a `mvn rdest, xzr'. 912c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin DCHECK(op == kOpOr); 913c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return NewLIR2(kA64Mvn2rr | wide, r_dest.GetReg(), (is_wide) ? rxzr : rwzr); 914c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 915c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 916e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu } 91743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 918c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin 919c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin RegStorage r_scratch; 920c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (is_wide) { 921c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin r_scratch = AllocTempWide(); 922c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin LoadConstantWide(r_scratch, value); 923c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } else { 924c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin r_scratch = AllocTemp(); 925c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin LoadConstant(r_scratch, value); 926c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin } 927c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin if (EncodingMap[alt_opcode].flags & IS_QUAD_OP) 928c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin res = NewLIR4(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg(), info); 929c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin else 930c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin res = NewLIR3(alt_opcode | wide, r_dest.GetReg(), r_src1.GetReg(), r_scratch.GetReg()); 931c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin FreeTemp(r_scratch); 932c763e350da562b0c6bebf10599588d4901140e45Matteo Franchin return res; 93343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 93443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 93543ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpRegImm(OpKind op, RegStorage r_dest_src1, int value) { 936ed65c5e982705defdb597d94d1aa3f2997239c9bSerban Constantinescu return OpRegImm64(op, r_dest_src1, static_cast<int64_t>(value)); 937e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin} 938e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 939ed65c5e982705defdb597d94d1aa3f2997239c9bSerban ConstantinescuLIR* Arm64Mir2Lir::OpRegImm64(OpKind op, RegStorage r_dest_src1, int64_t value) { 9404163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode wide = (r_dest_src1.Is64Bit()) ? WIDE(0) : UNWIDE(0); 9414163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 9424163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode neg_opcode = kA64Brk1d; 943e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin bool shift; 94443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin bool neg = (value < 0); 945b504d2f89fdd5c01816bcbad752797cb78de0e99buzbee uint64_t abs_value = (neg & !(value == LLONG_MIN)) ? -value : value; 946e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 947e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (LIKELY(abs_value < 0x1000)) { 948e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // abs_value is a 12-bit immediate. 949e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin shift = false; 950e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else if ((abs_value & UINT64_C(0xfff)) == 0 && ((abs_value >> 12) < 0x1000)) { 951e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin // abs_value is a shifted 12-bit immediate. 952e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin shift = true; 953e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin abs_value >>= 12; 954e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu } else if (LIKELY(abs_value < 0x1000000 && (op == kOpAdd || op == kOpSub))) { 955e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu // Note: It is better to use two ADD/SUB instead of loading a number to a temp register. 956e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu // This works for both normal registers and SP. 957e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu // For a frame size == 0x2468, it will be encoded as: 958e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu // sub sp, #0x2000 959e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu // sub sp, #0x468 960e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu if (neg) { 961e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu op = (op == kOpAdd) ? kOpSub : kOpAdd; 962e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu } 963e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu OpRegImm64(op, r_dest_src1, abs_value & (~INT64_C(0xfff))); 964e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu return OpRegImm64(op, r_dest_src1, abs_value & 0xfff); 965e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 966e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu RegStorage r_tmp; 967e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu LIR* res; 968e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu if (IS_WIDE(wide)) { 969e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu r_tmp = AllocTempWide(); 970e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu res = LoadConstantWide(r_tmp, value); 971e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu } else { 972e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu r_tmp = AllocTemp(); 973e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu res = LoadConstant(r_tmp, value); 974e2eb29e98be3ba72cce7da40847ab3d605b9455dZheng Xu } 975e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin OpRegReg(op, r_dest_src1, r_tmp); 976e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin FreeTemp(r_tmp); 977e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return res; 978e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 979e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 980bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin switch (op) { 98143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpAdd: 982e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin neg_opcode = kA64Sub4RRdT; 983e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Add4RRdT; 98443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 98543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpSub: 986e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin neg_opcode = kA64Add4RRdT; 987e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Sub4RRdT; 98843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 98943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kOpCmp: 990e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin neg_opcode = kA64Cmn3RdT; 991e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Cmp3RdT; 99243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 99343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 994e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LOG(FATAL) << "Bad op-kind in OpRegImm: " << op; 99543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 99643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 997e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 998e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (UNLIKELY(neg)) 999e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = neg_opcode; 1000e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 1001e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (EncodingMap[opcode].flags & IS_QUAD_OP) 1002e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR4(opcode | wide, r_dest_src1.GetReg(), r_dest_src1.GetReg(), abs_value, 1003e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin (shift) ? 1 : 0); 1004e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin else 1005e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return NewLIR3(opcode | wide, r_dest_src1.GetReg(), abs_value, (shift) ? 1 : 0); 100643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 100743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 1008e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinint Arm64Mir2Lir::EncodeShift(int shift_type, int amount) { 1009cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu DCHECK_EQ(shift_type & 0x3, shift_type); 1010cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu DCHECK_EQ(amount & 0x3f, amount); 1011c61b3c984c509d5f7c8eb71b853c81a34b5c28efMatteo Franchin return ((shift_type & 0x3) << 7) | (amount & 0x3f); 1012e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin} 1013e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 1014e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinint Arm64Mir2Lir::EncodeExtend(int extend_type, int amount) { 1015cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu DCHECK_EQ(extend_type & 0x7, extend_type); 1016cedee4744c2d4f3611a7bb9fe98ef1bf4c37d915Zheng Xu DCHECK_EQ(amount & 0x7, amount); 1017e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return (1 << 6) | ((extend_type & 0x7) << 3) | (amount & 0x7); 1018e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin} 1019e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 1020e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchinbool Arm64Mir2Lir::IsExtendEncoding(int encoded_value) { 1021e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin return ((1 << 6) & encoded_value) != 0; 102243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 102343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 102443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::LoadBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_dest, 1025e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int scale, OpSize size) { 102643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LIR* load; 10270955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin int expected_scale = 0; 10284163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 10294b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_base = Check64BitReg(r_base); 103063fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu 103163fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu // TODO(Arm64): The sign extension of r_index should be carried out by using an extended 103263fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu // register offset load (rather than doing the sign extension in a separate instruction). 103363fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu if (r_index.Is32Bit()) { 103463fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu // Assemble: ``sxtw xN, wN''. 103563fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu r_index = As64BitReg(r_index); 103663fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu NewLIR4(WIDE(kA64Sbfm4rrdd), r_index.GetReg(), r_index.GetReg(), 0, 31); 103763fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu } 103843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 103943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (r_dest.IsFloat()) { 10400955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin if (r_dest.IsDouble()) { 10410955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(size == k64 || size == kDouble); 10420955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 3; 10434163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin opcode = WIDE(kA64Ldr4fXxG); 10440955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin } else { 10450955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(r_dest.IsSingle()); 10460955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(size == k32 || size == kSingle); 10470955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 2; 10480955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin opcode = kA64Ldr4fXxG; 10490955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin } 10500955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin 10510955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(scale == 0 || scale == expected_scale); 10520955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin return NewLIR4(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), 10530955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin (scale != 0) ? 1 : 0); 105443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 105543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 105643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin switch (size) { 1057e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kDouble: 1058e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kWord: 1059e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case k64: 10603c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_dest = Check64BitReg(r_dest); 10610955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin opcode = WIDE(kA64Ldr4rXxG); 10620955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 3; 10630955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin break; 106463fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu case kReference: 1065f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe r_dest = As32BitReg(r_dest); 1066f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe FALLTHROUGH_INTENDED; 1067f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case kSingle: // Intentional fall-through. 1068f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case k32: 10693c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_dest = Check32BitReg(r_dest); 1070e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldr4rXxG; 10710955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 2; 107243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 107343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedHalf: 10744b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_dest = Check32BitReg(r_dest); 1075e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrh4wXxd; 10760955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 1; 107743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 107843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedHalf: 10794b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_dest = Check32BitReg(r_dest); 1080e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrsh4rXxd; 10810955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 1; 108243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 108343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedByte: 10844b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_dest = Check32BitReg(r_dest); 1085e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrb3wXx; 108643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 108743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedByte: 10884b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_dest = Check32BitReg(r_dest); 1089e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrsb3rXx; 109043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 109143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 109243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad size: " << size; 109343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 1094e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 10950955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin if (UNLIKELY(expected_scale == 0)) { 10960955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin // This is a tertiary op (e.g. ldrb, ldrsb), it does not not support scale. 10970955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK_NE(EncodingMap[UNWIDE(opcode)].flags & IS_TERTIARY_OP, 0U); 1098e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(scale, 0); 10990955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg()); 1100e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 11010955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(scale == 0 || scale == expected_scale); 11020955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin load = NewLIR4(opcode, r_dest.GetReg(), r_base.GetReg(), r_index.GetReg(), 1103e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin (scale != 0) ? 1 : 0); 1104e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 110543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 110643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return load; 110743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 110843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 110943ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::StoreBaseIndexed(RegStorage r_base, RegStorage r_index, RegStorage r_src, 1110e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin int scale, OpSize size) { 1111e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LIR* store; 11120955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin int expected_scale = 0; 11134163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 11144b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_base = Check64BitReg(r_base); 111563fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu 111663fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu // TODO(Arm64): The sign extension of r_index should be carried out by using an extended 111763fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu // register offset store (rather than doing the sign extension in a separate instruction). 111863fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu if (r_index.Is32Bit()) { 111963fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu // Assemble: ``sxtw xN, wN''. 112063fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu r_index = As64BitReg(r_index); 112163fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu NewLIR4(WIDE(kA64Sbfm4rrdd), r_index.GetReg(), r_index.GetReg(), 0, 31); 112263fe93d9f9d2956b1ee2b98cdd6ddd2153f5f9cfSerban Constantinescu } 112343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 112443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (r_src.IsFloat()) { 11250955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin if (r_src.IsDouble()) { 11260955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(size == k64 || size == kDouble); 11270955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 3; 11284163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin opcode = WIDE(kA64Str4fXxG); 11290955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin } else { 11300955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(r_src.IsSingle()); 11310955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(size == k32 || size == kSingle); 11320955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 2; 11330955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin opcode = kA64Str4fXxG; 11340955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin } 11350955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin 11360955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK(scale == 0 || scale == expected_scale); 11370955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin return NewLIR4(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg(), 11380955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin (scale != 0) ? 1 : 0); 113943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 114043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 114143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin switch (size) { 1142e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kDouble: // Intentional fall-trough. 1143e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kWord: // Intentional fall-trough. 1144e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case k64: 11453c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_src = Check64BitReg(r_src); 11460955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin opcode = WIDE(kA64Str4rXxG); 11470955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 3; 1148e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin break; 1149255e014542b2180620230e4d9d6000ae06846bbdMatteo Franchin case kReference: 1150f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe r_src = As32BitReg(r_src); 1151f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe FALLTHROUGH_INTENDED; 1152f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case kSingle: // Intentional fall-trough. 1153f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case k32: 11543c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_src = Check32BitReg(r_src); 1155e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Str4rXxG; 11560955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 2; 115743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 115843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedHalf: 115943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedHalf: 11604b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_src = Check32BitReg(r_src); 1161e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Strh4wXxd; 11620955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin expected_scale = 1; 116343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 116443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedByte: 116543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedByte: 11664b537a851b686402513a7c4a4e60f5457bb8d7c1Andreas Gampe r_src = Check32BitReg(r_src); 1167e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Strb3wXx; 116843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 116943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 117043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad size: " << size; 117143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 1172e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 11730955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin if (UNLIKELY(expected_scale == 0)) { 11740955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin // This is a tertiary op (e.g. strb), it does not not support scale. 11750955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin DCHECK_NE(EncodingMap[UNWIDE(opcode)].flags & IS_TERTIARY_OP, 0U); 1176e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin DCHECK_EQ(scale, 0); 11770955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg()); 1178e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 11790955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin store = NewLIR4(opcode, r_src.GetReg(), r_base.GetReg(), r_index.GetReg(), 11800955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin (scale != 0) ? 1 : 0); 1181e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } 118243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 118343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return store; 118443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 118543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 118643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin/* 118743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * Load value from base + displacement. Optionally perform null check 118843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * on base (which must have an associated s_reg and MIR). If not 118943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin * performing null check, incoming MIR can be null. 119043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin */ 119143ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::LoadBaseDispBody(RegStorage r_base, int displacement, RegStorage r_dest, 11923bf7c60a86d49bf8c05c5d2ac5ca8e9f80bd9824Vladimir Marko OpSize size) { 11932cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR* load = nullptr; 11944163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 11954163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode alt_opcode = kA64Brk1d; 1196bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin int scale = 0; 1197bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin 119843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin switch (size) { 1199e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kDouble: // Intentional fall-through. 1200e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kWord: // Intentional fall-through. 120143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case k64: 12023c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_dest = Check64BitReg(r_dest); 1203bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 3; 120443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (r_dest.IsFloat()) { 1205bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin DCHECK(r_dest.IsDouble()); 12064163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin opcode = WIDE(kA64Ldr3fXD); 12074163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin alt_opcode = WIDE(kA64Ldur3fXd); 1208e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 12090955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin opcode = WIDE(kA64Ldr3rXD); 12100955f7e470fb733aef07096536e9fba7c99250aaMatteo Franchin alt_opcode = WIDE(kA64Ldur3rXd); 121143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 121243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 1213255e014542b2180620230e4d9d6000ae06846bbdMatteo Franchin case kReference: 1214f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe r_dest = As32BitReg(r_dest); 1215f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe FALLTHROUGH_INTENDED; 1216f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case kSingle: // Intentional fall-through. 1217f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case k32: 12183c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_dest = Check32BitReg(r_dest); 1219bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 2; 122043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (r_dest.IsFloat()) { 1221bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin DCHECK(r_dest.IsSingle()); 1222e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldr3fXD; 1223bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin } else { 1224e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldr3rXD; 122543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 122643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 122743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedHalf: 1228bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 1; 1229bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin opcode = kA64Ldrh3wXF; 123043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 123143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedHalf: 1232bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 1; 1233e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrsh3rXF; 123443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 123543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedByte: 1236e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrb3wXd; 123743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 123843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedByte: 1239e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Ldrsb3rXd; 124043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 124143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 124243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad size: " << size; 124343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 124443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 1245bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin bool displacement_is_aligned = (displacement & ((1 << scale) - 1)) == 0; 1246bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin int scaled_disp = displacement >> scale; 1247bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin if (displacement_is_aligned && scaled_disp >= 0 && scaled_disp < 4096) { 1248bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // Can use scaled load. 1249bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin load = NewLIR3(opcode, r_dest.GetReg(), r_base.GetReg(), scaled_disp); 1250bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin } else if (alt_opcode != kA64Brk1d && IS_SIGNED_IMM9(displacement)) { 1251bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // Can use unscaled load. 1252bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin load = NewLIR3(alt_opcode, r_dest.GetReg(), r_base.GetReg(), displacement); 1253e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 1254bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // Use long sequence. 125533ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee // TODO: cleaner support for index/displacement registers? Not a reference, but must match width. 125633ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee RegStorage r_scratch = AllocTempWide(); 125733ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee LoadConstantWide(r_scratch, displacement); 1258582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe load = LoadBaseIndexed(r_base, r_scratch, 1259582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe (size == kReference) ? As64BitReg(r_dest) : r_dest, 1260582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe 0, size); 1261bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin FreeTemp(r_scratch); 126243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 126343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 126443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin // TODO: in future may need to differentiate Dalvik accesses w/ spills 12658dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 1266b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(r_base, rs_sp); 126743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, r_dest.Is64Bit()); 126843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 126943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return load; 127043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 127143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 12723c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* Arm64Mir2Lir::LoadBaseDisp(RegStorage r_base, int displacement, RegStorage r_dest, 12733c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe OpSize size, VolatileKind is_volatile) { 1274674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // LoadBaseDisp() will emit correct insn for atomic load on arm64 1275674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // assuming r_dest is correctly prepared using RegClassForFieldLoadStore(). 127643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 12773c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe LIR* load = LoadBaseDispBody(r_base, displacement, r_dest, size); 12783c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 12793c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe if (UNLIKELY(is_volatile == kVolatile)) { 128048f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // TODO: This should generate an acquire load instead of the barrier. 128148f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm GenMemBarrier(kLoadAny); 12823c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe } 12833c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 12843c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe return load; 12852689fbad6b5ec1ae8f8c8791a80c6fd3cf24144dAndreas Gampe} 128643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 128743ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::StoreBaseDispBody(RegStorage r_base, int displacement, RegStorage r_src, 1288e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin OpSize size) { 12892cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier LIR* store = nullptr; 12904163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode opcode = kA64Brk1d; 12914163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin A64Opcode alt_opcode = kA64Brk1d; 1292bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin int scale = 0; 1293bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin 129443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin switch (size) { 1295e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kDouble: // Intentional fall-through. 1296e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin case kWord: // Intentional fall-through. 129743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case k64: 12983c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_src = Check64BitReg(r_src); 1299bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 3; 1300e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin if (r_src.IsFloat()) { 1301bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin DCHECK(r_src.IsDouble()); 13024163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin opcode = WIDE(kA64Str3fXD); 13034163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin alt_opcode = WIDE(kA64Stur3fXd); 130443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } else { 13054163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin opcode = WIDE(kA64Str3rXD); 13064163c53ce38a0f1f88bf3e8d26de9914da38498bMatteo Franchin alt_opcode = WIDE(kA64Stur3rXd); 130743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 130843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 1309255e014542b2180620230e4d9d6000ae06846bbdMatteo Franchin case kReference: 1310f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe r_src = As32BitReg(r_src); 1311f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe FALLTHROUGH_INTENDED; 1312f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case kSingle: // Intentional fall-through. 1313f681570077563bb529a30f9e7c572b837cecfb83Andreas Gampe case k32: 13143c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe r_src = Check32BitReg(r_src); 1315bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 2; 131643ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin if (r_src.IsFloat()) { 131743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin DCHECK(r_src.IsSingle()); 1318e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Str3fXD; 1319bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin } else { 1320e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Str3rXD; 132143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 132243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 132343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedHalf: 132443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedHalf: 1325bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin scale = 1; 1326e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Strh3wXF; 132743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 132843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kUnsignedByte: 132943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin case kSignedByte: 1330e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin opcode = kA64Strb3wXd; 133143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin break; 133243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin default: 133343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin LOG(FATAL) << "Bad size: " << size; 133443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 1335e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin 1336bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin bool displacement_is_aligned = (displacement & ((1 << scale) - 1)) == 0; 1337bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin int scaled_disp = displacement >> scale; 1338bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin if (displacement_is_aligned && scaled_disp >= 0 && scaled_disp < 4096) { 1339bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // Can use scaled store. 1340bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin store = NewLIR3(opcode, r_src.GetReg(), r_base.GetReg(), scaled_disp); 1341bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin } else if (alt_opcode != kA64Brk1d && IS_SIGNED_IMM9(displacement)) { 1342bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // Can use unscaled store. 1343bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin store = NewLIR3(alt_opcode, r_src.GetReg(), r_base.GetReg(), displacement); 1344e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin } else { 1345bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // Use long sequence. 134633ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee RegStorage r_scratch = AllocTempWide(); 134733ae5583bdd69847a7316ab38a8fa8ccd63093efbuzbee LoadConstantWide(r_scratch, displacement); 1348582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe store = StoreBaseIndexed(r_base, r_scratch, 1349582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe (size == kReference) ? As64BitReg(r_src) : r_src, 1350582f541b35f40b75f2629a41259d2162608647d5Andreas Gampe 0, size); 1351e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin FreeTemp(r_scratch); 135243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 135343ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 1354bc6d197cdb02eeac0c98ec4ed37f530b003a4e7aMatteo Franchin // TODO: In future, may need to differentiate Dalvik & spill accesses. 13558dea81ca9c0201ceaa88086b927a5838a06a3e69Vladimir Marko if (mem_ref_type_ == ResourceMask::kDalvikReg) { 1356b28c1c06236751aa5c9e64dcb68b3c940341e496Ian Rogers DCHECK_EQ(r_base, rs_sp); 135743ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, r_src.Is64Bit()); 135843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin } 135943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin return store; 136043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 136143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 13623c12c512faf6837844d5465b23b9410889e5eb11Andreas GampeLIR* Arm64Mir2Lir::StoreBaseDisp(RegStorage r_base, int displacement, RegStorage r_src, 13633c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe OpSize size, VolatileKind is_volatile) { 136448f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // TODO: This should generate a release store and no barriers. 13653c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe if (UNLIKELY(is_volatile == kVolatile)) { 136648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // Ensure that prior accesses become visible to other threads first. 136748f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm GenMemBarrier(kAnyStore); 13683c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe } 13693c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 1370674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // StoreBaseDisp() will emit correct insn for atomic store on arm64 1371674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko // assuming r_dest is correctly prepared using RegClassForFieldLoadStore(). 13723c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 13733c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe LIR* store = StoreBaseDispBody(r_base, displacement, r_src, size); 13743c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 13753c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe if (UNLIKELY(is_volatile == kVolatile)) { 137648f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // Preserve order with respect to any subsequent volatile loads. 137748f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm // We need StoreLoad, but that generally requires the most expensive barrier. 137848f5c47907654350ce30a8dfdda0e977f5d3d39fHans Boehm GenMemBarrier(kAnyAny); 13793c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe } 13803c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe 13813c12c512faf6837844d5465b23b9410889e5eb11Andreas Gampe return store; 1382674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko} 1383674744e635ddbdfb311fbd25b5a27356560d30c3Vladimir Marko 138443ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpFpRegCopy(RegStorage r_dest, RegStorage r_src) { 13856a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(r_dest, r_src); 1386e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LOG(FATAL) << "Unexpected use of OpFpRegCopy for Arm64"; 13876a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 138843ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 138943ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 139043ec8737d8356dbff0a90bee521fb0e73438da47Matteo FranchinLIR* Arm64Mir2Lir::OpMem(OpKind op, RegStorage r_base, int disp) { 13916a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNUSED(op, r_base, disp); 1392e45fb9e7976c8462b94a58ad60b006b0eacec49fMatteo Franchin LOG(FATAL) << "Unexpected use of OpMem for Arm64"; 13936a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers UNREACHABLE(); 139443ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 139543ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 13966a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan RogersLIR* Arm64Mir2Lir::InvokeTrampoline(OpKind op, RegStorage r_tgt, 13976a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers QuickEntrypointEnum trampoline ATTRIBUTE_UNUSED) { 13986a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers // The address of the trampoline is already loaded into r_tgt. 1399984305917bf57b3f8d92965e4715a0370cc5bcfbAndreas Gampe return OpReg(op, r_tgt); 140043ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} 140143ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin 140243ec8737d8356dbff0a90bee521fb0e73438da47Matteo Franchin} // namespace art 1403