| /* Copyright 2017 IBM Corp. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| * implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef __ELF_ABI_H |
| #define __ELF_ABI_H |
| |
| #ifndef __ASSEMBLY__ |
| |
| #if defined (_CALL_ELF) && _CALL_ELF == 2 |
| #define ELF_ABI_v2 |
| #else |
| #define ELF_ABI_v1 |
| #endif |
| |
| /* From linux/arch/powerpc/include/asm/code-patching.h */ |
| #define OP_RT_RA_MASK 0xffff0000UL |
| #define LIS_R2 0x3c020000UL |
| #define ADDIS_R2_R12 0x3c4c0000UL |
| #define ADDI_R2_R2 0x38420000UL |
| |
| static inline uint64_t function_entry_address(void *func) |
| { |
| #ifdef ELF_ABI_v2 |
| u32 *insn = func; |
| /* |
| * A PPC64 ABIv2 function may have a local and a global entry |
| * point. We use the local entry point for branch tables called |
| * from asm, only a single TOC is used, so identify and step over |
| * the global entry point sequence. |
| * |
| * The global entry point sequence is always of the form: |
| * |
| * addis r2,r12,XXXX |
| * addi r2,r2,XXXX |
| * |
| * A linker optimisation may convert the addis to lis: |
| * |
| * lis r2,XXXX |
| * addi r2,r2,XXXX |
| */ |
| if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) || |
| ((*insn & OP_RT_RA_MASK) == LIS_R2)) && |
| ((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2)) |
| return (uint64_t)(insn + 2); |
| else |
| return (uint64_t)func; |
| #else |
| return *(uint64_t *)func; |
| #endif |
| } |
| |
| #endif /* __ASSEMBLY__ */ |
| |
| #endif /* __COMPILER_H */ |