aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/libjava/sysdep/pa/descriptor-pa32-hpux.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/libjava/sysdep/pa/descriptor-pa32-hpux.h')
-rw-r--r--gcc-4.8/libjava/sysdep/pa/descriptor-pa32-hpux.h91
1 files changed, 91 insertions, 0 deletions
diff --git a/gcc-4.8/libjava/sysdep/pa/descriptor-pa32-hpux.h b/gcc-4.8/libjava/sysdep/pa/descriptor-pa32-hpux.h
new file mode 100644
index 000000000..6000edb52
--- /dev/null
+++ b/gcc-4.8/libjava/sysdep/pa/descriptor-pa32-hpux.h
@@ -0,0 +1,91 @@
+/* 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