1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- /* descriptor-pa32-hpux.h - Given a function pointer, extract and return the
- actual code address of the corresponding function.
- This is done by checking if the plabel bit is set. If it's not set,
- return the function pointer. If it's set, mask it off and extract
- the address from the function descriptor. This address may point
- to an export stub. If so, extract the branch target from the stub
- and return it. Otherwise, the address from the function descriptor
- is returned.
- Copyright (C) 2006 Free Software Foundation
- This file is part of libgcj.
- This software is copyrighted work licensed under the terms of the
- Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
- details. */
- #define UNWRAP_FUNCTION_DESCRIPTOR pa_unwrap_function_descriptor
- #ifdef __cplusplus
- extern "C" {
- #endif
- /* Extract bit field from word using HP's numbering (MSB = 0). */
- #define GET_FIELD(X, FROM, TO) \
- ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
- static inline int
- sign_extend (int x, int len)
- {
- int signbit = (1 << (len - 1));
- int mask = (signbit << 1) - 1;
- return ((x & mask) ^ signbit) - signbit;
- }
- /* Extract a 17-bit signed constant from branch instructions. */
- static inline int
- extract_17 (unsigned word)
- {
- return sign_extend (GET_FIELD (word, 19, 28)
- | GET_FIELD (word, 29, 29) << 10
- | GET_FIELD (word, 11, 15) << 11
- | (word & 0x1) << 16, 17);
- }
- /* Extract a 22-bit signed constant from branch instructions. */
- static inline int
- extract_22 (unsigned word)
- {
- return sign_extend (GET_FIELD (word, 19, 28)
- | GET_FIELD (word, 29, 29) << 10
- | GET_FIELD (word, 11, 15) << 11
- | GET_FIELD (word, 6, 10) << 16
- | (word & 0x1) << 21, 22);
- }
- static void *
- pa_unwrap_function_descriptor (void *addr)
- {
- unsigned int *tmp_addr;
- /* Check if plabel bit is set in function pointer. */
- if (!((unsigned int) addr & 2))
- return addr;
- tmp_addr = *(unsigned int **) ((unsigned int) addr & ~3);
- /* If TMP_ADDR points to an export stub, adjust it so that it points
- to the branch target of the stub. */
- if ((*tmp_addr & 0xffe0e002) == 0xe8400000 /* bl x,r2 */
- && *(tmp_addr + 1) == 0x08000240 /* nop */
- && *(tmp_addr + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
- && *(tmp_addr + 3) == 0x004010a1 /* ldsid (rp),r1 */
- && *(tmp_addr + 4) == 0x00011820 /* mtsp r1,sr0 */
- && *(tmp_addr + 5) == 0xe0400002) /* be,n 0(sr0,rp) */
- /* Extract target address from PA 1.x 17-bit branch. */
- tmp_addr += extract_17 (*tmp_addr) + 2;
- else if ((*tmp_addr & 0xfc00e002) == 0xe800a000 /* b,l x,r2 */
- && *(tmp_addr + 1) == 0x08000240 /* nop */
- && *(tmp_addr + 2) == 0x4bc23fd1 /* ldw -18(sp),rp */
- && *(tmp_addr + 3) == 0xe840d002) /* bve,n (rp) */
- /* Extract target address from PA 2.0 22-bit branch. */
- tmp_addr += extract_22 (*tmp_addr) + 2;
- return (void *) tmp_addr;
- }
- #ifdef __cplusplus
- }
- #endif
|