X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gold%2Faarch64.cc;h=5ca5e0accfff921463a4714224802ba0099d6d71;hb=751e4d66b4c6daaf04e6bccdb3f9ce4a0620babb;hp=130fcc2cba0760ffdbf231234e8427c131733271;hpb=a48d0c12f893a922692492829f04189d9f216172;p=external%2Fbinutils.git diff --git a/gold/aarch64.cc b/gold/aarch64.cc index 130fcc2..5ca5e0a 100644 --- a/gold/aarch64.cc +++ b/gold/aarch64.cc @@ -77,7 +77,10 @@ class AArch64_insn_utilities public: typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype; - static const int BYTES_PER_INSN = 4; + static const int BYTES_PER_INSN; + + // Zero register encoding - 31. + static const unsigned int AARCH64_ZR; static unsigned int aarch64_bit(Insntype insn, int pos) @@ -87,6 +90,22 @@ public: aarch64_bits(Insntype insn, int pos, int l) { return (insn >> pos) & ((1 << l) - 1); } + // Get the encoding field "op31" of 3-source data processing insns. "op31" is + // the name defined in armv8 insn manual C3.5.9. + static unsigned int + aarch64_op31(Insntype insn) + { return aarch64_bits(insn, 21, 3); } + + // Get the encoding field "ra" of 3-source data processing insns. "ra" is the + // third source register. See armv8 insn manual C3.5.9. + static unsigned int + aarch64_ra(Insntype insn) + { return aarch64_bits(insn, 10, 5); } + + static bool + is_adr(const Insntype insn) + { return (insn & 0x9F000000) == 0x10000000; } + static bool is_adrp(const Insntype insn) { return (insn & 0x9F000000) == 0x90000000; } @@ -111,6 +130,39 @@ public: aarch64_rt2(const Insntype insn) { return aarch64_bits(insn, 10, 5); } + // Encode imm21 into adr. Signed imm21 is in the range of [-1M, 1M). + static Insntype + aarch64_adr_encode_imm(Insntype adr, int imm21) + { + gold_assert(is_adr(adr)); + gold_assert(-(1 << 20) <= imm21 && imm21 < (1 << 20)); + const int mask19 = (1 << 19) - 1; + const int mask2 = 3; + adr &= ~((mask19 << 5) | (mask2 << 29)); + adr |= ((imm21 & mask2) << 29) | (((imm21 >> 2) & mask19) << 5); + return adr; + } + + // Retrieve encoded adrp 33-bit signed imm value. This value is obtained by + // 21-bit signed imm encoded in the insn multiplied by 4k (page size) and + // 64-bit sign-extended, resulting in [-4G, 4G) with 12-lsb being 0. + static int64_t + aarch64_adrp_decode_imm(const Insntype adrp) + { + const int mask19 = (1 << 19) - 1; + const int mask2 = 3; + gold_assert(is_adrp(adrp)); + // 21-bit imm encoded in adrp. + uint64_t imm = ((adrp >> 29) & mask2) | (((adrp >> 5) & mask19) << 2); + // Retrieve msb of 21-bit-signed imm for sign extension. + uint64_t msbt = (imm >> 20) & 1; + // Real value is imm multipled by 4k. Value now has 33-bit information. + int64_t value = imm << 12; + // Sign extend to 64-bit by repeating msbt 31 (64-33) times and merge it + // with value. + return ((((uint64_t)(1) << 32) - msbt) << 33) | value; + } + static bool aarch64_b(const Insntype insn) { return (insn & 0xFC000000) == 0x14000000; } @@ -330,8 +382,42 @@ public: return true; } return false; + } // End of "aarch64_mem_op_p". + + // Return true if INSN is mac insn. + static bool + aarch64_mac(Insntype insn) + { return (insn & 0xff000000) == 0x9b000000; } + + // Return true if INSN is multiply-accumulate. + // (This is similar to implementaton in elfnn-aarch64.c.) + static bool + aarch64_mlxl(Insntype insn) + { + uint32_t op31 = aarch64_op31(insn); + if (aarch64_mac(insn) + && (op31 == 0 || op31 == 1 || op31 == 5) + /* Exclude MUL instructions which are encoded as a multiple-accumulate + with RA = XZR. */ + && aarch64_ra(insn) != AARCH64_ZR) + { + return true; + } + return false; } -}; +}; // End of "AArch64_insn_utilities". + + +// Insn length in byte. + +template +const int AArch64_insn_utilities::BYTES_PER_INSN = 4; + + +// Zero register encoding - 31. + +template +const unsigned int AArch64_insn_utilities::AARCH64_ZR = 0x1f; // Output_data_got_aarch64 class. @@ -603,8 +689,11 @@ enum // Stub for erratum 843419 handling. ST_E_843419 = 4, + // Stub for erratum 835769 handling. + ST_E_835769 = 5, + // Number of total stub types. - ST_NUMBER = 5 + ST_NUMBER = 6 }; @@ -695,6 +784,9 @@ Stub_template_repertoire::Stub_template_repertoire() 0x14000000, /* b