summaryrefslogtreecommitdiffstats
path: root/sys/contrib
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-05-15 05:04:44 +0000
committermarcel <marcel@FreeBSD.org>2003-05-15 05:04:44 +0000
commit54ea024a387cfbfd748ad1d2b2ccf18959a4f9da (patch)
treea4cf90ce9948f9ea926188d00fcf376fd3332a75 /sys/contrib
parentac48fcc177e0c1e9f20f76f4a6a9ec833537a1e3 (diff)
parent1edc7465a0eedb6ceb50376d0ef2bcd13a40e03d (diff)
downloadFreeBSD-src-54ea024a387cfbfd748ad1d2b2ccf18959a4f9da.zip
FreeBSD-src-54ea024a387cfbfd748ad1d2b2ccf18959a4f9da.tar.gz
This commit was generated by cvs2svn to compensate for changes in r115013,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'sys/contrib')
-rw-r--r--sys/contrib/ia64/libuwx/src/Makefile64
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx.h247
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_bstream.c179
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_bstream.h57
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_context.c329
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_context.h23
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_env.c168
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_env.h100
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_scoreboard.c277
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_scoreboard.h77
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_self.c261
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_self.h57
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_self_context.s153
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_step.c525
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_str.c122
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_str.h35
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_swap.c68
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_swap.h24
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_trace.c138
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_trace.h348
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_ttrace.c365
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_ttrace.h64
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_uinfo.c1103
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_uinfo.h64
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_utable.c255
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_utable.h33
-rw-r--r--sys/contrib/ia64/libuwx/test/Makefile13
-rw-r--r--sys/contrib/ia64/libuwx/test/dump_context.c70
-rw-r--r--sys/contrib/ia64/libuwx/test/dumpmyself.c101
29 files changed, 5320 insertions, 0 deletions
diff --git a/sys/contrib/ia64/libuwx/src/Makefile b/sys/contrib/ia64/libuwx/src/Makefile
new file mode 100644
index 0000000..f0f0871
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/Makefile
@@ -0,0 +1,64 @@
+# Makefile for IPF unwind express library, libuwx.
+#
+# To build a cross-unwind library (i.e., one hosted on a
+# non-IPF, non-HP-UX system), omit the "self" callbacks
+# and the dependency on libuca by setting SELFOBJS and
+# SELFLIBS to empty strings.
+
+AR = ar
+RANLIB = :
+
+# OTHERCFLAGS = -DDISABLE_TRACE # Disables trace output
+# OTHERCFLAGS = +DD64 # Builds 64-bit library
+OTHERCFLAGS =
+
+CFLAGS = +W944 -O $(OTHERCFLAGS)
+
+OBJS = uwx_bstream.o uwx_context.o uwx_env.o uwx_scoreboard.o \
+ uwx_step.o uwx_str.o uwx_swap.o uwx_trace.o uwx_uinfo.o \
+ uwx_utable.o
+
+# SELFOBJS = # For cross-unwind library
+SELFOBJS = uwx_self.o uwx_self_context.o uwx_ttrace.o
+
+# SELFLIBS = # For cross-unwind library
+SELFLIBS = -luca
+
+libuwx.a: $(OBJS) $(SELFOBJS)
+ $(AR) rv libuwx.a $?
+ $(RANLIB) libuwx.a
+
+libuwx.so: $(OBJS) $(SELFOBJS)
+ ld -b -o libuwx.so $(OBJS) $(SELFOBJS) $(SELFLIBS)
+
+libuwx.sl: $(OBJS) $(SELFOBJS)
+ ld -b -o libuwx.sl $(OBJS) $(SELFOBJS) $(SELFLIBS)
+
+uwx_bstream.o: uwx.h uwx_env.h uwx_bstream.h
+
+uwx_context.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_trace.h
+
+uwx_env.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_str.h uwx_trace.h
+
+uwx_scoreboard.o: uwx.h uwx_env.h uwx_scoreboard.h uwx_trace.h
+
+uwx_step.o: uwx.h uwx_env.h uwx_context.h uwx_utable.h \
+ uwx_uinfo.h uwx_scoreboard.h uwx_str.h uwx_trace.h
+
+uwx_str.o: uwx.h uwx_env.h uwx_str.h
+
+uwx_swap.o: uwx.h uwx_env.h uwx_swap.h
+
+uwx_trace.o: uwx.h uwx_env.h uwx_uinfo.h uwx_scoreboard.h uwx_trace.h
+
+uwx_uinfo.o: uwx.h uwx_env.h uwx_uinfo.h uwx_utable.h \
+ uwx_scoreboard.h uwx_bstream.h uwx_trace.h
+
+uwx_utable.o: uwx.h uwx_env.h uwx_utable.h uwx_swap.h uwx_trace.h
+
+uwx_self.o: uwx.h uwx_env.h uwx_context.h uwx_trace.h uwx_self.h
+
+uwx_self_context.o: uwx_self_context.s
+ $(CC) -c $(CFLAGS) -o uwx_self_context.o uwx_self_context.s
+
+uwx_ttrace.o: uwx.h uwx_env.h uwx_context.h uwx_trace.h uwx_ttrace.h
diff --git a/sys/contrib/ia64/libuwx/src/uwx.h b/sys/contrib/ia64/libuwx/src/uwx.h
new file mode 100644
index 0000000..82a264b
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx.h
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <inttypes.h>
+#else
+#include <sys/param.h>
+#include <sys/systm.h>
+#endif
+
+/* Unwind environment structure (opaque) */
+struct uwx_env;
+
+/* Allocate and free callbacks */
+typedef void *(*alloc_cb)(size_t size);
+typedef void (*free_cb)(void *ptr);
+extern int uwx_register_alloc_cb(alloc_cb alloc, free_cb free);
+
+/* Allocate and initialize an unwind environment */
+extern struct uwx_env *uwx_init(void);
+
+/* Free an unwind environment */
+extern int uwx_free(struct uwx_env *env);
+
+/* Put unwind express into cross-process mode */
+extern int uwx_set_remote(struct uwx_env *env, int is_big_endian_target);
+
+/* Copy-in callback */
+typedef int (*copyin_cb)(
+ int request, /* request code (see below) */
+ char *loc, /* local (destination) address */
+ uint64_t rem, /* remote (source) address */
+ int len, /* number of bytes to copy */
+ intptr_t tok); /* callback token */
+
+/* Lookup IP callback */
+typedef int (*lookupip_cb)(
+ int request, /* request code (see below) */
+ uint64_t ip, /* IP of current frame */
+ intptr_t tok, /* callback token */
+ uint64_t **vecp); /* parameter vector (in/out) */
+
+/* Register copy-in and lookup IP callbacks */
+extern int uwx_register_callbacks(
+ struct uwx_env *env, /* unwind environment */
+ intptr_t tok, /* callback token */
+ copyin_cb copyin, /* copy-in callback */
+ lookupip_cb lookupip); /* lookup IP callback */
+
+/* Initialize a context with the basic info needed to start an unwind */
+extern int uwx_init_context(
+ struct uwx_env *env, /* unwind environment */
+ uint64_t ip, /* IP (instruction pointer) */
+ uint64_t sp, /* SP (stack pointer) */
+ uint64_t bsp, /* BSP (backing store pointer) */
+ uint64_t cfm); /* CFM (current frame marker) */
+
+/* Set the value of a specific register in the current context (non fp) */
+extern int uwx_set_reg(
+ struct uwx_env *env, /* unwind environment */
+ int regid, /* register id (see below) */
+ uint64_t val); /* register value */
+
+/* Set the value of a floating-point register in the current context */
+extern int uwx_set_fr(
+ struct uwx_env *env, /* unwind environment */
+ int regid, /* register id (see below) */
+ uint64_t *val); /* register value (ptr to 16 bytes) */
+ /* (memory spill format) */
+
+/* Initialize the unwind history */
+extern int uwx_init_history(struct uwx_env *env);
+
+/* Step one frame */
+extern int uwx_step(struct uwx_env *env);
+
+/* Get symbol information, if available, for current frame */
+extern int uwx_get_sym_info(
+ struct uwx_env *env, /* unwind environment */
+ char **modp, /* load module name (out) */
+ char **symp, /* function name (out) */
+ uint64_t *offsetp); /* offset from start of function (out) */
+
+/* Get the value of a register from the current context */
+extern int uwx_get_reg(
+ struct uwx_env *env, /* unwind environment */
+ int regid, /* register id (see below) */
+ uint64_t *valp); /* register value (out) */
+
+/* Get the NaT bit of a GR from the current context */
+extern int uwx_get_nat(
+ struct uwx_env *env, /* unwind environment */
+ int regid, /* register id (see below) */
+ int *natp); /* NaT value (out: 0 or 1) */
+
+/* Get the spill location for a register in the current context */
+extern int uwx_get_spill_loc(
+ struct uwx_env *env, /* unwind environment */
+ int regid, /* register id (see below) */
+ uint64_t *dispp); /* disposition code (see below) (out) */
+
+/* Get the ABI context code (if uwx_step returned UWX_ABI_FRAME) */
+extern int uwx_get_abi_context_code(struct uwx_env *env);
+
+/* Return status codes for uwx_ APIs */
+#define UWX_OK 0
+#define UWX_BOTTOM 1 /* Hit bottom of stack */
+#define UWX_ABI_FRAME 2 /* Hit ABI-dependent frame */
+#define UWX_ERR_NOENV (-1) /* No uwx_env allocated */
+#define UWX_ERR_IPNOTFOUND (-2) /* Lookup IP c/b returned NOTFOUND */
+#define UWX_ERR_LOOKUPERR (-3) /* Lookup IP c/b returned ERR */
+#define UWX_ERR_BADKEY (-4) /* Bad result vector key */
+#define UWX_ERR_COPYIN_UTBL (-5) /* Error reading unwind table */
+#define UWX_ERR_COPYIN_UINFO (-6) /* Error reading unwind info */
+#define UWX_ERR_COPYIN_MSTK (-7) /* Error reading memory stack */
+#define UWX_ERR_COPYIN_RSTK (-8) /* Error reading register stack */
+#define UWX_ERR_COPYIN_REG (-9) /* Error reading context register */
+#define UWX_ERR_NOUENTRY (-10) /* No unwind table entry for ip */
+#define UWX_ERR_NOUDESC (-11) /* No unwind descriptor covers ip */
+#define UWX_ERR_BADUDESC (-12) /* Bad unwind descriptor */
+#define UWX_ERR_NOMEM (-13) /* Out of memory */
+#define UWX_ERR_PROLOG_UF (-14) /* Prologue underflow */
+#define UWX_ERR_UNDEFLABEL (-15) /* Undefined label in copy_state */
+#define UWX_ERR_BADREGID (-16) /* Bad register identifier */
+#define UWX_ERR_CANTUNWIND (-17) /* Can't unwind */
+#define UWX_ERR_NOCALLBACKS (-18) /* No callbacks registered */
+#define UWX_ERR_NOCONTEXT (-19) /* Context not initialized */
+
+/* Request codes for copyin callback */
+#define UWX_COPYIN_UINFO 1 /* Reading unwind info */
+#define UWX_COPYIN_MSTACK 2 /* Reading memory stack */
+#define UWX_COPYIN_RSTACK 3 /* Reading RSE backing store */
+#define UWX_COPYIN_REG 4 /* Reading initial register state */
+
+/* Request codes for lookup IP callback */
+#define UWX_LKUP_LOOKUP 1 /* Lookup IP */
+#define UWX_LKUP_FREE 2 /* Free result vector */
+#define UWX_LKUP_SYMBOLS 3 /* Lookup symbolic information */
+
+/* Return status codes for lookup IP callback */
+#define UWX_LKUP_NOTFOUND 0 /* IP not found */
+#define UWX_LKUP_ERR 1 /* Other error */
+#define UWX_LKUP_UTABLE 2 /* Returned ref to unwind table */
+#define UWX_LKUP_FDESC 3 /* Returned frame description */
+#define UWX_LKUP_SYMINFO 4 /* Returned symbolic information */
+
+/* The lookup IP callback receives a parameter vector, and returns */
+/* one on success. This vector is a series of key/value pairs; each */
+/* even-numbered slot is a key, and each odd-numbered slot is a */
+/* corresponding value. The vector is terminated by a pair whose */
+/* key is 0. */
+#define UWX_KEY_END 0 /* End of vector */
+
+/* Keys passed to lookup IP callback */
+#define UWX_KEY_PREDS 1 /* Predicate registers */
+
+/* Keys returned with UWX_LKUP_UTABLE */
+/* These key/value pairs describe the unwind table corresponding */
+/* to the load module in which the current IP resides. */
+#define UWX_KEY_TBASE 1 /* Base address of text seg */
+#define UWX_KEY_UFLAGS 2 /* Unwind flags */
+#define UWX_KEY_USTART 3 /* Base of unwind tbl */
+#define UWX_KEY_UEND 4 /* End of unwind tbl */
+
+/* Keys returned with UWX_LKUP_FDESC */
+/* These key/value pairs describe the state of the frame at the */
+/* given IP. They are typically used for dynamically-generated code. */
+#define UWX_KEY_FSIZE 1 /* Frame size */
+#define UWX_KEY_SPILL(reg_id) (2 | ((reg_id) << 4)) /* Reg spilled */
+#define UWX_KEY_CONTEXT 3 /* ABI-dep. context */
+
+/* Keys returned with UWX_LKUP_FDESC or UWX_LKUP_SYMINFO */
+#define UWX_KEY_MODULE 5 /* Name of load module */
+#define UWX_KEY_FUNC 6 /* Name of function */
+#define UWX_KEY_FUNCSTART 7 /* Address of start of function */
+
+/* Register identifiers */
+/* For use in UWX_LKUP_FDESC result vectors and context access APIs. */
+/* "no spill info": These regs aren't spilled directly, so */
+/* result vectors must not describe these registers. */
+/* The result vector must describe the related register or */
+/* pseudo register instead (ip:rp, sp:psp, bsp/cfm:pfs). */
+/* "pseudo register": Not a machine register, but treated as */
+/* one for unwind purposes. */
+#define UWX_REG_IP 0 /* ip (no spill info) */
+#define UWX_REG_SP 1 /* sp (no spill info) */
+#define UWX_REG_BSP 2 /* ar.bsp (no spill info) */
+#define UWX_REG_CFM 3 /* cfm (no spill info) */
+#define UWX_REG_RP 4 /* rp (pseudo-register) */
+#define UWX_REG_PSP 5 /* psp (pseudo-register) */
+#define UWX_REG_PFS 6 /* ar.pfs */
+#define UWX_REG_PREDS 7 /* p0 - p63 */
+#define UWX_REG_PRIUNAT 8 /* primary unat (pseudo-register) */
+#define UWX_REG_BSPSTORE 9 /* ar.bspstore */
+#define UWX_REG_RNAT 10 /* ar.rnat */
+#define UWX_REG_UNAT 11 /* ar.unat */
+#define UWX_REG_FPSR 12 /* ar.fpsr */
+#define UWX_REG_LC 13 /* ar.lc */
+#define UWX_REG_GR(gr) (0x100 | (gr))
+#define UWX_REG_FR(fr) (0x200 | (fr))
+#define UWX_REG_BR(br) (0x300 | (br))
+
+/* Values corresponding to UWX_KEY_SPILL keys indicate the disposition */
+/* of the spilled register -- either in the memory stack or in another */
+/* register. The PSP register may also have a disposition of "SPPLUS", */
+/* indicating that its value is SP plus a fixed constant. */
+#define UWX_DISP_NONE 0 /* Not spilled */
+#define UWX_DISP_SPPLUS(k) (1 | (k)) /* PSP = SP+constant */
+#define UWX_DISP_SPREL(disp) (2 | (disp)) /* Spilled at [SP+disp] */
+#define UWX_DISP_PSPREL(disp) (3 | (disp)) /* Spilled at [PSP+16-disp] */
+#define UWX_DISP_REG(reg) (4 | ((reg) << 4)) /* Saved to another reg. */
+
+/* The uwx_get_spill_loc() routine returns a spill location for a */
+/* given register in the current context. It will return a disposition */
+/* code of UWX_DISP_NONE, UWX_DISP_REG(reg), or one of the following */
+/* to indicate that the spilled value can be found in the memory */
+/* stack or the register stack backing store. */
+#define UWX_DISP_MSTK(addr) (5 | (addr)) /* Spilled in mem. stack */
+#define UWX_DISP_RSTK(addr) (6 | (addr)) /* Spilled in reg. stack */
+
+/* Extract the disposition code, offset, address, or register id */
+/* from a disposition returned from uwx_get_spill_loc(). */
+/* Compare the extracted disp code against UWX_DISP_REG(0), etc. */
+#define UWX_GET_DISP_CODE(disp) ((int)(disp) & 0x07)
+#define UWX_GET_DISP_OFFSET(disp) ((disp) & ~(uint64_t)0x07)
+#define UWX_GET_DISP_ADDR(disp) ((disp) & ~(uint64_t)0x07)
+#define UWX_GET_DISP_REGID(disp) ((int)(disp) >> 4)
diff --git a/sys/contrib/ia64/libuwx/src/uwx_bstream.c b/sys/contrib/ia64/libuwx/src/uwx_bstream.c
new file mode 100644
index 0000000..6ebe8c4
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_bstream.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_bstream.h"
+
+
+/* uwx_init_bstream: initialize a byte stream for reading */
+
+void uwx_init_bstream(
+ struct uwx_bstream *bstream,
+ struct uwx_env *env,
+ uint64_t source,
+ unsigned int len,
+ int request)
+{
+ bstream->buf = 0;
+ if (env->remote) {
+ bstream->source = source;
+ bstream->bufp = (unsigned char *) &bstream->buf;
+ bstream->nbuf = 0;
+ bstream->copyin = env->copyin;
+ bstream->cb_token = env->cb_token;
+ bstream->request = request;
+ }
+ else {
+ bstream->source = 0;
+ bstream->bufp = (unsigned char *) source;
+ bstream->nbuf = len;
+ bstream->copyin = 0;
+ bstream->cb_token = 0;
+ bstream->request = 0;
+ }
+ bstream->ntotal = len;
+ bstream->peekc = -1;
+}
+
+
+/* uwx_get_byte: read the next byte from the byte stream */
+
+int uwx_get_byte(struct uwx_bstream *bstream)
+{
+ int len;
+ int n;
+ int b;
+
+ if (bstream->peekc >= 0) {
+ b = bstream->peekc;
+ bstream->peekc = -1;
+ return b;
+ }
+ if (bstream->ntotal <= 0)
+ return -1;
+ if (bstream->nbuf <= 0) {
+ if (bstream->source & 0x7)
+ len = sizeof(uint32_t);
+ else
+ len = sizeof(uint64_t);
+ n = (*bstream->copyin)(bstream->request, (char *)&bstream->buf,
+ bstream->source, len, bstream->cb_token);
+ if (n != len)
+ return -1;
+ bstream->bufp = (unsigned char *) &bstream->buf;
+ bstream->nbuf = n;
+ bstream->source += n;
+ }
+
+ b = *bstream->bufp++;
+ bstream->nbuf--;
+ bstream->ntotal--;
+ return b;
+}
+
+
+/* uwx_unget_byte: push a byte back onto the byte stream */
+
+int uwx_unget_byte(struct uwx_bstream *bstream, int b)
+{
+ bstream->peekc = b;
+ return 0;
+}
+
+
+/* uwx_get_uleb128: read a ULEB128 value from the byte stream */
+
+int uwx_get_uleb128(struct uwx_bstream *bstream, uint64_t *valp)
+{
+ uint64_t val;
+ int i;
+ int b;
+
+ b = uwx_get_byte(bstream);
+ val = (uint64_t)(b & 0x7f) << 56;
+ for (i = 0; i < 8; i++) {
+ val = val >> 7;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 56;
+ }
+ }
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 63;
+ }
+ if (b & 0x80)
+ return -1;
+ *valp = val;
+ return 0;
+}
+
+#if 0
+int uwx_get_uleb128_alt(struct uwx_bstream *bstream, uint64_t *valp)
+{
+ uint64_t val;
+ int b;
+
+ b = uwx_get_byte(bstream);
+ val = b & 0x7f;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 7;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 14;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 21;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 28;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 35;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 42;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 49;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 56;
+ if (b & 0x80) {
+ b = uwx_get_byte(bstream);
+ val |= (uint64_t)(b & 0x7f) << 63;
+ if (b & 0x80)
+ return -1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ *valp = val;
+ return 0;
+}
+#endif
diff --git a/sys/contrib/ia64/libuwx/src/uwx_bstream.h b/sys/contrib/ia64/libuwx/src/uwx_bstream.h
new file mode 100644
index 0000000..1a64e89
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_bstream.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+struct uwx_bstream {
+ copyin_cb copyin;
+ intptr_t cb_token;
+ uint64_t source;
+ uint64_t buf;
+ unsigned char *bufp;
+ int nbuf;
+ unsigned int ntotal;
+ int request;
+ int peekc;
+};
+
+/* uwx_init_bstream: initialize a byte stream for reading */
+
+extern void uwx_init_bstream(
+ struct uwx_bstream *bstream,
+ struct uwx_env *env,
+ uint64_t source,
+ unsigned int len,
+ int request);
+
+
+/* uwx_get_byte: read the next byte from the byte stream */
+
+extern int uwx_get_byte(struct uwx_bstream *bstream);
+
+
+/* uwx_unget_byte: push a byte back onto the byte stream */
+
+extern int uwx_unget_byte(struct uwx_bstream *bstream, int b);
+
+
+/* uwx_get_uleb128: read a ULEB128 value from the byte stream */
+
+extern int uwx_get_uleb128(struct uwx_bstream *bstream, uint64_t *val);
diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.c b/sys/contrib/ia64/libuwx/src/uwx_context.c
new file mode 100644
index 0000000..9da3db3
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_context.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_context.h"
+#include "uwx_scoreboard.h"
+#include "uwx_trace.h"
+
+int uwx_init_context(
+ struct uwx_env *env,
+ uint64_t ip,
+ uint64_t sp,
+ uint64_t bsp,
+ uint64_t cfm)
+{
+ int i;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ env->context.special[UWX_REG_IP] = ip;
+ env->context.special[UWX_REG_SP] = sp;
+ env->context.special[UWX_REG_BSP] = bsp;
+ env->context.special[UWX_REG_CFM] = cfm;
+ for (i = UWX_REG_RP; i < NSPECIALREG; i++)
+ env->context.special[i] = 0;
+ for (i = 0; i < NPRESERVEDGR; i++)
+ env->context.gr[i] = 0;
+ env->context.valid_regs = VALID_BASIC4;
+ env->rstate = 0;
+ (void)uwx_init_history(env);
+ return UWX_OK;
+}
+
+int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
+{
+ int status;
+ int sor;
+ int rrb_gr;
+ uint64_t bsp;
+ int n;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ status = UWX_OK;
+
+ if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
+ *valp = env->context.special[regid];
+ else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
+ (env->context.valid_regs &
+ (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
+ *valp = env->context.gr[regid - UWX_REG_GR(4)];
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ bsp = env->context.special[UWX_REG_BSP];
+ TRACE_C_GET_REG(regid, bsp)
+ regid -= UWX_REG_GR(32);
+ sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
+ rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
+ if (sor != 0 && rrb_gr != 0 && regid < sor) {
+ TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
+ regid = (regid + rrb_gr) % sor;
+ }
+ bsp = uwx_add_to_bsp(bsp, regid);
+ n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
+ bsp, DWORDSZ, env->cb_token);
+ if (n != DWORDSZ)
+ status = UWX_ERR_COPYIN_RSTK;
+ }
+ else if (regid == UWX_REG_GR(0))
+ *valp = 0;
+ else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
+ (env->context.valid_regs &
+ (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
+ *valp = env->context.br[regid - UWX_REG_BR(1)];
+ else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(5) &&
+ (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
+ valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
+ valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
+ }
+ else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_BR(31) &&
+ (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
+ valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
+ valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
+ }
+ else if ( (regid < NSPECIALREG) ||
+ (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
+ (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
+ regid, DWORDSZ, env->cb_token);
+ if (n != DWORDSZ)
+ status = UWX_ERR_COPYIN_REG;
+ }
+ else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(127)) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
+ regid, 2*DWORDSZ, env->cb_token);
+ if (n != 2*DWORDSZ)
+ status = UWX_ERR_COPYIN_REG;
+ }
+ else if (regid == UWX_REG_FR(0)) {
+ valp[0] = 0;
+ valp[1] = 0;
+ }
+ else if (regid == UWX_REG_FR(1)) {
+ valp[0] = 0x000000000000ffffULL;
+ valp[1] = 0x8000000000000000ULL;
+ }
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
+{
+ int status;
+ int sor;
+ int rrb_gr;
+ uint64_t bsp;
+ uint64_t natcollp;
+ uint64_t natcoll;
+ int n;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ status = UWX_OK;
+
+ if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
+ (env->context.valid_regs &
+ (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
+ *natp = (env->context.special[UWX_REG_PRIUNAT] >>
+ (regid - UWX_REG_GR(4)) ) & 0x01;
+ }
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ bsp = env->context.special[UWX_REG_BSP];
+ regid -= UWX_REG_GR(32);
+ sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
+ rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
+ if (sor != 0 && rrb_gr != 0 && regid < sor) {
+ regid = (regid + rrb_gr) % sor;
+ }
+ bsp = uwx_add_to_bsp(bsp, regid);
+ natcollp = bsp | 0x01f8;
+ if (natcollp >= bsp)
+ n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll,
+ (uint64_t)UWX_REG_RNAT, DWORDSZ, env->cb_token);
+ else
+ n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
+ bsp, DWORDSZ, env->cb_token);
+ if (n != DWORDSZ)
+ return UWX_ERR_COPYIN_RSTK;
+ *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
+ }
+ else if (regid == UWX_REG_GR(0))
+ *natp = 0;
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
+{
+ int status;
+ int sor;
+ int rrb_gr;
+ uint64_t bsp;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ status = UWX_OK;
+
+ if (regid < NSPECIALREG)
+ *dispp = env->history.special[regid];
+ else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
+ *dispp = env->history.gr[regid - UWX_REG_GR(4)];
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ bsp = env->context.special[UWX_REG_BSP];
+ regid -= UWX_REG_GR(32);
+ sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
+ rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
+ if (sor != 0 && rrb_gr != 0 && regid < sor)
+ regid = (regid + rrb_gr) % sor;
+ bsp = uwx_add_to_bsp(bsp, regid);
+ *dispp = UWX_DISP_RSTK(bsp);
+ }
+ else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
+ *dispp = env->history.br[regid - UWX_REG_BR(1)];
+ else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
+ *dispp = env->history.fr[regid - UWX_REG_FR(2)];
+ else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
+ *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
+ else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
+ (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
+ (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
+ *dispp = UWX_DISP_REG(regid);
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
+{
+ int status;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ if (regid < NSPECIALREG) {
+ env->context.special[regid] = val;
+ env->context.valid_regs |= 1 << regid;
+ status = UWX_OK;
+ }
+ else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
+ env->context.gr[regid - UWX_REG_GR(4)] = val;
+ env->context.valid_regs |=
+ 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
+ status = UWX_OK;
+ }
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ status = UWX_ERR_BADREGID;
+ }
+ else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
+ env->context.br[regid - UWX_REG_BR(1)] = val;
+ env->context.valid_regs |=
+ 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
+ status = UWX_OK;
+ }
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
+{
+
+ if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
+ regid -= UWX_REG_FR(2);
+ else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
+ regid -= UWX_REG_FR(16) - 4;
+ else
+ return UWX_ERR_BADREGID;
+
+ env->context.fr[regid].part0 = val[0];
+ env->context.fr[regid].part1 = val[1];
+ env->context.valid_frs |= 1 << regid;
+ env->nsbreg = NSBREG;
+ return UWX_OK;
+}
+
+uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
+{
+ int bias;
+
+ /*
+ * Here's a picture of the backing store as modeled in
+ * the computations below. "X" marks NaT collections at
+ * every 0x1f8 mod 0x200 address.
+ *
+ * To make the NaT adjustments easier, we bias the current bsp
+ * by enough slots to place it at the previous NaT collection.
+ * Then we need to add the bias to the number of slots,
+ * then add 1 for every 63 slots to account for NaT collections.
+ * Then we can remove the bias again and add the adjusted
+ * number of slots to the bsp.
+ *
+ * 0 1f8 3f8
+ * +---------------------------------------------------------------+
+ * | X X|
+ * +---------------------------------------------------------------+
+ * <-------- bias -------->
+ * <--- nslots --->
+ * ^
+ * |
+ * bsp
+ * <------- adjusted (nslots + bias) ------->
+
+ * When subtracting from bsp, we bias the bsp in the opposite
+ * direction so that it is at the next NaT collection.
+ *
+ * 0 1f8 3f8
+ * +---------------------------------------------------------------+
+ * | X X|
+ * +---------------------------------------------------------------+
+ * <------- bias ------->
+ * <--- nslots --->
+ * ^
+ * |
+ * bsp
+ * <------ adjusted (nslots + bias) ------>
+ */
+
+ if (nslots > 0) {
+ bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
+ nslots += (nslots + bias) / 63;
+ }
+ else if (nslots < 0) {
+ bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ;
+ nslots -= (-nslots + bias) / 63;
+ }
+ return bsp + nslots * DWORDSZ;
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.h b/sys/contrib/ia64/libuwx/src/uwx_context.h
new file mode 100644
index 0000000..5f80bf0
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_context.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+extern uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots);
diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.c b/sys/contrib/ia64/libuwx/src/uwx_env.c
new file mode 100644
index 0000000..406d156
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_env.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#else
+#define free(p) /* nullified */
+#define malloc(sz) NULL
+#endif
+
+#include "uwx_env.h"
+#include "uwx_scoreboard.h"
+#include "uwx_str.h"
+#include "uwx_trace.h"
+
+alloc_cb uwx_allocate_cb = 0;
+free_cb uwx_free_cb = 0;
+
+int uwx_register_alloc_cb(alloc_cb alloc, free_cb free)
+{
+ uwx_allocate_cb = alloc;
+ uwx_free_cb = free;
+ return UWX_OK;
+}
+
+int uwx_init_history(struct uwx_env *env)
+{
+ int i;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ for (i = 0; i < NSPECIALREG; i++)
+ env->history.special[i] = UWX_DISP_REG(i);;
+ for (i = 0; i < NPRESERVEDGR; i++)
+ env->history.gr[i] = UWX_DISP_REG(UWX_REG_GR(4+i));
+ for (i = 0; i < NPRESERVEDBR; i++)
+ env->history.br[i] = UWX_DISP_REG(UWX_REG_BR(1+i));
+ for (i = 0; i < 4; i++)
+ env->history.fr[i] = UWX_DISP_REG(UWX_REG_FR(2+i));
+ for ( ; i < NPRESERVEDFR; i++)
+ env->history.fr[i] = UWX_DISP_REG(UWX_REG_FR(12+i));
+
+ return UWX_OK;
+}
+
+struct uwx_env *uwx_init()
+{
+ int i;
+ struct uwx_env *env;
+
+ if (uwx_allocate_cb == 0)
+ env = (struct uwx_env *) malloc(sizeof(struct uwx_env));
+ else
+ env = (struct uwx_env *) (*uwx_allocate_cb)(sizeof(struct uwx_env));
+ if (env != 0) {
+ env->context.valid_regs = 0;
+ env->context.valid_frs = 0;
+ for (i = 0; i < NSPECIALREG; i++)
+ env->context.special[i] = 0;
+ for (i = 0; i < NPRESERVEDGR; i++)
+ env->context.gr[i] = 0;
+ for (i = 0; i < NPRESERVEDBR; i++)
+ env->context.br[i] = 0;
+ for (i = 0; i < NPRESERVEDFR; i++) {
+ env->context.fr[i].part0 = 0;
+ env->context.fr[i].part1 = 0;
+ }
+ env->rstate = 0;
+ env->function_offset = 0;
+ (void)uwx_init_history(env);
+ env->allocate_cb = uwx_allocate_cb;
+ env->free_cb = uwx_free_cb;
+ env->free_scoreboards = 0;
+ env->used_scoreboards = 0;
+ env->labeled_scoreboards = 0;
+ (void)uwx_init_str_pool(env);
+ env->module_name = 0;
+ env->function_name = 0;
+ env->cb_token = 0;
+ env->copyin = 0;
+ env->lookupip = 0;
+ env->remote = 0;
+ env->byte_swap = 0;
+ env->abi_context = 0;
+ env->nsbreg = NSBREG_NOFR;
+ env->nscoreboards = 0;
+ env->trace = 0;
+ TRACE_INIT
+ for (i = 0; i < NSCOREBOARDS; i++)
+ (void) uwx_alloc_scoreboard(env);
+ }
+ return env;
+}
+
+int uwx_set_remote(struct uwx_env *env, int is_big_endian_target)
+{
+ int is_big_endian_host;
+ char *p;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ env->remote = 1;
+
+ is_big_endian_host = 1;
+ p = (char *)&is_big_endian_host;
+ *p = 0;
+ if (is_big_endian_target == is_big_endian_host)
+ env->byte_swap = 0;
+ else
+ env->byte_swap = 1;
+
+ return UWX_OK;
+}
+
+int uwx_register_callbacks(
+ struct uwx_env *env,
+ intptr_t tok,
+ copyin_cb copyin,
+ lookupip_cb lookupip)
+{
+ if (env == 0)
+ return UWX_ERR_NOENV;
+ env->cb_token = tok;
+ env->copyin = copyin;
+ env->lookupip = lookupip;
+ return UWX_OK;
+}
+
+int uwx_get_abi_context_code(struct uwx_env *env)
+{
+ if (env == 0)
+ return UWX_ERR_NOENV;
+ return env->abi_context;
+}
+
+int uwx_free(struct uwx_env *env)
+{
+ if (env != 0) {
+ uwx_free_scoreboards(env);
+ uwx_free_str_pool(env);
+ if (env->free_cb == 0)
+ free((void *)env);
+ else
+ (*env->free_cb)((void *)env);
+ }
+ return UWX_OK;
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_env.h b/sys/contrib/ia64/libuwx/src/uwx_env.h
new file mode 100644
index 0000000..4f662e4
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_env.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx.h"
+
+#define WORDSZ 4
+#define DWORDSZ 8
+#define BUNDLESZ 16
+#define SLOTSPERBUNDLE 3
+
+#define UNWIND_TBL_32BIT 0x8000000000000000LL
+
+#define UNW_VER(x) ((x) >> 48)
+#define UNW_FLAG_MASK 0x0000ffff00000000LL
+#define UNW_FLAG_EHANDLER 0x0000000100000000LL
+#define UNW_FLAG_UHANDLER 0x0000000200000000LL
+#define UNW_LENGTH(x) ((x) & 0x00000000ffffffffLL)
+
+struct uwx_scoreboard;
+
+#define NSCOREBOARDS 8 /* Initial allocation of scoreboards */
+
+#define NSPECIALREG 14
+#define NPRESERVEDGR 4
+#define NPRESERVEDBR 5
+#define NPRESERVEDFR 20
+
+struct uwx_fpreg {
+ uint64_t part0;
+ uint64_t part1;
+};
+
+struct uwx_context {
+ unsigned int valid_regs;
+ unsigned int valid_frs;
+ uint64_t special[NSPECIALREG];
+ uint64_t gr[NPRESERVEDGR];
+ uint64_t br[NPRESERVEDBR];
+ struct uwx_fpreg fr[NPRESERVEDFR];
+};
+
+#define VALID_GR_SHIFT NSPECIALREG
+#define VALID_BR_SHIFT (NSPECIALREG + NPRESERVEDGR)
+
+#define VALID_BASIC4 0x0f /* IP, SP, BSP, PFS */
+
+struct uwx_history {
+ uint64_t special[NSPECIALREG];
+ uint64_t gr[NPRESERVEDGR];
+ uint64_t br[NPRESERVEDBR];
+ uint64_t fr[NPRESERVEDFR];
+};
+
+struct uwx_str_pool;
+
+struct uwx_env {
+ struct uwx_context context;
+ uint64_t *rstate;
+ int64_t function_offset;
+ struct uwx_history history;
+ alloc_cb allocate_cb;
+ free_cb free_cb;
+ struct uwx_scoreboard *free_scoreboards;
+ struct uwx_scoreboard *used_scoreboards;
+ struct uwx_scoreboard *labeled_scoreboards;
+ struct uwx_str_pool *string_pool;
+ char *module_name;
+ char *function_name;
+ intptr_t cb_token;
+ copyin_cb copyin;
+ lookupip_cb lookupip;
+ int remote;
+ int byte_swap;
+ int abi_context;
+ int nsbreg;
+ int nscoreboards;
+ int trace;
+};
+
+extern alloc_cb uwx_allocate_cb;
+extern free_cb uwx_free_cb;
diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c
new file mode 100644
index 0000000..fe37559
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#else
+#define free(p) /* nullified */
+#define malloc(sz) NULL
+#endif
+
+#include "uwx_env.h"
+#include "uwx_scoreboard.h"
+#include "uwx_trace.h"
+
+
+struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env)
+{
+ struct uwx_scoreboard *sb;
+ int i;
+
+ if (env->free_scoreboards != 0) {
+ sb = env->free_scoreboards;
+ env->free_scoreboards = sb->nextfree;
+ TRACE_B_REUSE(sb->id)
+ }
+ else {
+ if (env->allocate_cb == 0)
+ sb = (struct uwx_scoreboard *)
+ malloc(sizeof(struct uwx_scoreboard));
+ else
+ sb = (struct uwx_scoreboard *)
+ (*env->allocate_cb)(sizeof(struct uwx_scoreboard));
+ if (sb == 0)
+ return 0;
+ sb->id = env->nscoreboards++;
+ sb->nextused = env->used_scoreboards;
+ env->used_scoreboards = sb;
+ TRACE_B_ALLOC(sb->id)
+ }
+
+ sb->nextstack = 0;
+ sb->nextlabel = 0;
+ for (i = 0; i < env->nsbreg; i++)
+ sb->rstate[i] = UWX_DISP_NONE;
+ sb->rstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_BR(0));
+ sb->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
+ sb->rstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_PFS);
+ sb->rstate[SBREG_PRIUNAT] = UWX_DISP_REG(UWX_REG_UNAT);
+ sb->label = 0;
+ return sb;
+}
+
+static
+void uwx_reclaim_scoreboards(struct uwx_env *env)
+{
+ struct uwx_scoreboard *sb;
+
+ env->free_scoreboards = 0;
+ for (sb = env->used_scoreboards; sb != 0; sb = sb->nextused) {
+ sb->nextfree = env->free_scoreboards;
+ env->free_scoreboards = sb;
+ }
+ env->labeled_scoreboards = 0;
+}
+
+struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env)
+{
+ struct uwx_scoreboard *sb;
+
+ uwx_reclaim_scoreboards(env);
+ sb = uwx_alloc_scoreboard(env);
+ return sb;
+}
+
+struct uwx_scoreboard *uwx_new_scoreboard(
+ struct uwx_env *env,
+ struct uwx_scoreboard *prevsb)
+{
+ int i;
+ struct uwx_scoreboard *sb;
+
+ sb = uwx_alloc_scoreboard(env);
+ if (sb == 0)
+ return 0;
+ sb->nextstack = prevsb;
+ for (i = 0; i < env->nsbreg; i++)
+ sb->rstate[i] = prevsb->rstate[i];
+ return sb;
+}
+
+struct uwx_scoreboard *uwx_pop_scoreboards(
+ struct uwx_env *env,
+ struct uwx_scoreboard *sb,
+ int ecount)
+{
+ struct uwx_scoreboard *next;
+
+ while (ecount > 0) {
+ next = sb->nextstack;
+ TRACE_B_POP(sb->id)
+ sb->nextstack = 0;
+ sb->nextfree = env->free_scoreboards;
+ env->free_scoreboards = sb;
+ sb = next;
+ if (sb == 0)
+ return 0;
+ ecount--;
+ }
+ return sb;
+}
+
+int uwx_label_scoreboard(
+ struct uwx_env *env,
+ struct uwx_scoreboard *sb,
+ int label)
+{
+ struct uwx_scoreboard *new;
+ struct uwx_scoreboard *back;
+ struct uwx_scoreboard *next;
+ int i;
+
+ TRACE_B_LABEL(label)
+
+ /* Copy the current stack, storing reverse links */
+ /* in the "nextstack" field. */
+
+ back = 0;
+ new = 0;
+ while (sb != 0) {
+ TRACE_B_LABEL_COPY(sb->id)
+ new = uwx_alloc_scoreboard(env);
+ if (new == 0)
+ return UWX_ERR_NOMEM;
+ new->nextstack = back;
+ for (i = 0; i < env->nsbreg; i++)
+ new->rstate[i] = sb->rstate[i];
+ sb = sb->nextstack;
+ back = new;
+ }
+
+ /* The "new" pointer now points to the bottom of the new stack, */
+ /* and the "nextstack" links lead towards the top. */
+ /* Now go back down the stack, reversing the stack links to their */
+ /* proper direction. */
+
+ back = 0;
+ while (new != 0) {
+ next = new->nextstack;
+ new->nextstack = back;
+ TRACE_B_LABEL_REVERSE(back, new)
+ back = new;
+ new = next;
+ }
+
+ /* The "back" pointer now points to the top of the stack. */
+
+ back->label = label;
+ back->nextlabel = env->labeled_scoreboards;
+ env->labeled_scoreboards = back;
+ return UWX_OK;
+}
+
+int uwx_copy_scoreboard(
+ struct uwx_env *env,
+ struct uwx_scoreboard *sb,
+ int label)
+{
+ struct uwx_scoreboard *next;
+ struct uwx_scoreboard *next2;
+ struct uwx_scoreboard *lsb;
+ struct uwx_scoreboard *new;
+ struct uwx_scoreboard *back;
+ int i;
+
+ TRACE_B_COPY(label, sb->id)
+
+ /* Free the existing stack. */
+
+ next = sb->nextstack;
+ while (next != 0) {
+ TRACE_B_COPY_FREE(next->id)
+ next2 = next->nextstack;
+ next->nextstack = 0;
+ next->nextfree = env->free_scoreboards;
+ env->free_scoreboards = next;
+ next = next2;
+ }
+
+ /* Find the scoreboard with the requested label. */
+
+ for (lsb = env->labeled_scoreboards; lsb != 0; lsb = lsb->nextlabel) {
+ if (lsb->label == label)
+ break;
+ }
+
+ if (lsb == 0)
+ return UWX_ERR_UNDEFLABEL;
+
+ TRACE_B_COPY_FOUND(lsb->id)
+
+ /* Copy the labeled scoreboard. */
+
+ sb->nextstack = 0;
+ sb->nextlabel = 0;
+ for (i = 0; i < env->nsbreg; i++)
+ sb->rstate[i] = lsb->rstate[i];
+ sb->label = 0;
+
+ /* Now copy its stack, storing reverse links in the nextstack field. */
+
+ back = sb;
+ new = 0;
+ for (next = lsb->nextstack; next != 0; next = next->nextstack) {
+ TRACE_B_COPY_COPY(next->id)
+ new = uwx_alloc_scoreboard(env);
+ if (new == 0)
+ return UWX_ERR_NOMEM;
+ new->nextstack = back;
+ for (i = 0; i < env->nsbreg; i++)
+ new->rstate[i] = next->rstate[i];
+ back = new;
+ }
+
+ /* The "new" pointer now points to the bottom of the new stack, */
+ /* and the "nextstack" links lead towards the top. */
+ /* Now go back down the stack, reversing the nextstack links to their */
+ /* proper direction. */
+
+ back = 0;
+ while (new != 0) {
+ next = new->nextstack;
+ new->nextstack = back;
+ TRACE_B_COPY_REVERSE(back, new)
+ back = new;
+ new = next;
+ }
+
+ return UWX_OK;
+}
+
+void uwx_free_scoreboards(struct uwx_env *env)
+{
+ struct uwx_scoreboard *sb;
+ struct uwx_scoreboard *next;
+
+ for (sb = env->used_scoreboards; sb != 0; sb = next) {
+ TRACE_B_FREE(sb->id)
+ next = sb->nextused;
+ if (env->free_cb == 0)
+ free((void *)sb);
+ else
+ (*env->free_cb)((void *)sb);
+ }
+ env->free_scoreboards = 0;
+ env->used_scoreboards = 0;
+ env->labeled_scoreboards = 0;
+}
+
diff --git a/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h
new file mode 100644
index 0000000..ff2b4b8
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_scoreboard.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define NSB_SPECIAL 9
+#define NSB_GR 4
+#define NSB_BR 5
+#define NSB_FR 20
+
+#define SBREG_RP 0
+#define SBREG_PSP 1
+#define SBREG_PFS 2
+#define SBREG_PREDS 3
+#define SBREG_UNAT 4
+#define SBREG_PRIUNAT 5
+#define SBREG_RNAT 6
+#define SBREG_LC 7
+#define SBREG_FPSR 8
+#define SBREG_GR (0 + NSB_SPECIAL)
+#define SBREG_BR (SBREG_GR + NSB_GR)
+#define SBREG_FR (SBREG_BR + NSB_BR)
+
+#define NSBREG_NOFR (NSB_SPECIAL + NSB_GR + NSB_BR)
+#define NSBREG (NSB_SPECIAL + NSB_GR + NSB_BR + NSB_FR)
+
+struct uwx_scoreboard {
+ struct uwx_scoreboard *nextused;
+ struct uwx_scoreboard *nextfree;
+ struct uwx_scoreboard *nextstack;
+ struct uwx_scoreboard *nextlabel;
+ uint64_t rstate[NSBREG];
+ int label;
+ int id;
+};
+
+extern struct uwx_scoreboard *uwx_alloc_scoreboard(struct uwx_env *env);
+
+extern struct uwx_scoreboard *uwx_init_scoreboards(struct uwx_env *env);
+
+extern struct uwx_scoreboard *uwx_new_scoreboard(
+ struct uwx_env *env,
+ struct uwx_scoreboard *prevsb);
+
+extern struct uwx_scoreboard *uwx_pop_scoreboards(
+ struct uwx_env *env,
+ struct uwx_scoreboard *sb,
+ int ecount);
+
+extern int uwx_label_scoreboard(
+ struct uwx_env *env,
+ struct uwx_scoreboard *sb,
+ int label);
+
+extern int uwx_copy_scoreboard(
+ struct uwx_env *env,
+ struct uwx_scoreboard *sb,
+ int label);
+
+extern void uwx_free_scoreboards(struct uwx_env *env);
diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.c b/sys/contrib/ia64/libuwx/src/uwx_self.c
new file mode 100644
index 0000000..d1c080e
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_self.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <crt0.h>
+#include <dlfcn.h>
+#include <sys/uc_access.h>
+#endif
+
+#include "uwx_env.h"
+#include "uwx_context.h"
+#include "uwx_trace.h"
+#include "uwx_self.h"
+
+#define UWX_ABI_HPUX_SIGCONTEXT 0x0101 /* abi = HP-UX, context = 1 */
+
+struct uwx_self_info {
+ ucontext_t *ucontext;
+ uint64_t bspstore;
+ uint64_t rvec[10];
+ uint64_t sendsig_start;
+ uint64_t sendsig_end;
+ alloc_cb allocate_cb;
+ free_cb free_cb;
+ int trace;
+};
+
+struct uwx_self_info *uwx_self_init_info(struct uwx_env *env)
+{
+ struct uwx_self_info *info;
+
+ if (env->allocate_cb == 0)
+ info = (struct uwx_self_info *)
+ malloc(sizeof(struct uwx_self_info));
+ else
+ info = (struct uwx_self_info *)
+ (*env->allocate_cb)(sizeof(struct uwx_self_info));
+ if (info == 0)
+ return 0;
+
+ info->ucontext = 0;
+ info->bspstore = 0;
+ info->sendsig_start = __load_info->li_sendsig_txt;
+ info->sendsig_end = __load_info->li_sendsig_txt +
+ __load_info->li_sendsig_tsz;
+ info->allocate_cb = env->allocate_cb;
+ info->free_cb = env->free_cb;
+ info->trace = env->trace;
+ return info;
+}
+
+int uwx_self_free_info(struct uwx_self_info *info)
+{
+ if (info->free_cb == 0)
+ free((void *)info);
+ else
+ (*info->free_cb)((void *)info);
+ return UWX_OK;
+}
+
+int uwx_self_init_from_sigcontext(
+ struct uwx_env *env,
+ struct uwx_self_info *info,
+ ucontext_t *ucontext)
+{
+ int status;
+ uint16_t reason;
+ uint64_t ip;
+ uint64_t sp;
+ uint64_t bsp;
+ uint64_t cfm;
+ unsigned int nat;
+ uint64_t ec;
+
+ info->ucontext = ucontext;
+ status = __uc_get_reason(ucontext, &reason);
+ status = __uc_get_ip(ucontext, &ip);
+ status = __uc_get_grs(ucontext, 12, 1, &sp, &nat);
+ status = __uc_get_ar(ucontext, 17, &bsp);
+ status = __uc_get_ar(ucontext, 18, &info->bspstore);
+ status = __uc_get_ar(ucontext, 66, &ec);
+ status = __uc_get_cfm(ucontext, &cfm);
+ cfm |= ec << 52;
+ if (reason != 0)
+ bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f));
+ uwx_init_context(env, ip, sp, bsp, cfm);
+ return UWX_OK;
+}
+
+int uwx_self_do_context_frame(
+ struct uwx_env *env,
+ struct uwx_self_info *info)
+{
+ int abi_context;
+ int status;
+ uint64_t ucontext;
+
+ abi_context = uwx_get_abi_context_code(env);
+ if (abi_context != UWX_ABI_HPUX_SIGCONTEXT)
+ return UWX_SELF_ERR_BADABICONTEXT;
+ status = uwx_get_reg(env, UWX_REG_GR(32), (uint64_t *)&ucontext);
+ if (status != 0)
+ return status;
+ return uwx_self_init_from_sigcontext(env, info, (ucontext_t *)ucontext);
+}
+
+int uwx_self_copyin(
+ int request,
+ char *loc,
+ uint64_t rem,
+ int len,
+ intptr_t tok)
+{
+ int status;
+ int regid;
+ unsigned int nat;
+ struct uwx_self_info *info = (struct uwx_self_info *) tok;
+ unsigned long *wp;
+ uint64_t *dp;
+
+ dp = (uint64_t *) loc;
+
+ if (request == UWX_COPYIN_UINFO ||
+ request == UWX_COPYIN_MSTACK) {
+ if (len == 4) {
+ wp = (unsigned long *) loc;
+ *wp = *(unsigned long *)rem;
+ TRACE_SELF_COPYIN4(rem, len, wp)
+ }
+ else if (len == 8) {
+ *dp = *(uint64_t *)rem;
+ TRACE_SELF_COPYIN4(rem, len, dp)
+ }
+ else
+ return 0;
+ }
+ else if (request == UWX_COPYIN_RSTACK && len == 8) {
+ if (info->ucontext == 0 || rem < info->bspstore) {
+ *dp = *(uint64_t *)rem;
+ TRACE_SELF_COPYIN4(rem, len, dp)
+ }
+ else {
+ status = __uc_get_rsebs(info->ucontext, (uint64_t *)rem, 1, dp);
+ if (status != 0)
+ return 0;
+ }
+ }
+ else if (request == UWX_COPYIN_REG && len == 8) {
+ if (info->ucontext == 0)
+ return 0;
+ regid = (int)rem;
+ if (rem < UWX_REG_GR(0)) {
+ switch (regid) {
+ case UWX_REG_PFS:
+ status = __uc_get_ar(info->ucontext, 64, dp);
+ break;
+ case UWX_REG_PREDS:
+ status = __uc_get_prs(info->ucontext, dp);
+ break;
+ case UWX_REG_RNAT:
+ status = __uc_get_ar(info->ucontext, 19, dp);
+ break;
+ case UWX_REG_UNAT:
+ status = __uc_get_ar(info->ucontext, 36, dp);
+ break;
+ case UWX_REG_FPSR:
+ status = __uc_get_ar(info->ucontext, 40, dp);
+ break;
+ case UWX_REG_LC:
+ status = __uc_get_ar(info->ucontext, 65, dp);
+ break;
+ default:
+ return 0;
+ }
+ }
+ else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) {
+ status = __uc_get_grs(info->ucontext,
+ regid - UWX_REG_GR(0), 1, dp, &nat);
+ }
+ else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) {
+ status = __uc_get_brs(info->ucontext,
+ regid - UWX_REG_BR(0), 1, dp);
+ }
+ if (status != 0)
+ return 0;
+ }
+ return len;
+}
+
+
+int uwx_self_lookupip(
+ int request,
+ uint64_t ip,
+ intptr_t tok,
+ uint64_t **resultp)
+{
+ struct uwx_self_info *info = (struct uwx_self_info *) tok;
+ UINT64 handle;
+ struct load_module_desc desc;
+ uint64_t *unwind_base;
+ uint64_t *rvec;
+ int i;
+
+ if (request == UWX_LKUP_LOOKUP) {
+ TRACE_SELF_LOOKUP(ip)
+ if (ip >= info->sendsig_start && ip < info->sendsig_end) {
+ i = 0;
+ rvec = info->rvec;
+ rvec[i++] = UWX_KEY_CONTEXT;
+ rvec[i++] = UWX_ABI_HPUX_SIGCONTEXT;
+ rvec[i++] = 0;
+ rvec[i++] = 0;
+ *resultp = rvec;
+ return UWX_LKUP_FDESC;
+ }
+ else {
+ handle = dlmodinfo(ip, &desc, sizeof(desc), 0, 0, 0);
+ if (handle == 0)
+ return UWX_LKUP_ERR;
+ unwind_base = (uint64_t *) desc.unwind_base;
+ TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base)
+ i = 0;
+ rvec = info->rvec;
+ rvec[i++] = UWX_KEY_TBASE;
+ rvec[i++] = desc.text_base;
+ rvec[i++] = UWX_KEY_UFLAGS;
+ rvec[i++] = unwind_base[0];
+ rvec[i++] = UWX_KEY_USTART;
+ rvec[i++] = desc.text_base + unwind_base[1];
+ rvec[i++] = UWX_KEY_UEND;
+ rvec[i++] = desc.text_base + unwind_base[2];
+ rvec[i++] = 0;
+ rvec[i++] = 0;
+ *resultp = rvec;
+ return UWX_LKUP_UTABLE;
+ }
+ }
+ else if (request == UWX_LKUP_FREE) {
+ return 0;
+ }
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_self.h b/sys/contrib/ia64/libuwx/src/uwx_self.h
new file mode 100644
index 0000000..b916235
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_self.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <signal.h>
+#endif
+
+struct uwx_self_info;
+
+extern struct uwx_self_info *uwx_self_init_info(struct uwx_env *env);
+
+extern int uwx_self_free_info(struct uwx_self_info *info);
+
+extern int uwx_self_init_context(struct uwx_env *env);
+
+extern int uwx_self_init_from_sigcontext(
+ struct uwx_env *env,
+ struct uwx_self_info *info,
+ ucontext_t *ucontext);
+
+extern int uwx_self_do_context_frame(
+ struct uwx_env *env,
+ struct uwx_self_info *info);
+
+extern int uwx_self_copyin(
+ int request,
+ char *loc,
+ uint64_t rem,
+ int len,
+ intptr_t tok);
+
+extern int uwx_self_lookupip(
+ int request,
+ uint64_t ip,
+ intptr_t tok,
+ uint64_t **resultp);
+
+#define UWX_SELF_ERR_BADABICONTEXT (-101)
diff --git a/sys/contrib/ia64/libuwx/src/uwx_self_context.s b/sys/contrib/ia64/libuwx/src/uwx_self_context.s
new file mode 100644
index 0000000..fb89e76
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_self_context.s
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef _LP64
+#define SWIZZLE add
+#define STPTR st8
+#else
+#define SWIZZLE addp4
+#define STPTR st4
+#endif
+
+rRP = r14
+rPFS = r15
+rUNAT = r16
+rRNAT = r17
+rENV0 = r18
+rENV1 = r19
+rENV2 = r20
+rNSLOT = r21
+rBSP = r22
+rPBSP = r23
+rRSC = r24
+rNATP = r25
+rBIAS = r26
+rRSC0 = r27
+rTMP1 = r28
+rTMP2 = r29
+rTMP3 = r30
+rTMP4 = r31
+rTMP5 = r8
+
+ .text
+ .proc uwx_self_init_context
+ .global uwx_self_init_context
+uwx_self_init_context:
+ .prologue
+ alloc rPFS = ar.pfs, 1, 0, 0, 0
+ mov rUNAT = ar.unat
+ .body
+ SWIZZLE rENV0 = r0, r32 // rENV0 = &env
+ ;;
+ flushrs
+ extr.u rNSLOT = rPFS, 7, 7 // nslots = pfs.sol
+ mov rRP = b0
+ ;;
+ mov rRSC = ar.rsc
+ add rENV1 = 120, rENV0 // rENV1 = &env->context.gr[0]
+ add rENV2 = 128, rENV0 // rENV2 = &env->context.gr[1]
+ ;;
+ and rRSC0 = -4, rRSC // clear ar.rsc.mode
+ adds rNATP = 0x1f8, r0
+ mov rTMP1 = b1
+ ;;
+ st8.spill [rENV1] = r4, 16 // env+120: r4
+ st8.spill [rENV2] = r5, 16 // env+128: r5
+ mov rTMP2 = b2
+ ;;
+ st8.spill [rENV1] = r6, 16 // env+136: r6
+ st8.spill [rENV2] = r7, 16 // env+144: r7
+ mov rTMP3 = b3
+ ;;
+ st8 [rENV1] = rTMP1, 16 // env+152: b1
+ st8 [rENV2] = rTMP2, 16 // env+160: b2
+ mov rTMP1 = b4
+ ;;
+ st8 [rENV1] = rTMP3, 16 // env+168: b3
+ st8 [rENV2] = rTMP1, 16 // env+176: b4
+ mov rTMP2 = b5
+ ;;
+ st8 [rENV1] = rTMP2 // env+184: b5
+ mov ar.rsc = rRSC0 // enforced lazy mode
+ add rENV1 = 8, rENV0
+ ;;
+ mov rRNAT = ar.rnat // get copy of ar.rnat
+ movl rTMP1 = 0x7fec8f00000000 // valid_regs: ip, sp, bsp, cfm,
+ // preds, rnat, unat, lc, grs, brs
+ ;;
+ mov ar.rsc = rRSC // restore ar.rsc
+ mov rBSP = ar.bsp
+ add rTMP3 = 120, rENV0 // spill_loc = &env->context.gr[0]
+ ;;
+ mov rTMP2 = ar.unat
+ nop
+ extr.u rTMP3 = rTMP3, 3, 6 // bitpos = spill_loc{8:3}
+ ;;
+ or rNATP = rBSP, rNATP // natp = bsp | 0x1f8
+ sub rTMP4 = 64, rTMP3 // (64 - bitpos)
+ shr rTMP5 = rTMP2, rTMP3 // (unat >> bitpos)
+ ;;
+ sub rBIAS = rNATP, rBSP // bias = (natp - bsp) ...
+ nop
+ shl rTMP2 = rTMP2, rTMP4 // (unat << (64 - bitpos))
+ ;;
+ or rTMP2 = rTMP2, rTMP5 // rotate_right(unat, bitpos)
+ extr.u rBIAS = rBIAS, 3, 6 // ... div 8
+ mov rTMP4 = pr
+ ;;
+ st8 [rENV0] = rTMP1, 16 // env+0: valid_regs mask
+ st8 [rENV1] = rRP, 24 // env+8: ip (my rp)
+ add rBIAS = rNSLOT, rBIAS // bias += nslots
+ ;;
+ cmp.lt p6, p0 = 63, rBIAS // if (63 < bias) ...
+ cmp.lt p7, p0 = 126, rBIAS // if (126 < bias) ...
+ nop
+ ;;
+ st8 [rENV0] = r12, 48 // env+16: sp
+ st8 [rENV1] = rPFS, 40 // env+32: cfm (my pfs)
+(p6) add rNSLOT = 1, rNSLOT // ... nslots++
+ ;;
+ st8 [rENV0] = rTMP4, 24 // env+64: preds
+ st8 [rENV1] = rTMP2, 24 // env+72: priunat
+(p7) add rNSLOT = 1, rNSLOT // ... nslots++
+ ;;
+ st8 [rENV0] = rRNAT, -64 // env+88: rnat
+ st8 [rENV1] = rUNAT, 8 // env+96: unat
+ dep.z rTMP3 = rNSLOT, 3, 7 // (nslots << 3)
+ ;;
+ sub rPBSP = rBSP, rTMP3 // prev_bsp = bsp - (nslots << 3)
+ mov rTMP3 = ar.fpsr
+ mov rTMP1 = ar.lc
+ ;;
+ st8 [rENV0] = rPBSP // env+24: bsp (my prev bsp)
+ st8 [rENV1] = rTMP3, 8 // env+104: fpsr
+ add rENV2 = 320, rENV2 // rENV2 = &env->context.rstate
+ ;;
+ st8 [rENV1] = rTMP1 // env+112: lc
+ STPTR [rENV2] = r0 // env+512: env->rstate = 0
+ nop
+ ;;
+ mov ar.unat = rUNAT
+ mov ret0 = r0 // return UWX_OK
+ br.ret.sptk b0
+ .endp
+
diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.c b/sys/contrib/ia64/libuwx/src/uwx_step.c
new file mode 100644
index 0000000..fcbbb5d
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_step.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_context.h"
+#include "uwx_utable.h"
+#include "uwx_uinfo.h"
+#include "uwx_scoreboard.h"
+#include "uwx_str.h"
+#include "uwx_trace.h"
+
+/*
+ * uwx_step.c
+ *
+ * This file contains the routines for stepping from one frame
+ * into its callers frame. The context for the current frame
+ * is maintained inside the current unwind environment
+ * (struct uwx_env), and is updated with each call to
+ * uwx_step() to refer to the previous frame.
+ */
+
+
+/* Forward Declarations */
+
+int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate);
+int uwx_restore_reg(struct uwx_env *env, uint64_t rstate,
+ uint64_t *valp, uint64_t *histp);
+int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat);
+
+
+/* uwx_get_frame_info: Gets unwind info for current frame */
+static
+int uwx_get_frame_info(struct uwx_env *env)
+{
+ int i;
+ int status;
+ int cbstatus;
+ uint64_t *uvec;
+ uint64_t *rstate;
+ struct uwx_utable_entry uentry;
+ uint64_t uvecout[4];
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+ if (env->copyin == 0 || env->lookupip == 0)
+ return UWX_ERR_NOCALLBACKS;
+ if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4)
+ return UWX_ERR_NOCONTEXT;
+
+ env->function_offset = -1LL;
+ env->function_name = 0;
+ env->module_name = 0;
+ uwx_reset_str_pool(env);
+
+ /* Use the lookup IP callback routine to find out about the */
+ /* current IP. If the predicate registers are valid, pass them */
+ /* in the uvec. */
+
+ i = 0;
+ if (env->context.valid_regs & (1 << UWX_REG_PREDS)) {
+ uvecout[i++] = UWX_KEY_PREDS;
+ uvecout[i++] = env->context.special[UWX_REG_PREDS];
+ }
+ uvecout[i++] = UWX_KEY_END;
+ uvecout[i++] = 0;
+ uvec = uvecout;
+ cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP,
+ env->context.special[UWX_REG_IP], env->cb_token, &uvec);
+
+ /* If NOTFOUND, there's nothing we can do but return an error. */
+
+ if (cbstatus == UWX_LKUP_NOTFOUND) {
+ status = UWX_ERR_IPNOTFOUND;
+ }
+
+ /* If the callback returns an unwind table, we need to */
+ /* search the table for an unwind entry that describes the */
+ /* code region of interest, then decode the unwind information */
+ /* associated with that unwind table entry, and store the */
+ /* resulting register state array in the unwind environment */
+ /* block. */
+
+ else if (cbstatus == UWX_LKUP_UTABLE) {
+ status = uwx_search_utable(env, uvec, &uentry);
+ (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
+ if (status == UWX_OK)
+ status = uwx_decode_uinfo(env, &uentry, &rstate);
+ else if (status == UWX_ERR_NOUENTRY)
+ status = uwx_default_rstate(env, &rstate);
+ if (status == UWX_OK)
+ env->rstate = rstate;
+ }
+
+ /* If the callback returns a frame description (in the form */
+ /* of an update vector), convert the update vector into a */
+ /* register state array, then invoke the callback again to */
+ /* let it free any memory it allocated. */
+
+ else if (cbstatus == UWX_LKUP_FDESC) {
+ status = uwx_decode_uvec(env, uvec, &rstate);
+ (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
+ if (status == UWX_OK)
+ env->rstate = rstate;
+ }
+
+ /* Any other return from the callback is an error. */
+
+ else {
+ status = UWX_ERR_LOOKUPERR;
+ }
+ return status;
+}
+
+
+/* uwx_get_sym_info: Gets symbolic info from current frame */
+int uwx_get_sym_info(
+ struct uwx_env *env,
+ char **modp,
+ char **symp,
+ uint64_t *offsetp)
+{
+ int status;
+ int cbstatus;
+ uint64_t ip;
+ uint64_t *uvec;
+ uint64_t uvecout[2];
+ int i;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+ if (env->copyin == 0 || env->lookupip == 0)
+ return UWX_ERR_NOCALLBACKS;
+ if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4)
+ return UWX_ERR_NOCONTEXT;
+
+ /* If we haven't already obtained the frame info for the */
+ /* current frame, get it now. */
+
+ if (env->rstate == 0) {
+ status = uwx_get_frame_info(env);
+ if (status != UWX_OK)
+ return status;
+ }
+
+ /* Get the symbolic information from the lookup IP callback. */
+ if (env->function_name == 0) {
+ ip = env->context.special[UWX_REG_IP];
+ i = 0;
+ if (env->function_offset >= 0) {
+ uvecout[i++] = UWX_KEY_FUNCSTART;
+ uvecout[i++] = ip - env->function_offset;
+ }
+ uvecout[i++] = UWX_KEY_END;
+ uvecout[i++] = 0;
+ uvec = uvecout;
+ cbstatus = (*env->lookupip)(UWX_LKUP_SYMBOLS,
+ env->context.special[UWX_REG_IP], env->cb_token, &uvec);
+
+ if (cbstatus == UWX_LKUP_SYMINFO) {
+ for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
+ switch ((int)uvec[i]) {
+ case UWX_KEY_MODULE:
+ env->module_name =
+ uwx_alloc_str(env, (char *)(uvec[i+1]));
+ break;
+ case UWX_KEY_FUNC:
+ env->function_name =
+ uwx_alloc_str(env, (char *)(uvec[i+1]));
+ break;
+ case UWX_KEY_FUNCSTART:
+ env->function_offset = ip - uvec[i+1];
+ break;
+ }
+ }
+ (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
+ }
+ }
+
+ *modp = env->module_name;
+ *symp = env->function_name;
+ *offsetp = env->function_offset;
+
+ return UWX_OK;
+}
+
+
+/* uwx_step: Steps from the current frame to the previous frame */
+
+int uwx_step(struct uwx_env *env)
+{
+ int i;
+ int status;
+ int pfs_sol;
+ int dispcode;
+ uint64_t val;
+ uint64_t fval[2];
+ uint64_t hist;
+ uint64_t tempgr[NPRESERVEDGR];
+ int needpriunat;
+ int unat;
+ int tempnat;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+ if (env->copyin == 0 || env->lookupip == 0)
+ return UWX_ERR_NOCALLBACKS;
+ if ((env->context.valid_regs & VALID_BASIC4) != VALID_BASIC4)
+ return UWX_ERR_NOCONTEXT;
+
+ /* If we haven't already obtained the frame info for the */
+ /* current frame, get it now. */
+
+ if (env->rstate == 0) {
+ status = uwx_get_frame_info(env);
+ if (status != UWX_OK)
+ return status;
+ }
+
+ TRACE_S_STEP(env->rstate)
+
+ /* Complete the current context by restoring the current values */
+ /* of psp, rp, and pfs. */
+
+ if (env->rstate[SBREG_PSP] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_PSP], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_PSP] = val;
+ env->history.special[UWX_REG_PSP] = hist;
+ TRACE_S_RESTORE_REG("PSP", env->rstate[SBREG_PSP], val)
+ }
+ if (env->rstate[SBREG_RP] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_RP], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_RP] = val;
+ env->history.special[UWX_REG_RP] = hist;
+ TRACE_S_RESTORE_REG("RP", env->rstate[SBREG_RP], val)
+ }
+ if (env->rstate[SBREG_PFS] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_PFS], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_PFS] = val;
+ env->history.special[UWX_REG_PFS] = hist;
+ TRACE_S_RESTORE_REG("PFS", env->rstate[SBREG_PFS], val)
+ }
+
+ /* Check for bottom of stack (rp == 0). */
+
+ if (env->context.special[UWX_REG_RP] == 0)
+ return UWX_BOTTOM;
+
+ /* Find where the primary unat is saved, get a copy. */
+ /* Then, as we restore the GRs, we'll merge the NaT bits into the */
+ /* priunat register in the context. */
+ /* (Make sure we need it, though, before we try to get it, */
+ /* because the attempt to get it might invoke the copy-in callback. */
+ /* We don't need the priunat unless one of GR 4-7 was */
+ /* saved to the memory stack.) */
+
+ needpriunat = 0;
+ for (i = 0; i < NSB_GR; i++) {
+ dispcode = UWX_GET_DISP_CODE(env->rstate[SBREG_GR + i]);
+ if (dispcode == UWX_DISP_SPREL(0) || dispcode == UWX_DISP_PSPREL(0))
+ needpriunat = 1;
+ }
+ unat = 0;
+ if (needpriunat && env->rstate[SBREG_PRIUNAT] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_PRIUNAT], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ unat = (int) val;
+ env->history.special[UWX_REG_PRIUNAT] = hist;
+ TRACE_S_RESTORE_REG("PRIUNAT", env->rstate[SBREG_PRIUNAT], val)
+ }
+
+ /* Retrieve saved values of the preserved GRs into temporaries. */
+
+ tempnat = (int) env->context.special[UWX_REG_PRIUNAT];
+ for (i = 0; i < NSB_GR; i++) {
+ if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env,
+ env->rstate[SBREG_GR + i], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ tempgr[i] = val;
+ if (uwx_restore_nat(env, env->rstate[SBREG_GR + i], unat))
+ tempnat |= 1 << i;
+ else
+ tempnat &= ~(1 << i);
+ env->history.gr[i] = hist;
+ env->context.valid_regs |= 1 << (i + VALID_GR_SHIFT);
+ TRACE_S_RESTORE_GR(i, env->rstate[SBREG_GR + i], val)
+ }
+ }
+
+ /* Now we have everything we need to step back to the previous frame. */
+
+ /* Restore preserved BRs. */
+
+ for (i = 0; i < NSB_BR; i++) {
+ if (env->rstate[SBREG_BR + i] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env,
+ env->rstate[SBREG_BR + i], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.br[i] = val;
+ env->history.br[i] = hist;
+ env->context.valid_regs |= 1 << (i + VALID_BR_SHIFT);
+ TRACE_S_RESTORE_BR(i, env->rstate[SBREG_BR + i], val)
+ }
+ }
+
+ /* Restore preserved FRs. */
+
+ if (env->nsbreg == NSBREG) {
+ for (i = 0; i < NSB_FR; i++) {
+ if (env->rstate[SBREG_FR + i] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env,
+ env->rstate[SBREG_FR + i], fval, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.fr[i].part0 = fval[0];
+ env->context.fr[i].part1 = fval[1];
+ env->history.fr[i] = hist;
+ env->context.valid_frs |= 1 << i;
+ TRACE_S_RESTORE_FR(i, env->rstate[SBREG_FR + i], fval)
+ }
+ }
+ }
+
+ /* Restore other preserved regs. */
+
+ if (env->rstate[SBREG_PREDS] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_PREDS], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_PREDS] = val;
+ env->history.special[UWX_REG_PREDS] = hist;
+ env->context.valid_regs |= 1 << UWX_REG_PREDS;
+ TRACE_S_RESTORE_REG("PREDS", env->rstate[SBREG_PREDS], val)
+ }
+ if (env->rstate[SBREG_RNAT] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_RNAT], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_RNAT] = val;
+ env->history.special[UWX_REG_RNAT] = hist;
+ env->context.valid_regs |= 1 << UWX_REG_RNAT;
+ TRACE_S_RESTORE_REG("RNAT", env->rstate[SBREG_RNAT], val)
+ }
+ if (env->rstate[SBREG_UNAT] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_UNAT], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_UNAT] = val;
+ env->history.special[UWX_REG_UNAT] = hist;
+ env->context.valid_regs |= 1 << UWX_REG_UNAT;
+ TRACE_S_RESTORE_REG("UNAT", env->rstate[SBREG_UNAT], val)
+ }
+ if (env->rstate[SBREG_FPSR] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_FPSR], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_FPSR] = val;
+ env->history.special[UWX_REG_FPSR] = hist;
+ env->context.valid_regs |= 1 << UWX_REG_FPSR;
+ TRACE_S_RESTORE_REG("FPSR", env->rstate[SBREG_FPSR], val)
+ }
+ if (env->rstate[SBREG_LC] != UWX_DISP_NONE) {
+ status = uwx_restore_reg(env, env->rstate[SBREG_LC], &val, &hist);
+ if (status != UWX_OK)
+ return status;
+ env->context.special[UWX_REG_LC] = val;
+ env->history.special[UWX_REG_LC] = hist;
+ env->context.valid_regs |= 1 << UWX_REG_LC;
+ TRACE_S_RESTORE_REG("LC", env->rstate[SBREG_LC], val)
+ }
+
+ /* Restore preserved GRs from temporaries. */
+
+ for (i = 0; i < NSB_GR; i++) {
+ if (env->rstate[SBREG_GR + i] != UWX_DISP_NONE)
+ env->context.gr[i] = tempgr[i];
+ }
+ env->context.special[UWX_REG_PRIUNAT] = tempnat;
+
+ /* Restore the frame markers. */
+
+ env->context.special[UWX_REG_IP] = env->context.special[UWX_REG_RP];
+ env->history.special[UWX_REG_IP] = env->history.special[UWX_REG_RP];
+
+ env->context.special[UWX_REG_SP] = env->context.special[UWX_REG_PSP];
+ env->history.special[UWX_REG_SP] = env->history.special[UWX_REG_PSP];
+
+ pfs_sol = ((unsigned int)env->context.special[UWX_REG_PFS] >> 7) & 0x7f;
+ env->context.special[UWX_REG_BSP] = uwx_add_to_bsp(
+ env->context.special[UWX_REG_BSP],
+ -pfs_sol);
+
+ env->context.special[UWX_REG_CFM] = env->context.special[UWX_REG_PFS];
+ env->history.special[UWX_REG_CFM] = env->history.special[UWX_REG_PFS];
+
+ env->context.special[UWX_REG_RP] = 0;
+
+ /* The frame info for the new frame isn't yet available. */
+
+ env->rstate = 0;
+
+ return UWX_OK;
+}
+
+
+/* uwx_decode_uvec: Converts the update vector into a register state array */
+
+int uwx_decode_uvec(struct uwx_env *env, uint64_t *uvec, uint64_t **rstate)
+{
+ while (*uvec != 0) {
+ switch ((int)*uvec++) {
+ case UWX_KEY_CONTEXT:
+ env->abi_context = (int)(*uvec++);
+ return UWX_ABI_FRAME;
+ default:
+ return UWX_ERR_CANTUNWIND;
+ }
+ }
+ return UWX_OK;
+}
+
+
+/* uwx_restore_reg: Restores a register according to the scoreboard */
+
+#define COPYIN_MSTACK_8(dest, src) \
+ (env->remote? \
+ (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \
+ DWORDSZ, env->cb_token) : \
+ (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) )
+
+int uwx_restore_reg(struct uwx_env *env, uint64_t rstate,
+ uint64_t *valp, uint64_t *histp)
+{
+ int status;
+ uint64_t p;
+ int n;
+ int regid;
+
+ status = UWX_OK;
+
+ switch (UWX_GET_DISP_CODE(rstate)) {
+ case UWX_DISP_SPPLUS(0):
+ *valp = env->context.special[UWX_REG_SP] +
+ UWX_GET_DISP_OFFSET(rstate);
+ *histp = UWX_DISP_NONE;
+ break;
+ case UWX_DISP_SPREL(0):
+ p = env->context.special[UWX_REG_SP] +
+ UWX_GET_DISP_OFFSET(rstate);
+ n = COPYIN_MSTACK_8((char *)valp, p);
+ if (n != DWORDSZ)
+ status = UWX_ERR_COPYIN_MSTK;
+ *histp = UWX_DISP_MSTK(p);
+ break;
+ case UWX_DISP_PSPREL(0):
+ p = env->context.special[UWX_REG_PSP] + 16 -
+ UWX_GET_DISP_OFFSET(rstate);
+ n = COPYIN_MSTACK_8((char *)valp, p);
+ if (n != DWORDSZ)
+ status = UWX_ERR_COPYIN_MSTK;
+ *histp = UWX_DISP_MSTK(p);
+ break;
+ case UWX_DISP_REG(0):
+ regid = UWX_GET_DISP_REGID(rstate);
+ status = uwx_get_reg(env, regid, valp);
+ (void) uwx_get_spill_loc(env, regid, histp);
+ break;
+ }
+ return status;
+}
+
+/* uwx_restore_nat: Returns the saved NaT bit for a preserved GR */
+
+int uwx_restore_nat(struct uwx_env *env, uint64_t rstate, int unat)
+{
+ int nat;
+ uint64_t p;
+
+ nat = 0;
+ switch (UWX_GET_DISP_CODE(rstate)) {
+ case UWX_DISP_SPREL(0):
+ p = env->context.special[UWX_REG_SP] +
+ UWX_GET_DISP_OFFSET(rstate);
+ nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01;
+ break;
+ case UWX_DISP_PSPREL(0):
+ p = env->context.special[UWX_REG_PSP] + 16 -
+ UWX_GET_DISP_OFFSET(rstate);
+ nat = (unat >> (((int)p >> 3) & 0x3f)) & 0x01;
+ break;
+ case UWX_DISP_REG(0):
+ (void) uwx_get_nat(env, UWX_GET_DISP_REGID(rstate), &nat);
+ break;
+ }
+ return nat;
+}
+
diff --git a/sys/contrib/ia64/libuwx/src/uwx_str.c b/sys/contrib/ia64/libuwx/src/uwx_str.c
new file mode 100644
index 0000000..9ad1ec3
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_str.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_str.h"
+
+#ifdef _KERNEL
+#define free(p) /* nullified */
+#define malloc(sz) NULL
+#endif
+
+/*
+ * uwx_str.c
+ *
+ * This file contains the routines for maintaining a string
+ * pool for the unwind environment. We preallocate enough
+ * space for most purposes so that no memory allocation is
+ * necessary during a normal unwind. If we do need more,
+ * we use the allocate callback, if one is provided.
+ *
+ * The string pool is reused with each call to step(),
+ * and is completely freed when the unwind environment is
+ * freed.
+ */
+
+
+int uwx_init_str_pool(struct uwx_env *env)
+{
+ if (env->allocate_cb == 0)
+ env->string_pool = (struct uwx_str_pool *)
+ malloc(sizeof(struct uwx_str_pool));
+ else
+ env->string_pool = (struct uwx_str_pool *)
+ (*env->allocate_cb)(sizeof(struct uwx_str_pool));
+
+ if (env->string_pool == 0)
+ return UWX_ERR_NOMEM;
+
+ env->string_pool->next = 0;
+ env->string_pool->size = STRPOOLSIZE;
+ env->string_pool->used = 0;
+
+ return UWX_OK;
+}
+
+void uwx_free_str_pool(struct uwx_env *env)
+{
+ struct uwx_str_pool *pool;
+ struct uwx_str_pool *next;
+
+ for (pool = env->string_pool; pool != 0; pool = next) {
+ next = pool->next;
+ if (env->free_cb == 0)
+ free(pool);
+ else
+ (*env->free_cb)(pool);
+ }
+}
+
+char *uwx_alloc_str(struct uwx_env *env, char *str)
+{
+ int len;
+ int size;
+ struct uwx_str_pool *pool;
+ struct uwx_str_pool *prev;
+ char *p;
+
+ len = strlen(str) + 1;
+ prev = 0;
+ for (pool = env->string_pool; pool != 0; pool = pool->next) {
+ prev = pool;
+ if (pool->size - pool->used >= len)
+ break;
+ }
+ if (pool == 0) {
+ size = STRPOOLSIZE;
+ if (len > size)
+ size = len;
+ size += sizeof(struct uwx_str_pool) - STRPOOLSIZE;
+ if (env->allocate_cb == 0)
+ pool = (struct uwx_str_pool *) malloc(size);
+ else
+ pool = (struct uwx_str_pool *) (*env->allocate_cb)(size);
+ if (env->string_pool == 0)
+ return 0;
+ pool->next = 0;
+ pool->size = size;
+ pool->used = 0;
+ prev->next = pool;
+ }
+ p = pool->pool + pool->used;
+ strcpy(p, str);
+ pool->used += len;
+ return p;
+}
+
+void uwx_reset_str_pool(struct uwx_env *env)
+{
+ struct uwx_str_pool *pool;
+
+ for (pool = env->string_pool; pool != 0; pool = pool->next)
+ pool->used = 0;
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_str.h b/sys/contrib/ia64/libuwx/src/uwx_str.h
new file mode 100644
index 0000000..98f7516
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_str.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define STRPOOLSIZE 400
+
+struct uwx_str_pool {
+ struct uwx_str_pool *next;
+ int size;
+ int used;
+ char pool[STRPOOLSIZE];
+};
+
+extern int uwx_init_str_pool(struct uwx_env *env);
+extern void uwx_free_str_pool(struct uwx_env *env);
+extern char *uwx_alloc_str(struct uwx_env *env, char *str);
+extern void uwx_reset_str_pool(struct uwx_env *env);
diff --git a/sys/contrib/ia64/libuwx/src/uwx_swap.c b/sys/contrib/ia64/libuwx/src/uwx_swap.c
new file mode 100644
index 0000000..237bd90
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_swap.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_swap.h"
+
+void uwx_swap4(uint32_t *w)
+{
+ unsigned char *p;
+ unsigned char t[4];
+
+ p = (unsigned char *) w;
+
+ t[0] = p[0];
+ t[1] = p[1];
+ t[2] = p[2];
+ t[3] = p[3];
+
+ p[0] = t[3];
+ p[1] = t[2];
+ p[2] = t[1];
+ p[3] = t[0];
+}
+
+void uwx_swap8(uint64_t *dw)
+{
+ unsigned char *p;
+ unsigned char t[8];
+
+ p = (unsigned char *) dw;
+
+ t[0] = p[0];
+ t[1] = p[1];
+ t[2] = p[2];
+ t[3] = p[3];
+ t[4] = p[4];
+ t[5] = p[5];
+ t[6] = p[6];
+ t[7] = p[7];
+
+ p[0] = t[7];
+ p[1] = t[6];
+ p[2] = t[5];
+ p[3] = t[4];
+ p[4] = t[3];
+ p[5] = t[2];
+ p[6] = t[1];
+ p[7] = t[0];
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_swap.h b/sys/contrib/ia64/libuwx/src/uwx_swap.h
new file mode 100644
index 0000000..edceaaf
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_swap.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+extern void uwx_swap4(uint32_t *w);
+extern void uwx_swap8(uint64_t *dw);
diff --git a/sys/contrib/ia64/libuwx/src/uwx_trace.c b/sys/contrib/ia64/libuwx/src/uwx_trace.c
new file mode 100644
index 0000000..695192a
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_trace.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_uinfo.h"
+#include "uwx_scoreboard.h"
+#include "uwx_trace.h"
+
+void uwx_trace_init(struct uwx_env *env)
+{
+ char *tstr;
+
+ tstr = getenv("UWX_TRACE");
+ if (tstr != NULL) {
+ while (*tstr != '\0') {
+ switch (*tstr) {
+ case 'i': env->trace |= UWX_TRACE_UINFO; break;
+ case 't': env->trace |= UWX_TRACE_UTABLE; break;
+ case 'b': env->trace |= UWX_TRACE_SB; break;
+ case 'r': env->trace |= UWX_TRACE_RSTATE; break;
+ case 's': env->trace |= UWX_TRACE_STEP; break;
+ case 'c': env->trace |= UWX_TRACE_CONTEXT; break;
+ case 'C': env->trace |= UWX_TRACE_COPYIN; break;
+ case 'L': env->trace |= UWX_TRACE_LOOKUPIP; break;
+ case '?':
+#ifdef _KERNEL
+ printf("UWX_TRACE flag `%c' unknown.\n", *tstr);
+#else
+ fprintf(stderr, "UWX_TRACE flags:\n");
+ fprintf(stderr, " i: unwind info\n");
+ fprintf(stderr, " t: unwind table searching\n");
+ fprintf(stderr, " b: scoreboard management\n");
+ fprintf(stderr, " r: register state vector\n");
+ fprintf(stderr, " s: step\n");
+ fprintf(stderr, " c: context\n");
+ fprintf(stderr, " C: copyin callback\n");
+ fprintf(stderr, " L: lookup ip callback\n");
+ exit(1);
+#endif
+ }
+ tstr++;
+ }
+ }
+}
+
+char *uwx_sb_rnames[] = {
+ "RP", "PSP", "PFS",
+ "PREDS", "UNAT", "PRIUNAT", "RNAT", "LC", "FPSR",
+ "GR4", "GR5", "GR6", "GR7",
+ "BR1", "BR2", "BR3", "BR4", "BR5",
+ "FR2", "FR3", "FR4", "FR5",
+ "FR16", "FR17", "FR18", "FR19",
+ "FR20", "FR21", "FR22", "FR23",
+ "FR24", "FR25", "FR26", "FR27",
+ "FR28", "FR29", "FR30", "FR31",
+};
+
+void uwx_dump_rstate(int regid, uint64_t rstate)
+{
+ int reg;
+
+ if (rstate == UWX_DISP_NONE)
+ return;
+ printf(" %-7s", uwx_sb_rnames[regid]);
+ switch (UWX_GET_DISP_CODE(rstate)) {
+ case UWX_DISP_NONE:
+ printf(" unchanged\n");
+ break;
+ case UWX_DISP_SPPLUS(0):
+ printf(" SP + %d\n", (int)rstate & ~0x07);
+ break;
+ case UWX_DISP_SPREL(0):
+ printf(" [SP + %d]\n", (int)rstate & ~0x07);
+ break;
+ case UWX_DISP_PSPREL(0):
+ printf(" [PSP + 16 - %d]\n", (int)rstate & ~0x07);
+ break;
+ case UWX_DISP_REG(0):
+ reg = UWX_GET_DISP_REGID(rstate);
+ if (reg == UWX_REG_PFS)
+ printf(" [AR.PFS]\n");
+ else if (reg == UWX_REG_UNAT)
+ printf(" [AR.UNAT]\n");
+ else if (reg >= UWX_REG_GR(0) && reg < UWX_REG_GR(128))
+ printf(" [GR%d]\n", reg - UWX_REG_GR(0));
+ else if (reg >= UWX_REG_FR(0) && reg < UWX_REG_FR(128))
+ printf(" [FR%d]\n", reg - UWX_REG_FR(0));
+ else if (reg >= UWX_REG_BR(0) && reg < UWX_REG_BR(8))
+ printf(" [BR%d]\n", reg - UWX_REG_BR(0));
+ else
+ printf(" [reg %d]\n", reg);
+ break;
+ default:
+ printf(" <%08llx>\n", (unsigned long long)rstate);
+ break;
+ }
+}
+
+void uwx_dump_scoreboard(
+ struct uwx_scoreboard *scoreboard,
+ int nsbreg,
+ struct uwx_rhdr *rhdr,
+ int cur_slot,
+ int ip_slot)
+{
+ int i;
+
+ if (rhdr->is_prologue)
+ printf(" Prologue region (start = %d, length = %d)\n",
+ (int)cur_slot, (int)rhdr->rlen);
+ else
+ printf(" Body region (start = %d, length = %d, ecount = %d)\n",
+ cur_slot, (int)rhdr->rlen, rhdr->ecount);
+ if (ip_slot < rhdr->rlen)
+ printf(" IP is in this region (offset = %d)\n", ip_slot);
+ for (i = 0; i < nsbreg; i++)
+ uwx_dump_rstate(i, scoreboard->rstate[i]);
+}
+
diff --git a/sys/contrib/ia64/libuwx/src/uwx_trace.h b/sys/contrib/ia64/libuwx/src/uwx_trace.h
new file mode 100644
index 0000000..4b8cdaa
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_trace.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define UWX_TRACE_SB 1 /* UWX_TRACE=b: scoreboard mgmt */
+#define UWX_TRACE_UINFO 2 /* UWX_TRACE=i: unwind info */
+#define UWX_TRACE_RSTATE 4 /* UWX_TRACE=r: reg state vector */
+#define UWX_TRACE_STEP 8 /* UWX_TRACE=s: step */
+#define UWX_TRACE_UTABLE 16 /* UWX_TRACE=t: unwind tbl search */
+#define UWX_TRACE_CONTEXT 32 /* UWX_TRACE=c: context */
+#define UWX_TRACE_COPYIN 64 /* UWX_TRACE=C: copyin callback */
+#define UWX_TRACE_LOOKUPIP 128 /* UWX_TRACE=L: lookupip callback */
+
+#ifdef DISABLE_TRACE
+
+#define TRACE_INIT
+#define TRACE_B_REUSE(id)
+#define TRACE_B_ALLOC(id)
+#define TRACE_B_POP(id)
+#define TRACE_B_LABEL(label)
+#define TRACE_B_LABEL_COPY(id)
+#define TRACE_B_LABEL_REVERSE(back, new)
+#define TRACE_B_COPY(label, id)
+#define TRACE_B_COPY_FREE(id)
+#define TRACE_B_COPY_FOUND(id)
+#define TRACE_B_COPY_COPY(id)
+#define TRACE_B_COPY_REVERSE(back, new)
+#define TRACE_B_FREE(id)
+#define TRACE_I_DECODE_RHDR_1(name, b0)
+#define TRACE_I_DECODE_RHDR_1L(name, b0, val)
+#define TRACE_I_DECODE_RHDR_2L(name, b0, b1, val)
+#define TRACE_I_DECODE_PROLOGUE_1(name, b0)
+#define TRACE_I_DECODE_PROLOGUE_1L(name, b0, val)
+#define TRACE_I_DECODE_PROLOGUE_1LL(name, b0, val1, val2)
+#define TRACE_I_DECODE_PROLOGUE_2(name, b0, b1)
+#define TRACE_I_DECODE_PROLOGUE_2L(name, b0, b1, parm1)
+#define TRACE_I_DECODE_PROLOGUE_3(name, b0, b1, b2)
+#define TRACE_I_DECODE_PROLOGUE_4(name, b0, b1, b2, b3)
+#define TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base)
+#define TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask)
+#define TRACE_I_DECODE_PROLOGUE_NSPILL(ngr)
+#define TRACE_I_DECODE_BODY_1(name, b0)
+#define TRACE_I_DECODE_BODY_1L(name, b0, parm1)
+#define TRACE_I_DECODE_BODY_1LL(name, b0, parm1, parm2)
+#define TRACE_R_UIB(uentry, ulen)
+#define TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot)
+#define TRACE_S_STEP(rstate)
+#define TRACE_S_RESTORE_REG(regname, rstate, val)
+#define TRACE_S_RESTORE_GR(regid, rstate, val)
+#define TRACE_S_RESTORE_BR(regid, rstate, val)
+#define TRACE_S_RESTORE_FR(regid, rstate, val)
+#define TRACE_T_SEARCH32(ip)
+#define TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end)
+#define TRACE_C_GET_REG(regid, bsp)
+#define TRACE_C_ROTATE_GR(regid, sor, rrb_gr, newregid)
+#define TRACE_SELF_COPYIN4(rem, len, wp)
+#define TRACE_SELF_COPYIN8(rem, len, dp)
+#define TRACE_SELF_LOOKUP(ip)
+#define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base)
+
+#else /* not TRACE_DISABLED */
+
+extern void uwx_trace_init(struct uwx_env *env);
+
+extern void uwx_dump_rstate(int regid, uint64_t rstate);
+
+struct uwx_rhdr;
+
+extern void uwx_dump_scoreboard(
+ struct uwx_scoreboard *scoreboard,
+ int nsbreg,
+ struct uwx_rhdr *rhdr,
+ int cur_slot,
+ int ip_slot);
+
+#define TRACE_INIT uwx_trace_init(env);
+
+#define TRACE_B_REUSE(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_alloc_scoreboard: reuse id %d\n", (id));
+
+#define TRACE_B_ALLOC(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_alloc_scoreboard: alloc id %d\n", (id));
+
+#define TRACE_B_POP(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_pop_scoreboards: free id %d\n", (id));
+
+#define TRACE_B_LABEL(label) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_label_scoreboard: label %d\n", (label));
+
+#define TRACE_B_LABEL_COPY(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_label_scoreboard: copy id %d\n", (id));
+
+#define TRACE_B_LABEL_REVERSE(back, new) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_label_scoreboard: reverse link %d -> %d\n", \
+ (new)->id, ((back) == 0) ? -1 : (back)->id);
+
+#define TRACE_B_COPY(label, id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_copy_scoreboard: label %d, cur sb id %d\n", (label), (id));
+
+#define TRACE_B_COPY_FREE(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_copy_scoreboard: free id %d\n", (id));
+
+#define TRACE_B_COPY_FOUND(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_copy_scoreboard: found id %d\n", (id));
+
+#define TRACE_B_COPY_COPY(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_copy_scoreboard: copy id %d\n", (id));
+
+#define TRACE_B_COPY_REVERSE(back, new) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_copy_scoreboard: reverse link %d -> %d\n", \
+ (new)->id, ((back) == 0) ? -1 : (back)->id);
+
+#define TRACE_B_FREE(id) \
+ if (env->trace & UWX_TRACE_SB) \
+ printf("uwx_free_scoreboards: free id %d\n", (id));
+
+#define TRACE_I_DECODE_RHDR_1(name, b0) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_rhdr: %02x %s\n", \
+ (b0), (name));
+
+#define TRACE_I_DECODE_RHDR_1L(name, b0, val) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_rhdr: %02x %08x %s\n", \
+ (b0), (int)(val), (name));
+
+#define TRACE_I_DECODE_RHDR_2L(name, b0, b1, val) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_rhdr: %02x %02x %08x %s\n", \
+ (b0), (b1), (int)(val), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_1(name, b0) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %s\n", \
+ (b0), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_1L(name, b0, val) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %08x %s\n", \
+ (b0), (int)(val), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_1LL(name, b0, val1, val2) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %08x %08x %s\n", \
+ (b0), (int)(val1), (int)(val2), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_2(name, b0, b1) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %02x %s\n", \
+ (b0), (b1), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_2L(name, b0, b1, val) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %02x %08x %s\n", \
+ (b0), (b1), (int)(val), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_3(name, b0, b1, b2) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %02x %02x %s\n", \
+ (b0), (b1), (b2), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_4(name, b0, b1, b2, b3) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: %02x %02x %02x %02x %s\n", \
+ (b0), (b1), (b2), (b3), (name));
+
+#define TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: spill base = %08x\n", (int)(spill_base));
+
+#define TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: gr_mem_mask = %02x; gr_gr_mask = %02x\n", \
+ (gr_mem_mask), (gr_gr_mask));
+
+#define TRACE_I_DECODE_PROLOGUE_NSPILL(ngr) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_prologue: ngr = %d\n", (ngr));
+
+#define TRACE_I_DECODE_BODY_1(name, b0) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_body: %02x %s\n", \
+ (b0), (name));
+
+#define TRACE_I_DECODE_BODY_1L(name, b0, val) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_body: %02x %08x %s\n", \
+ (b0), (int)(val), (name));
+
+#define TRACE_I_DECODE_BODY_1LL(name, b0, val1, val2) \
+ if (env->trace & UWX_TRACE_UINFO) \
+ printf("uwx_decode_body: %02x %08x %08x %s\n", \
+ (b0), (int)(val1), (int)(val2), (name));
+
+#define TRACE_R_UIB(uentry, ulen) \
+ if (env->trace & UWX_TRACE_RSTATE) \
+ printf("Unwind info block (flags = %08x %08x, ulen = %d)\n", \
+ (unsigned int)((uentry)->unwind_flags >> 32), \
+ (unsigned int)(uentry)->unwind_flags, \
+ (ulen));
+
+#define TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot) \
+ if (env->trace & UWX_TRACE_RSTATE) \
+ uwx_dump_scoreboard(scoreboard, env->nsbreg, \
+ &(rhdr), cur_slot, ip_slot);
+
+#define TRACE_S_STEP(rstate) \
+ if (env->trace & UWX_TRACE_STEP) { \
+ printf("uwx_step:\n"); \
+ uwx_dump_rstate(SBREG_RP, (rstate)[SBREG_RP]); \
+ uwx_dump_rstate(SBREG_PSP, (rstate)[SBREG_PSP]); \
+ uwx_dump_rstate(SBREG_PFS, (rstate)[SBREG_PFS]); \
+ }
+
+#define TRACE_S_RESTORE_REG(regname, rstate, val) \
+ if (env->trace & UWX_TRACE_STEP) \
+ printf(" restore %-7s (rstate = %08x %08x) = %08x %08x\n", \
+ regname, \
+ (unsigned int) ((rstate) >> 32), \
+ (unsigned int) (rstate), \
+ (unsigned int) ((val) >> 32), \
+ (unsigned int) (val));
+
+#define TRACE_S_RESTORE_GR(regid, rstate, val) \
+ if (env->trace & UWX_TRACE_STEP) \
+ printf(" restore GR%d (rstate = %08x %08x) = %08x %08x\n", \
+ (regid) + 4, \
+ (unsigned int) ((rstate) >> 32), \
+ (unsigned int) (rstate), \
+ (unsigned int) ((val) >> 32), \
+ (unsigned int) (val));
+
+#define TRACE_S_RESTORE_BR(regid, rstate, val) \
+ if (env->trace & UWX_TRACE_STEP) \
+ printf(" restore BR%d (rstate = %08x %08x) = %08x %08x\n", \
+ (regid) + 1, \
+ (unsigned int) ((rstate) >> 32), \
+ (unsigned int) (rstate), \
+ (unsigned int) ((val) >> 32), \
+ (unsigned int) (val));
+
+#define TRACE_S_RESTORE_FR(regid, rstate, fval) \
+ if (env->trace & UWX_TRACE_STEP) \
+ printf(" restore FR%d (rstate = %08x %08x) = %08x %08x %08x %08x\n", \
+ (regid) + 1, \
+ (unsigned int) ((rstate) >> 32), \
+ (unsigned int) (rstate), \
+ (unsigned int) ((fval[0]) >> 32), \
+ (unsigned int) (fval[0]), \
+ (unsigned int) ((fval[1]) >> 32), \
+ (unsigned int) (fval[1]));
+
+#define TRACE_T_SEARCH32(ip) \
+ if (env->trace & UWX_TRACE_UTABLE) \
+ printf("uwx_search_utable32 (relative ip = %08x)\n", (ip));
+
+#define TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end) \
+ if (env->trace & UWX_TRACE_UTABLE) \
+ printf(" lb/ub = %d/%d, mid = %d, start/end = %08x %08x\n", \
+ lb, ub, mid, code_start, code_end);
+
+#define TRACE_C_GET_REG(regid, bsp) \
+ if (env->trace & UWX_TRACE_CONTEXT) \
+ printf("uwx_get_reg (gr%d, bsp = %08x %08x)\n", \
+ (regid) - UWX_REG_GR(0), \
+ (unsigned int) ((bsp) >> 32), \
+ (unsigned int) (bsp));
+
+#define TRACE_C_ROTATE_GR(regid, sor, rrb_gr, newregid) \
+ if (env->trace & UWX_TRACE_CONTEXT) \
+ printf("uwx_get_reg (gr%d, sor = %d, rrb = %d) --> gr%d\n", \
+ (regid) + 32, \
+ (sor), \
+ (rrb_gr), \
+ (newregid) + 32);
+
+#define TRACE_SELF_COPYIN4(rem, len, wp) \
+ if (info->trace & UWX_TRACE_COPYIN) \
+ printf("copyin (rem = %08x %08x, len = %d, val = %08x)\n", \
+ (unsigned int) ((rem) >> 32), \
+ (unsigned int) (rem), \
+ (len), *(wp));
+
+#define TRACE_SELF_COPYIN8(rem, len, dp) \
+ if (info->trace & UWX_TRACE_COPYIN) \
+ printf("copyin (rem = %08x %08x, len = %d, val = %08x %08x)\n", \
+ (unsigned int) ((rem) >> 32), \
+ (unsigned int) (rem), \
+ (len), \
+ ((unsigned int *)(dp))[0], \
+ ((unsigned int *)(dp))[1]);
+
+#define TRACE_SELF_LOOKUP(ip) \
+ if (info->trace & UWX_TRACE_LOOKUPIP) \
+ printf("Lookup IP callback: ip = %08x %08x\n", \
+ (unsigned int) ((ip) >> 32), \
+ (unsigned int) (ip));
+
+#define TRACE_SELF_LOOKUP_DESC(text_base, unwind_base) \
+ if (info->trace & UWX_TRACE_LOOKUPIP) { \
+ printf(" text base: %08x %08x\n", \
+ (unsigned int) ((text_base) >> 32), \
+ (unsigned int) (text_base)); \
+ printf(" unwind base: %08x %08x\n", \
+ (unsigned int) ((uint64_t)(unwind_base) >> 32), \
+ (unsigned int) (unwind_base)); \
+ printf(" unwind flags: %08x %08x\n", \
+ (unsigned int) ((unwind_base)[0] >> 32), \
+ (unsigned int) (unwind_base)[0]); \
+ printf(" unwind start: %08x %08x\n", \
+ (unsigned int) (((text_base)+(unwind_base)[1]) >> 32), \
+ (unsigned int) ((text_base)+(unwind_base)[1])); \
+ printf(" unwind end: %08x %08x\n", \
+ (unsigned int) (((text_base)+(unwind_base)[2]) >> 32), \
+ (unsigned int) ((text_base)+(unwind_base)[2])); \
+ }
+
+#endif /* TRACE_DISABLED */
+
diff --git a/sys/contrib/ia64/libuwx/src/uwx_ttrace.c b/sys/contrib/ia64/libuwx/src/uwx_ttrace.c
new file mode 100644
index 0000000..a506ed0
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_ttrace.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/ttrace.h>
+#include <sys/uc_access.h>
+#include <machine/sys/uregs.h>
+#endif
+
+#include "uwx_env.h"
+#include "uwx_context.h"
+#include "uwx_trace.h"
+#include "uwx_ttrace.h"
+
+struct uwx_ttrace_info {
+ uint64_t bspstore;
+ uint64_t load_map;
+ uint64_t rvec[10];
+ alloc_cb allocate_cb;
+ free_cb free_cb;
+ int have_ucontext;
+ pid_t pid;
+ lwpid_t lwpid;
+ int trace;
+ ucontext_t ucontext;
+};
+
+void *uwx_ttrace_memcpy(void *buffer, uint64_t ptr, size_t bufsiz, int ident)
+{
+ uint64_t *dest;
+ uint64_t val;
+ int status;
+
+ status = ttrace(TT_PROC_RDDATA, (pid_t)ident,
+ 0, ptr, bufsiz, (uint64_t)buffer);
+ if (status != 0)
+ return NULL;
+ return buffer;
+}
+
+struct uwx_ttrace_info *uwx_ttrace_init_info(
+ struct uwx_env *env,
+ pid_t pid,
+ lwpid_t lwpid,
+ uint64_t load_map)
+{
+ struct uwx_ttrace_info *info;
+
+ if (env->allocate_cb == 0)
+ info = (struct uwx_ttrace_info *)
+ malloc(sizeof(struct uwx_ttrace_info));
+ else
+ info = (struct uwx_ttrace_info *)
+ (*env->allocate_cb)(sizeof(struct uwx_ttrace_info));
+ if (info == 0)
+ return 0;
+
+ info->bspstore = 0;
+ info->load_map = load_map;
+ info->allocate_cb = env->allocate_cb;
+ info->free_cb = env->free_cb;
+ info->have_ucontext = 0;
+ info->pid = pid;
+ info->lwpid = lwpid;
+ info->trace = env->trace;
+ return info;
+}
+
+int uwx_ttrace_free_info(struct uwx_ttrace_info *info)
+{
+ if (info->free_cb == 0)
+ free((void *)info);
+ else
+ (*info->free_cb)((void *)info);
+ return UWX_OK;
+}
+
+int uwx_ttrace_init_context(struct uwx_env *env, struct uwx_ttrace_info *info)
+{
+ uint64_t reason;
+ uint64_t ip;
+ uint64_t sp;
+ uint64_t bsp;
+ uint64_t cfm;
+ uint64_t ec;
+ int status;
+
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__reason, (uint64_t)8, (uint64_t)&reason);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__ip, (uint64_t)8, (uint64_t)&ip);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__r12, (uint64_t)8, (uint64_t)&sp);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__ar_bsp, (uint64_t)8, (uint64_t)&bsp);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__ar_bspstore, (uint64_t)8, (uint64_t)&info->bspstore);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__cfm, (uint64_t)8, (uint64_t)&cfm);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+ status = ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ (uint64_t)__ar_ec, (uint64_t)8, (uint64_t)&ec);
+ if (status != 0)
+ return UWX_TT_ERR_TTRACE;
+
+ cfm |= ec << 52;
+
+ if (reason != 0)
+ bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f));
+
+ return uwx_init_context(env, ip, sp, bsp, cfm);
+}
+
+int uwx_ttrace_init_from_sigcontext(
+ struct uwx_env *env,
+ struct uwx_ttrace_info *info,
+ uint64_t ucontext)
+{
+ int status;
+ uint16_t reason;
+ uint64_t ip;
+ uint64_t sp;
+ uint64_t bsp;
+ uint64_t cfm;
+ unsigned int nat;
+ uint64_t ec;
+
+ info->have_ucontext = 1;
+ uwx_ttrace_memcpy(&info->ucontext,
+ ucontext,
+ sizeof(__uc_misc_t),
+ info->pid);
+ uwx_ttrace_memcpy(&info->ucontext.__uc_mcontext,
+ (uint64_t) &((ucontext_t *)ucontext)->__uc_mcontext,
+ sizeof(mcontext_t),
+ info->pid);
+ status = __uc_get_reason(&info->ucontext, &reason);
+ status = __uc_get_ip(&info->ucontext, &ip);
+ status = __uc_get_grs(&info->ucontext, 12, 1, &sp, &nat);
+ status = __uc_get_ar(&info->ucontext, 17, &bsp);
+ status = __uc_get_ar(&info->ucontext, 18, &info->bspstore);
+ status = __uc_get_ar(&info->ucontext, 66, &ec);
+ status = __uc_get_cfm(&info->ucontext, &cfm);
+ cfm |= ec << 52;
+ if (reason != 0)
+ bsp = uwx_add_to_bsp(bsp, -((unsigned int)cfm & 0x7f));
+ uwx_init_context(env, ip, sp, bsp, cfm);
+ return UWX_OK;
+}
+
+int uwx_ttrace_do_context_frame(
+ struct uwx_env *env,
+ struct uwx_ttrace_info *info)
+{
+ int abi_context;
+ int status;
+ uint64_t ucontext;
+
+ abi_context = uwx_get_abi_context_code(env);
+ if (abi_context != 0x0101) /* abi = HP-UX, context = 1 */
+ return UWX_TT_ERR_BADABICONTEXT;
+ status = uwx_get_reg(env, UWX_REG_GR(32), &ucontext);
+ if (status != 0)
+ return status;
+ return uwx_ttrace_init_from_sigcontext(env, info, ucontext);
+}
+
+int uwx_ttrace_copyin(
+ int request,
+ char *loc,
+ uint64_t rem,
+ int len,
+ intptr_t tok)
+{
+ int status;
+ int regid;
+ unsigned int nat;
+ struct uwx_ttrace_info *info = (struct uwx_ttrace_info *) tok;
+ unsigned long *wp;
+ uint64_t *dp;
+ int ttreg;
+
+ dp = (uint64_t *) loc;
+
+ if (request == UWX_COPYIN_UINFO) {
+ if (len == 4) {
+ status = ttrace(TT_PROC_RDTEXT, info->pid,
+ 0, rem, 4, (uint64_t)loc);
+ wp = (unsigned long *) loc;
+ TRACE_SELF_COPYIN4(rem, len, wp)
+ }
+ else if (len == 8) {
+ status = ttrace(TT_PROC_RDTEXT, info->pid,
+ 0, rem, 8, (uint64_t)loc);
+ TRACE_SELF_COPYIN4(rem, len, dp)
+ }
+ else
+ return 0;
+ }
+ else if (request == UWX_COPYIN_MSTACK && len == 8) {
+ status = ttrace(TT_PROC_RDDATA, info->pid, 0, rem, 8, (uint64_t)loc);
+ TRACE_SELF_COPYIN4(rem, len, dp)
+ }
+ else if (request == UWX_COPYIN_RSTACK && len == 8) {
+ if (info->have_ucontext == 0 || rem < info->bspstore) {
+ status = ttrace(TT_PROC_RDDATA, info->pid, 0, rem, 8, (uint64_t)loc);
+ TRACE_SELF_COPYIN4(rem, len, dp)
+ }
+ else {
+ status = __uc_get_rsebs(&info->ucontext, (uint64_t *)rem, 1, dp);
+ if (status != 0)
+ return 0;
+ }
+ }
+ else if (request == UWX_COPYIN_REG && len == 8) {
+ regid = (int)rem;
+ if (info->have_ucontext) {
+ if (regid < UWX_REG_GR(0)) {
+ switch (regid) {
+ case UWX_REG_PFS:
+ status = __uc_get_ar(&info->ucontext, 64, dp);
+ break;
+ case UWX_REG_PREDS:
+ status = __uc_get_prs(&info->ucontext, dp);
+ break;
+ case UWX_REG_RNAT:
+ status = __uc_get_ar(&info->ucontext, 19, dp);
+ break;
+ case UWX_REG_UNAT:
+ status = __uc_get_ar(&info->ucontext, 36, dp);
+ break;
+ case UWX_REG_FPSR:
+ status = __uc_get_ar(&info->ucontext, 40, dp);
+ break;
+ case UWX_REG_LC:
+ status = __uc_get_ar(&info->ucontext, 65, dp);
+ break;
+ default:
+ return 0;
+ }
+ }
+ else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) {
+ status = __uc_get_grs(&info->ucontext,
+ regid - UWX_REG_GR(0), 1, dp, &nat);
+ }
+ else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) {
+ status = __uc_get_brs(&info->ucontext,
+ regid - UWX_REG_BR(0), 1, dp);
+ }
+ }
+ else {
+ if (regid < UWX_REG_GR(0)) {
+ switch (regid) {
+ case UWX_REG_PFS:
+ ttreg = __ar_pfs;
+ break;
+ case UWX_REG_PREDS:
+ ttreg = __pr;
+ break;
+ case UWX_REG_RNAT:
+ ttreg = __ar_rnat;
+ break;
+ case UWX_REG_UNAT:
+ ttreg = __ar_unat;
+ break;
+ case UWX_REG_FPSR:
+ ttreg = __ar_fpsr;
+ break;
+ case UWX_REG_LC:
+ ttreg = __ar_lc;
+ break;
+ default:
+ return 0;
+ }
+ }
+ else if (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) {
+ ttreg = regid - UWX_REG_GR(1) + __r1;
+ }
+ else if (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) {
+ ttreg = regid - UWX_REG_BR(0) + __b0;
+ }
+ else
+ return 0;
+ status == ttrace(TT_LWP_RUREGS, info->pid, info->lwpid,
+ ttreg, 8, (uint64_t)loc);
+ }
+ if (status != 0)
+ return 0;
+ }
+ return len;
+}
+
+
+int uwx_ttrace_lookupip(
+ int request,
+ uint64_t ip,
+ intptr_t tok,
+ uint64_t **resultp)
+{
+ struct uwx_ttrace_info *info = (struct uwx_ttrace_info *) tok;
+ UINT64 handle;
+ struct load_module_desc desc;
+ uint64_t *unwind_base;
+ uint64_t *rvec;
+ int i;
+
+ if (request == UWX_LKUP_LOOKUP) {
+ TRACE_SELF_LOOKUP(ip)
+ handle = dlmodinfo((unsigned long) ip, &desc, sizeof(desc),
+ uwx_ttrace_memcpy, info->pid, info->load_map);
+ if (handle == 0)
+ return UWX_LKUP_ERR;
+ unwind_base = (uint64_t *) desc.unwind_base;
+ TRACE_SELF_LOOKUP_DESC(desc.text_base, unwind_base)
+ i = 0;
+ rvec = info->rvec;
+ rvec[i++] = UWX_KEY_TBASE;
+ rvec[i++] = desc.text_base;
+ rvec[i++] = UWX_KEY_UFLAGS;
+ rvec[i++] = unwind_base[0];
+ rvec[i++] = UWX_KEY_USTART;
+ rvec[i++] = desc.text_base + unwind_base[1];
+ rvec[i++] = UWX_KEY_UEND;
+ rvec[i++] = desc.text_base + unwind_base[2];
+ rvec[i++] = 0;
+ rvec[i++] = 0;
+ *resultp = rvec;
+ return UWX_LKUP_UTABLE;
+ }
+ else if (request == UWX_LKUP_FREE) {
+ return 0;
+ }
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_ttrace.h b/sys/contrib/ia64/libuwx/src/uwx_ttrace.h
new file mode 100644
index 0000000..232afea
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_ttrace.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _KERNEL
+#include <signal.h>
+#endif
+
+struct uwx_ttrace_info;
+
+extern struct uwx_ttrace_info *uwx_ttrace_init_info(
+ struct uwx_env *env,
+ pid_t pid,
+ lwpid_t lwpid,
+ uint64_t load_map);
+
+extern int uwx_ttrace_free_info(struct uwx_ttrace_info *info);
+
+extern int uwx_ttrace_init_context(
+ struct uwx_env *env,
+ struct uwx_ttrace_info *info);
+
+extern int uwx_ttrace_init_from_sigcontext(
+ struct uwx_env *env,
+ struct uwx_ttrace_info *info,
+ uint64_t ucontext);
+
+extern int uwx_ttrace_do_context_frame(
+ struct uwx_env *env,
+ struct uwx_ttrace_info *info);
+
+extern int uwx_ttrace_copyin(
+ int request,
+ char *loc,
+ uint64_t rem,
+ int len,
+ intptr_t tok);
+
+extern int uwx_ttrace_lookupip(
+ int request,
+ uint64_t ip,
+ intptr_t tok,
+ uint64_t **resultp);
+
+#define UWX_TT_ERR_BADABICONTEXT (-101)
+#define UWX_TT_ERR_TTRACE (-102)
diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.c b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c
new file mode 100644
index 0000000..1244026
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.c
@@ -0,0 +1,1103 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_uinfo.h"
+#include "uwx_utable.h"
+#include "uwx_scoreboard.h"
+#include "uwx_bstream.h"
+#include "uwx_trace.h"
+#include "uwx_swap.h"
+
+int uwx_count_ones(unsigned int mask);
+
+/*
+ * uwx_uinfo.c
+ *
+ * This file contains the routines for reading and decoding
+ * the unwind information block.
+ *
+ * The main entry point, uwx_decode_uinfo(), is given a pointer
+ * to an unwind table entry and a pointer (passed by reference)
+ * to be filled in with a pointer to an update vector. It will
+ * read and decode the unwind descriptors contained in the
+ * unwind information block, then build the register state array,
+ * which describes the actions necessary to step from the current
+ * frame to the previous one.
+ */
+
+#define COPYIN_UINFO_4(dest, src) \
+ (env->remote? \
+ (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \
+ WORDSZ, env->cb_token) : \
+ (*(uint32_t *)(dest) = *(uint32_t *)(src), WORDSZ) )
+
+#define COPYIN_UINFO_8(dest, src) \
+ (env->remote? \
+ (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \
+ DWORDSZ, env->cb_token) : \
+ (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) )
+
+
+/* uwx_default_rstate: Returns the default register state for a leaf routine */
+
+int uwx_default_rstate(struct uwx_env *env, uint64_t **rstatep)
+{
+ struct uwx_scoreboard *sb;
+
+ sb = uwx_init_scoreboards(env);
+ *rstatep = sb->rstate;
+ return UWX_OK;
+}
+
+
+/* uwx_decode_uinfo: Decodes unwind info region */
+
+int uwx_decode_uinfo(
+ struct uwx_env *env,
+ struct uwx_utable_entry *uentry,
+ uint64_t **rstatep)
+{
+ uint64_t uinfohdr;
+ unsigned int ulen;
+ int len;
+ struct uwx_bstream bstream;
+ struct uwx_scoreboard *scoreboard;
+ int ip_slot;
+ int cur_slot;
+ int status;
+ struct uwx_rhdr rhdr;
+
+ /* Remember the offset from the start of the function */
+ /* to the current IP. This helps the client find */
+ /* the symbolic information. */
+
+ env->function_offset = env->context.special[UWX_REG_IP] -
+ uentry->code_start;
+
+ /* Read the unwind info header using the copyin callback. */
+ /* (If we're reading a 32-bit unwind table, we need to */
+ /* read the header as two 32-bit pieces to preserve the */
+ /* guarantee that we always call copyin for aligned */
+ /* 4-byte or 8-byte chunks.) */
+ /* Then compute the length of the unwind descriptor */
+ /* region and initialize a byte stream to read it. */
+
+ if (uentry->unwind_flags & UNWIND_TBL_32BIT) {
+ len = COPYIN_UINFO_4((char *)&uinfohdr, uentry->unwind_info);
+ len += COPYIN_UINFO_4((char *)&uinfohdr + WORDSZ,
+ uentry->unwind_info + WORDSZ);
+ }
+ else
+ len = COPYIN_UINFO_8((char *)&uinfohdr, uentry->unwind_info);
+ if (len != DWORDSZ)
+ return UWX_ERR_COPYIN_UINFO;
+ if (env->byte_swap)
+ uwx_swap8(&uinfohdr);
+ if (uentry->unwind_flags & UNWIND_TBL_32BIT)
+ ulen = UNW_LENGTH(uinfohdr) * WORDSZ;
+ else
+ ulen = UNW_LENGTH(uinfohdr) * DWORDSZ;
+ uwx_init_bstream(&bstream, env,
+ uentry->unwind_info + DWORDSZ, ulen, UWX_COPYIN_UINFO);
+
+ TRACE_R_UIB(uentry, ulen)
+
+ /* Create an initial scoreboard for tracking the unwind state. */
+
+ scoreboard = uwx_init_scoreboards(env);
+
+ /* Prepare to read and decode the unwind regions described */
+ /* by the unwind info block. Find the target "ip" slot */
+ /* relative to the beginning of the region. The lower 4 bits */
+ /* of the actual IP encode the slot number within a bundle. */
+
+ cur_slot = 0;
+ ip_slot = (int) ((env->context.special[UWX_REG_IP] & ~0x0fLL)
+ - uentry->code_start)
+ / BUNDLESZ * SLOTSPERBUNDLE
+ + (unsigned int) (env->context.special[UWX_REG_IP] & 0x0f);
+
+ /* Loop over the regions in the unwind info block. */
+
+ for (;;) {
+
+ /* Decode the next region header. */
+ /* We have an error if we reach the end of the info block, */
+ /* since we should have found our target ip slot by then. */
+ /* We also have an error if the next byte isn't a region */
+ /* header record. */
+
+ status = uwx_decode_rhdr(env, &bstream, &rhdr);
+ if (status != UWX_OK)
+ return status;
+
+ /* If a prologue region, get a new scoreboard, pushing */
+ /* the previous one onto the prologue stack. Then read */
+ /* and decode the prologue region records. */
+
+ if (rhdr.is_prologue) {
+ scoreboard = uwx_new_scoreboard(env, scoreboard);
+ if (scoreboard == 0)
+ return UWX_ERR_NOMEM;
+ status = uwx_decode_prologue(env, &bstream,
+ scoreboard, &rhdr, ip_slot);
+ }
+
+ /* If a body region, read and decode the body region */
+ /* records. If the body has an epilogue count, */
+ /* uwx_decode_body will note that in the region header */
+ /* record for use at the bottom of the loop. */
+
+ else {
+ status = uwx_decode_body(env, &bstream, scoreboard, &rhdr, ip_slot);
+ }
+
+ if (status != UWX_OK)
+ return status;
+
+ TRACE_R_DUMP_SB(scoreboard, rhdr, cur_slot, ip_slot)
+
+ /* If the target ip slot is within this region, we're done. */
+ /* Return the scoreboard's register state array. */
+
+ if (ip_slot < rhdr.rlen) {
+ *rstatep = scoreboard->rstate;
+ return UWX_OK;
+ }
+
+ /* Otherwise, update the current ip slot, pop the */
+ /* scoreboard stack based on the epilogue count, */
+ /* and loop back around for the next region. */
+
+ cur_slot += rhdr.rlen;
+ ip_slot -= rhdr.rlen;
+ if (rhdr.ecount > 0) {
+ scoreboard = uwx_pop_scoreboards(env, scoreboard, rhdr.ecount);
+ if (scoreboard == 0)
+ return UWX_ERR_PROLOG_UF;
+ }
+ }
+ /*NOTREACHED*/
+}
+
+
+/* uwx_decode_rhdr: Decodes a region header record */
+
+int uwx_decode_rhdr(
+ struct uwx_env *env,
+ struct uwx_bstream *bstream,
+ struct uwx_rhdr *rhdr)
+{
+ int b0;
+ int b1;
+ uint64_t val;
+ int status;
+
+ /* Get the first byte of the next descriptor record. */
+ b0 = uwx_get_byte(bstream);
+ if (b0 < 0)
+ return UWX_ERR_NOUDESC;
+
+ /* Initialize region header record. */
+
+ rhdr->is_prologue = 0;
+ rhdr->rlen = 0;
+ rhdr->mask = 0;
+ rhdr->grsave = 0;
+ rhdr->ecount = 0;
+
+ /* Format R1 */
+
+ if (b0 < 0x40) {
+ if ((b0 & 0x20) == 0) {
+ TRACE_I_DECODE_RHDR_1("(R1) prologue", b0)
+ rhdr->is_prologue = 1;
+ }
+ else
+ TRACE_I_DECODE_RHDR_1("(R1) body", b0)
+ rhdr->rlen = b0 & 0x1f;
+ }
+
+ /* Format R2 */
+
+ else if (b0 < 0x60) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ status = uwx_get_uleb128(bstream, &val);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_RHDR_2L("(R2) prologue_gr", b0, b1, val)
+ rhdr->is_prologue = 1;
+ rhdr->rlen = (unsigned int) val;
+ rhdr->mask = ((b0 & 0x07) << 1) | (b1 >> 7);
+ rhdr->grsave = b1 & 0x7f;
+ }
+
+ /* Format R3 */
+
+ else if (b0 < 0x80) {
+ status = uwx_get_uleb128(bstream, &val);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ if ((b0 & 0x03) == 0) {
+ TRACE_I_DECODE_RHDR_1L("(R3) prologue", b0, val)
+ rhdr->is_prologue = 1;
+ }
+ else
+ TRACE_I_DECODE_RHDR_1L("(R3) body", b0, val)
+ rhdr->rlen = (unsigned int) val;
+ }
+
+ /* Otherwise, not a region header record. */
+
+ else {
+ TRACE_I_DECODE_RHDR_1("(?)", b0)
+ return UWX_ERR_BADUDESC;
+ }
+
+ return UWX_OK;
+}
+
+
+/* uwx_decode_prologue: Decodes a prologue region */
+
+int uwx_decode_prologue(
+ struct uwx_env *env,
+ struct uwx_bstream *bstream,
+ struct uwx_scoreboard *scoreboard,
+ struct uwx_rhdr *rhdr,
+ int ip_slot)
+{
+ int status;
+ int reg;
+ int mask;
+ int b0;
+ int b1;
+ int b2;
+ int b3;
+ int r;
+ int t;
+ int i;
+ uint64_t parm1;
+ uint64_t parm2;
+ uint64_t newrstate[NSBREG];
+ int tspill[NSBREG];
+ int priunat_mem_rstate;
+ int t_priunat_mem;
+ unsigned int gr_mem_mask;
+ unsigned int br_mem_mask;
+ unsigned int fr_mem_mask;
+ unsigned int gr_gr_mask;
+ unsigned int br_gr_mask;
+ int ngr;
+ int nbr;
+ int nfr;
+ unsigned int spill_base;
+ unsigned int gr_base;
+ unsigned int br_base;
+ unsigned int fr_base;
+
+ /* Initialize an array of register states from the current */
+ /* scoreboard, along with a parallel array of spill times. */
+ /* We use this as a temporary scoreboard, then update the */
+ /* real scoreboard at the end of the procedure. */
+ /* We initialize the spill time to (rhdr.rlen - 1) so that */
+ /* spills without a "when" descriptor will take effect */
+ /* at the end of the prologue region. */
+ /* (Boundary condition: all actions in a zero-length prologue */
+ /* will appear to have happened in the instruction slot */
+ /* immediately preceding the prologue.) */
+
+ for (i = 0; i < env->nsbreg; i++) {
+ newrstate[i] = scoreboard->rstate[i];
+ tspill[i] = rhdr->rlen - 1;
+ }
+ priunat_mem_rstate = UWX_DISP_NONE;
+ t_priunat_mem = rhdr->rlen - 1;
+
+ fr_mem_mask = 0;
+ gr_mem_mask = 0;
+ br_mem_mask = 0;
+ gr_gr_mask = 0;
+ br_gr_mask = 0;
+ nfr = 0;
+ ngr = 0;
+ nbr = 0;
+ spill_base = 0;
+
+ /* If prologue_gr header record supplied mask and grsave, */
+ /* record these in the scoreboard. */
+
+ reg = rhdr->grsave;
+ mask = rhdr->mask;
+ if (mask & 0x8) {
+ newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
+ reg++;
+ }
+ if (mask & 0x4) {
+ newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
+ reg++;
+ }
+ if (mask & 0x2) {
+ newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
+ reg++;
+ }
+ if (mask & 0x1) {
+ newrstate[SBREG_PREDS] = UWX_DISP_REG(UWX_REG_GR(reg));
+ reg++;
+ }
+
+ /* Read prologue descriptor records until */
+ /* we hit another region header. */
+
+ for (;;) {
+
+ b0 = uwx_get_byte(bstream);
+
+ if (b0 < 0x80) {
+ /* Return the last byte read to the byte stream, since it's */
+ /* really the first byte of the next region header record. */
+ if (b0 >= 0)
+ (void) uwx_unget_byte(bstream, b0);
+ break;
+ }
+
+ switch ((b0 & 0x70) >> 4) {
+
+ case 0: /* 1000 xxxx */
+ case 1: /* 1001 xxxx */
+ /* Format P1 (br_mem) */
+ TRACE_I_DECODE_PROLOGUE_1("(P1) br_mem", b0)
+ br_mem_mask = b0 & 0x1f;
+ break;
+
+ case 2: /* 1010 xxxx */
+ /* Format P2 (br_gr) */
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_PROLOGUE_2("(P2) br_gr", b0, b1)
+ mask = ((b0 & 0x0f) << 1) | (b1 >> 7);
+ reg = b1 & 0x7f;
+ br_gr_mask = mask;
+ for (i = 0; i < NSB_BR && mask != 0; i++) {
+ if (mask & 0x01) {
+ newrstate[SBREG_BR + i] = UWX_DISP_REG(UWX_REG_GR(reg));
+ reg++;
+ }
+ mask = mask >> 1;
+ }
+ break;
+
+ case 3: /* 1011 xxxx */
+ /* Format P3 */
+ if (b0 < 0xb8) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ r = ((b0 & 0x3) << 1) | (b1 >> 7);
+ reg = b1 & 0x7f;
+ switch (r) {
+ case 0: /* psp_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) psp_gr", b0, b1)
+ newrstate[SBREG_PSP] = UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 1: /* rp_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) rp_gr", b0, b1)
+ newrstate[SBREG_RP] = UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 2: /* pfs_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) pfs_gr", b0, b1)
+ newrstate[SBREG_PFS] = UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 3: /* preds_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) preds_gr", b0, b1)
+ newrstate[SBREG_PREDS] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 4: /* unat_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) unat_gr", b0, b1)
+ newrstate[SBREG_UNAT] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 5: /* lc_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) lc_gr", b0, b1)
+ newrstate[SBREG_LC] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 6: /* rp_br */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) rp_br", b0, b1)
+ scoreboard->rstate[SBREG_RP] =
+ UWX_DISP_REG(UWX_REG_BR(reg));
+ break;
+ case 7: /* rnat_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) rnat_gr", b0, b1)
+ newrstate[SBREG_RNAT] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 8: /* bsp_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) bsp_gr", b0, b1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 9: /* bspstore_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) bspstore_gr", b0, b1)
+ /* Don't track BSPSTORE yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 10: /* fpsr_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) fpsr_gr", b0, b1)
+ newrstate[SBREG_FPSR] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ case 11: /* priunat_gr */
+ TRACE_I_DECODE_PROLOGUE_2("(P3) priunat_gr", b0, b1)
+ newrstate[SBREG_PRIUNAT] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ break;
+ default:
+ TRACE_I_DECODE_PROLOGUE_2("(P3) ??", b0, b1)
+ return UWX_ERR_BADUDESC;
+ }
+ }
+
+ /* Format P4 (spill_mask) */
+ else if (b0 == 0xb8) {
+ TRACE_I_DECODE_PROLOGUE_1("(P4) spill_mask", b0)
+ /* The spill_mask descriptor is followed by */
+ /* an imask field whose length is determined */
+ /* by the region length: there are two mask */
+ /* bits per instruction slot in the region. */
+ /* We decode these bits two at a time, counting */
+ /* the number of FRs, GRs, and BRs that are */
+ /* saved up to the slot of interest. Other */
+ /* descriptors describe which sets of these */
+ /* registers are spilled, and we put those */
+ /* two pieces of information together at the */
+ /* end of the main loop. */
+ t = 0;
+ while (t < rhdr->rlen) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ for (i = 0; i < 4 && (t + i) < ip_slot; i++) {
+ switch (b1 & 0xc0) {
+ case 0x00: break;
+ case 0x40: nfr++; break;
+ case 0x80: ngr++; break;
+ case 0xc0: nbr++; break;
+ }
+ b1 = b1 << 2;
+ }
+ t += 4;
+ }
+ }
+
+ /* Format P5 (frgr_mem) */
+ else if (b0 == 0xb9) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ b3 = uwx_get_byte(bstream);
+ if (b3 < 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_PROLOGUE_4("(P5) frgr_mem", b0, b1, b2, b3)
+ gr_mem_mask = b1 >> 4;
+ fr_mem_mask = ((b1 & 0x0f) << 16) | (b2 << 8) | b3;
+ }
+
+ /* Invalid descriptor record */
+ else {
+ TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
+ return UWX_ERR_BADUDESC;
+ }
+
+ break;
+
+ case 4: /* 1100 xxxx */
+ /* Format P6 (fr_mem) */
+ TRACE_I_DECODE_PROLOGUE_1("(P6) fr_mem", b0)
+ fr_mem_mask = b0 & 0x0f;
+ break;
+
+ case 5: /* 1101 xxxx */
+ /* Format P6 (gr_mem) */
+ TRACE_I_DECODE_PROLOGUE_1("(P6) gr_mem", b0)
+ gr_mem_mask = b0 & 0x0f;
+ break;
+
+ case 6: /* 1110 xxxx */
+ /* Format P7 */
+ r = b0 & 0xf;
+ status = uwx_get_uleb128(bstream, &parm1);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ switch (r) {
+ case 0: /* mem_stack_f */
+ status = uwx_get_uleb128(bstream, &parm2);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_PROLOGUE_1LL("(P7) mem_stack_f", b0, parm1, parm2)
+ newrstate[SBREG_PSP] = UWX_DISP_SPPLUS(parm2 * 16);
+ tspill[SBREG_PSP] = (int) parm1;
+ break;
+ case 1: /* mem_stack_v */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) mem_stack_v", b0, parm1)
+ tspill[SBREG_PSP] = (int) parm1;
+ break;
+ case 2: /* spill_base */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) spill_base", b0, parm1)
+ spill_base = 4 * (unsigned int) parm1;
+ break;
+ case 3: /* psp_sprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) psp_sprel", b0, parm1)
+ newrstate[SBREG_PSP] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 4: /* rp_when */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_when", b0, parm1)
+ tspill[SBREG_RP] = (int) parm1;
+ break;
+ case 5: /* rp_psprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) rp_psprel", b0, parm1)
+ newrstate[SBREG_RP] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 6: /* pfs_when */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_when", b0, parm1)
+ tspill[SBREG_PFS] = (int) parm1;
+ break;
+ case 7: /* pfs_psprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) pfs_psprel", b0, parm1)
+ newrstate[SBREG_PFS] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 8: /* preds_when */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_when", b0, parm1)
+ tspill[SBREG_PREDS] = (int) parm1;
+ break;
+ case 9: /* preds_psprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) preds_psprel", b0, parm1)
+ newrstate[SBREG_PREDS] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 10: /* lc_when */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_when", b0, parm1)
+ tspill[SBREG_LC] = (int) parm1;
+ break;
+ case 11: /* lc_psprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) lc_psprel", b0, parm1)
+ newrstate[SBREG_LC] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 12: /* unat_when */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_when", b0, parm1)
+ tspill[SBREG_UNAT] = (int) parm1;
+ break;
+ case 13: /* unat_psprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) unat_psprel", b0, parm1)
+ newrstate[SBREG_UNAT] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 14: /* fpsr_when */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_when", b0, parm1)
+ tspill[SBREG_FPSR] = (int) parm1;
+ break;
+ case 15: /* fpsr_psprel */
+ TRACE_I_DECODE_PROLOGUE_1L("(P7) fpsr_psprel", b0, parm1)
+ newrstate[SBREG_FPSR] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ }
+ break;
+
+ case 7: /* 1111 xxxx */
+ /* Format P8 */
+ if (b0 == 0xf0) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ status = uwx_get_uleb128(bstream, &parm1);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ switch (b1) {
+ case 1: /* rp_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) rp_sprel", b0, b1, parm1)
+ newrstate[SBREG_RP] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 2: /* pfs_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) pfs_sprel", b0, b1, parm1)
+ newrstate[SBREG_PFS] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 3: /* preds_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) preds_sprel", b0, b1, parm1)
+ newrstate[SBREG_PREDS] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 4: /* lc_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) lc_sprel", b0, b1, parm1)
+ newrstate[SBREG_LC] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 5: /* unat_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) unat_sprel", b0, b1, parm1)
+ newrstate[SBREG_UNAT] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 6: /* fpsr_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) fpsr_sprel", b0, b1, parm1)
+ newrstate[SBREG_FPSR] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 7: /* bsp_when */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_when", b0, b1, parm1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 8: /* bsp_psprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_psprel", b0, b1, parm1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 9: /* bsp_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) bsp_sprel", b0, b1, parm1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 10: /* bspstore_when */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_when", b0, b1, parm1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 11: /* bspstore_psprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_psprel", b0, b1, parm1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 12: /* bspstore_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) bspstore_sprel", b0, b1, parm1)
+ /* Don't track BSP yet */
+ return UWX_ERR_CANTUNWIND;
+ break;
+ case 13: /* rnat_when */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_when", b0, b1, parm1)
+ tspill[SBREG_RNAT] = (int) parm1;
+ break;
+ case 14: /* rnat_psprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_psprel", b0, b1, parm1)
+ newrstate[SBREG_RNAT] = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 15: /* rnat_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) rnat_sprel", b0, b1, parm1)
+ newrstate[SBREG_RNAT] = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 16: /* priunat_when_gr */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_gr", b0, b1, parm1)
+ tspill[SBREG_PRIUNAT] = (int) parm1;
+ break;
+ case 17: /* priunat_psprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_psprel", b0, b1, parm1)
+ priunat_mem_rstate = UWX_DISP_PSPREL(parm1 * 4);
+ break;
+ case 18: /* priunat_sprel */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_sprel", b0, b1, parm1)
+ priunat_mem_rstate = UWX_DISP_SPREL(parm1 * 4);
+ break;
+ case 19: /* priunat_when_mem */
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) priunat_when_mem", b0, b1, parm1)
+ t_priunat_mem = (int) parm1;
+ break;
+ default:
+ TRACE_I_DECODE_PROLOGUE_2L("(P8) ??", b0, b1, parm1)
+ return UWX_ERR_BADUDESC;
+ }
+ }
+
+ /* Format P9 (gr_gr) */
+ else if (b0 == 0xf1) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_PROLOGUE_3("(P9) gr_gr", b0, b1, b2)
+ mask = b1 & 0x0f;
+ reg = b2 & 0x7f;
+ gr_gr_mask = mask;
+ for (i = 0; i < NSB_GR && mask != 0; i++) {
+ if (mask & 0x01) {
+ newrstate[SBREG_GR + i] =
+ UWX_DISP_REG(UWX_REG_GR(reg));
+ reg++;
+ }
+ mask = mask >> 1;
+ }
+ }
+
+ /* Format X1 */
+ else if (b0 == 0xf9) {
+ TRACE_I_DECODE_PROLOGUE_1("(X1)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format X2 */
+ else if (b0 == 0xfa) {
+ TRACE_I_DECODE_PROLOGUE_1("(X2)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format X3 */
+ else if (b0 == 0xfb) {
+ TRACE_I_DECODE_PROLOGUE_1("(X3)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format X4 */
+ else if (b0 == 0xfc) {
+ TRACE_I_DECODE_PROLOGUE_1("(X4)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ b3 = uwx_get_byte(bstream);
+ if (b3 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format P10 */
+ else if (b0 == 0xff) {
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_PROLOGUE_3("(P10) abi", b0, b1, b2)
+ env->abi_context = (b1 << 8) | b2;
+ return UWX_ABI_FRAME;
+ }
+
+ /* Invalid descriptor record */
+ else {
+ TRACE_I_DECODE_PROLOGUE_1("(?)", b0)
+ return UWX_ERR_BADUDESC;
+ }
+ break;
+ }
+ }
+
+ /* Process the masks of spilled GRs, FRs, and BRs to */
+ /* determine when and where each register was saved. */
+
+ fr_base = spill_base + 16 * uwx_count_ones(fr_mem_mask);
+ br_base = fr_base + 8 * uwx_count_ones(br_mem_mask);
+ gr_base = br_base + 8 * uwx_count_ones(gr_mem_mask);
+ TRACE_I_DECODE_PROLOGUE_SPILL_BASE(spill_base)
+ TRACE_I_DECODE_PROLOGUE_MASKS(gr_mem_mask, gr_gr_mask)
+ TRACE_I_DECODE_PROLOGUE_NSPILL(ngr)
+ for (i = 0; ngr > 0 && i <= NSB_GR; i++) {
+ if (gr_mem_mask & 1) {
+ newrstate[SBREG_GR + i] = UWX_DISP_PSPREL(gr_base);
+ tspill[SBREG_GR + i] = 0;
+ gr_base -= 8;
+ ngr--;
+ }
+ else if (gr_gr_mask & 1) {
+ tspill[SBREG_GR + i] = 0;
+ ngr--;
+ }
+ gr_gr_mask = gr_gr_mask >> 1;
+ gr_mem_mask = gr_mem_mask >> 1;
+ }
+ for (i = 0; nbr > 0 && i <= NSB_BR; i++) {
+ if (br_mem_mask & 1) {
+ newrstate[SBREG_BR + i] = UWX_DISP_PSPREL(br_base);
+ tspill[SBREG_BR + i] = 0;
+ br_base -= 8;
+ nbr--;
+ }
+ else if (br_gr_mask & 1) {
+ tspill[SBREG_BR + i] = 0;
+ nbr--;
+ }
+ br_gr_mask = br_gr_mask >> 1;
+ br_mem_mask = br_mem_mask >> 1;
+ }
+ for (i = 0; nfr > 0 && i <= NSB_FR; i++) {
+ if (fr_mem_mask & 1) {
+ newrstate[SBREG_FR + i] = UWX_DISP_PSPREL(fr_base);
+ tspill[SBREG_FR + i] = 0;
+ fr_base -= 8;
+ nfr--;
+ }
+ fr_mem_mask = fr_mem_mask >> 1;
+ }
+
+ /* Update the scoreboard. */
+
+ for (i = 0; i < env->nsbreg; i++) {
+ if (ip_slot > tspill[i])
+ scoreboard->rstate[i] = newrstate[i];
+ }
+ if (priunat_mem_rstate != UWX_DISP_NONE && ip_slot > t_priunat_mem)
+ scoreboard->rstate[SBREG_PRIUNAT] = priunat_mem_rstate;
+
+ return UWX_OK;
+}
+
+int uwx_count_ones(unsigned int mask)
+{
+ mask = (mask & 0x55555555) + ((mask & 0xaaaaaaaa) >> 1);
+ mask = (mask & 0x33333333) + ((mask & 0xcccccccc) >> 2);
+ mask = (mask & 0x0f0f0f0f) + ((mask & 0xf0f0f0f0) >> 4);
+ mask = (mask & 0x00ff00ff) + ((mask & 0xff00ff00) >> 8);
+ return (mask & 0x0000ffff) + ((mask & 0xffff0000) >> 16);
+}
+
+/* uwx_decode_body: Decodes a body region */
+
+int uwx_decode_body(
+ struct uwx_env *env,
+ struct uwx_bstream *bstream,
+ struct uwx_scoreboard *scoreboard,
+ struct uwx_rhdr *rhdr,
+ int ip_slot)
+{
+ int status;
+ int b0;
+ int b1;
+ int b2;
+ int b3;
+ int label;
+ int ecount;
+ int i;
+ uint64_t parm1;
+ uint64_t parm2;
+ uint64_t newrstate[NSBREG];
+ int tspill[NSBREG];
+ int t_sp_restore;
+
+ /* Initialize an array of register states from the current */
+ /* scoreboard, along with a parallel array of spill times. */
+ /* We use this as a temporary scoreboard, then update the */
+ /* real scoreboard at the end of the procedure. */
+ /* We initialize the spill time to (rhdr.rlen - 1) so that */
+ /* spills without a "when" descriptor will take effect */
+ /* at the end of the prologue region. */
+ /* (Boundary condition: all actions in a zero-length prologue */
+ /* will appear to have happened in the instruction slot */
+ /* immediately preceding the prologue.) */
+
+ for (i = 0; i < env->nsbreg; i++) {
+ newrstate[i] = scoreboard->rstate[i];
+ tspill[i] = rhdr->rlen - 1;
+ }
+ t_sp_restore = rhdr->rlen - 1;
+
+ /* Read body descriptor records until */
+ /* we hit another region header. */
+
+ for (;;) {
+
+ b0 = uwx_get_byte(bstream);
+
+ if (b0 < 0x80) {
+ /* Return the last byte read to the byte stream, since it's */
+ /* really the first byte of the next region header record. */
+ if (b0 >= 0)
+ (void) uwx_unget_byte(bstream, b0);
+ break;
+ }
+
+ /* Format B1 (label_state) */
+ if (b0 < 0xa0) {
+ TRACE_I_DECODE_BODY_1("(B1) label_state", b0)
+ label = b0 & 0x1f;
+ status = uwx_label_scoreboard(env, scoreboard, label);
+ if (status != UWX_OK)
+ return (status);
+ }
+
+ /* Format B1 (copy_state) */
+ else if (b0 < 0xc0) {
+ TRACE_I_DECODE_BODY_1("(B1) copy_state", b0)
+ label = b0 & 0x1f;
+ status = uwx_copy_scoreboard(env, scoreboard, label);
+ if (status != UWX_OK)
+ return (status);
+ for (i = 0; i < env->nsbreg; i++) {
+ newrstate[i] = scoreboard->rstate[i];
+ tspill[i] = rhdr->rlen;
+ }
+ }
+
+ /* Format B2 (epilogue) */
+ else if (b0 < 0xe0) {
+ ecount = b0 & 0x1f;
+ status = uwx_get_uleb128(bstream, &parm1);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_BODY_1L("(B2) epilogue", b0, parm1)
+ rhdr->ecount = ecount + 1;
+ t_sp_restore = rhdr->rlen - (unsigned int) parm1;
+ }
+
+ /* Format B3 (epilogue) */
+ else if (b0 == 0xe0) {
+ status = uwx_get_uleb128(bstream, &parm1);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ status = uwx_get_uleb128(bstream, &parm2);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_BODY_1LL("(B3) epilogue", b0, parm1, parm2)
+ t_sp_restore = rhdr->rlen - (unsigned int) parm1;
+ rhdr->ecount = (unsigned int) parm2 + 1;
+ }
+
+ /* Format B4 (label_state) */
+ else if (b0 == 0xf0) {
+ status = uwx_get_uleb128(bstream, &parm1);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_BODY_1L("(B4) label_state", b0, parm1)
+ label = (int) parm1;
+ status = uwx_label_scoreboard(env, scoreboard, label);
+ if (status != UWX_OK)
+ return (status);
+ }
+
+ /* Format B4 (copy_state) */
+ else if (b0 == 0xf8) {
+ status = uwx_get_uleb128(bstream, &parm1);
+ if (status != 0)
+ return UWX_ERR_BADUDESC;
+ TRACE_I_DECODE_BODY_1L("(B4) copy_state", b0, parm1)
+ label = (int) parm1;
+ status = uwx_copy_scoreboard(env, scoreboard, label);
+ if (status != UWX_OK)
+ return (status);
+ for (i = 0; i < env->nsbreg; i++) {
+ newrstate[i] = scoreboard->rstate[i];
+ tspill[i] = rhdr->rlen;
+ }
+ }
+
+ /* Format X1 */
+ else if (b0 == 0xf9) {
+ TRACE_I_DECODE_BODY_1("(X1)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format X2 */
+ else if (b0 == 0xfa) {
+ TRACE_I_DECODE_BODY_1("(X2)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format X3 */
+ else if (b0 == 0xfb) {
+ TRACE_I_DECODE_BODY_1("(X3)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Format X4 */
+ else if (b0 == 0xfc) {
+ TRACE_I_DECODE_BODY_1("(X4)", b0)
+ b1 = uwx_get_byte(bstream);
+ if (b1 < 0)
+ return UWX_ERR_BADUDESC;
+ b2 = uwx_get_byte(bstream);
+ if (b2 < 0)
+ return UWX_ERR_BADUDESC;
+ b3 = uwx_get_byte(bstream);
+ if (b3 < 0)
+ return UWX_ERR_BADUDESC;
+ /* Don't support X-format descriptors yet */
+ return UWX_ERR_CANTUNWIND;
+ }
+
+ /* Invalid descriptor record */
+ else {
+ TRACE_I_DECODE_BODY_1("(?)", b0)
+ return UWX_ERR_BADUDESC;
+ }
+ }
+
+ /* Update the scoreboard. */
+
+ for (i = 0; i < env->nsbreg; i++) {
+ if (ip_slot > tspill[i])
+ scoreboard->rstate[i] = newrstate[i];
+ }
+
+ /* If we've passed the point in the epilogue where sp */
+ /* is restored, update the scoreboard entry for PSP */
+ /* and reset any entries for registers saved in memory. */
+
+ if (ip_slot > t_sp_restore) {
+ scoreboard->rstate[SBREG_PSP] = UWX_DISP_SPPLUS(0);
+ for (i = 0; i < env->nsbreg; i++) {
+ if (UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_SPREL(0) ||
+ UWX_GET_DISP_CODE(scoreboard->rstate[i]) == UWX_DISP_PSPREL(0))
+ scoreboard->rstate[i] = UWX_DISP_NONE;
+ }
+ }
+
+ return UWX_OK;
+}
+
diff --git a/sys/contrib/ia64/libuwx/src/uwx_uinfo.h b/sys/contrib/ia64/libuwx/src/uwx_uinfo.h
new file mode 100644
index 0000000..b1fbdd9
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_uinfo.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+struct uwx_utable_entry;
+
+extern int uwx_decode_uinfo(
+ struct uwx_env *env,
+ struct uwx_utable_entry *uentry,
+ uint64_t **rstatep);
+
+extern int uwx_default_rstate(
+ struct uwx_env *env,
+ uint64_t **rstatep);
+
+/* Region header record */
+
+struct uwx_rhdr {
+ int is_prologue; /* true if prologue region */
+ unsigned int rlen; /* length of region (# instruction slots) */
+ int mask; /* register save mask */
+ int grsave; /* first gr used for saving */
+ unsigned int ecount; /* epilogue count (0 = no epilogue) */
+ unsigned int epilogue_t; /* epilogue "t" value */
+};
+
+struct uwx_bstream;
+
+extern int uwx_decode_rhdr(
+ struct uwx_env *env,
+ struct uwx_bstream *bstream,
+ struct uwx_rhdr *rhdr);
+
+extern int uwx_decode_prologue(
+ struct uwx_env *env,
+ struct uwx_bstream *bstream,
+ struct uwx_scoreboard *scoreboard,
+ struct uwx_rhdr *rhdr,
+ int ip_slot);
+
+extern int uwx_decode_body(
+ struct uwx_env *env,
+ struct uwx_bstream *bstream,
+ struct uwx_scoreboard *scoreboard,
+ struct uwx_rhdr *rhdr,
+ int ip_slot);
diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.c b/sys/contrib/ia64/libuwx/src/uwx_utable.c
new file mode 100644
index 0000000..517f4dd
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_utable.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_utable.h"
+#include "uwx_swap.h"
+#include "uwx_trace.h"
+
+/*
+ * uwx_utable.c
+ *
+ * This file contains the routines for searching an unwind table.
+ * The main entry point, uwx_search_utable(), gets the
+ * necessary information from the lookup ip callback's result
+ * vector, determines whether the table is 32-bit or 64-bit,
+ * then invokes the binary search routine for that format.
+ */
+
+
+/* Forward declarations */
+
+int uwx_search_utable32(
+ struct uwx_env *env,
+ uint32_t text_base,
+ uint32_t unwind_start,
+ uint32_t unwind_end,
+ struct uwx_utable_entry *uentry);
+
+int uwx_search_utable64(
+ struct uwx_env *env,
+ uint64_t text_base,
+ uint64_t unwind_start,
+ uint64_t unwind_end,
+ struct uwx_utable_entry *uentry);
+
+
+/* uwx_search_utable: Searches an unwind table for IP in current context */
+
+int uwx_search_utable(
+ struct uwx_env *env,
+ uint64_t *uvec,
+ struct uwx_utable_entry *uentry)
+{
+ uint64_t text_base = 0;
+ uint64_t unwind_flags;
+ uint64_t unwind_start = 0;
+ uint64_t unwind_end = 0;
+ int keys;
+ int status;
+
+ /* Get unwind table information from the result vector. */
+ /* Make sure all three required values are given. */
+
+ keys = 0;
+ unwind_flags = 0;
+ while (*uvec != 0) {
+ switch ((int)*uvec++) {
+ case UWX_KEY_TBASE:
+ keys |= 1;
+ text_base = *uvec++;
+ break;
+ case UWX_KEY_UFLAGS:
+ unwind_flags = *uvec++;
+ break;
+ case UWX_KEY_USTART:
+ keys |= 2;
+ unwind_start = *uvec++;
+ break;
+ case UWX_KEY_UEND:
+ keys |= 4;
+ unwind_end = *uvec++;
+ break;
+ default:
+ return UWX_ERR_BADKEY;
+ }
+ }
+ if (keys != 7)
+ return UWX_ERR_BADKEY;
+
+ /* Copy the unwind flags into the unwind entry. */
+ /* (uwx_decode_uinfo needs to know whether it's 32-bit or 64-bit.) */
+
+ uentry->unwind_flags = unwind_flags;
+
+ /* Call the appropriate binary search routine. */
+
+ if (unwind_flags & UNWIND_TBL_32BIT)
+ status = uwx_search_utable32(env,
+ (uint32_t) text_base,
+ (uint32_t) unwind_start,
+ (uint32_t) unwind_end,
+ uentry);
+ else
+ status = uwx_search_utable64(env,
+ text_base, unwind_start, unwind_end, uentry);
+
+ return status;
+}
+
+
+/* uwx_search_utable32: Binary search of 32-bit unwind table */
+
+#define COPYIN_UINFO_4(dest, src) \
+ (env->remote? \
+ (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \
+ WORDSZ, env->cb_token) : \
+ (*(uint32_t *)(dest) = *(uint32_t *)(src), WORDSZ) )
+
+int uwx_search_utable32(
+ struct uwx_env *env,
+ uint32_t text_base,
+ uint32_t unwind_start,
+ uint32_t unwind_end,
+ struct uwx_utable_entry *uentry)
+{
+ int lb;
+ int ub;
+ int mid = 0;
+ int len;
+ uint32_t ip;
+ uint32_t code_start;
+ uint32_t code_end;
+ uint32_t unwind_info;
+
+ /* Since the unwind table uses segment-relative offsets, convert */
+ /* the IP in the current context to a segment-relative offset. */
+
+ ip = env->context.special[UWX_REG_IP] - text_base;
+
+ TRACE_T_SEARCH32(ip)
+
+ /* Standard binary search. */
+ /* Might modify this to do interpolation in the future. */
+
+ lb = 0;
+ ub = (unwind_end - unwind_start) / (3 * WORDSZ);
+ while (ub > lb) {
+ mid = (lb + ub) / 2;
+ len = COPYIN_UINFO_4((char *)&code_start,
+ (intptr_t)(unwind_start+mid*3*WORDSZ));
+ len += COPYIN_UINFO_4((char *)&code_end,
+ (intptr_t)(unwind_start+mid*3*WORDSZ+WORDSZ));
+ if (len != 2 * WORDSZ)
+ return UWX_ERR_COPYIN_UTBL;
+ if (env->byte_swap) {
+ uwx_swap4(&code_start);
+ uwx_swap4(&code_end);
+ }
+ TRACE_T_BINSEARCH32(lb, ub, mid, code_start, code_end)
+ if (ip >= code_end)
+ lb = mid + 1;
+ else if (ip < code_start)
+ ub = mid;
+ else
+ break;
+ }
+ if (ub <= lb)
+ return UWX_ERR_NOUENTRY;
+ len = COPYIN_UINFO_4((char *)&unwind_info,
+ (intptr_t)(unwind_start+mid*3*WORDSZ+2*WORDSZ));
+ if (len != WORDSZ)
+ return UWX_ERR_COPYIN_UTBL;
+ if (env->byte_swap)
+ uwx_swap4(&unwind_info);
+ uentry->code_start = text_base + code_start;
+ uentry->code_end = text_base + code_end;
+ uentry->unwind_info = text_base + unwind_info;
+ return UWX_OK;
+}
+
+
+/* uwx_search_utable64: Binary search of 64-bit unwind table */
+
+#define COPYIN_UINFO_8(dest, src) \
+ (env->remote? \
+ (*env->copyin)(UWX_COPYIN_UINFO, (dest), (src), \
+ DWORDSZ, env->cb_token) : \
+ (*(uint64_t *)(dest) = *(uint64_t *)(src), DWORDSZ) )
+
+int uwx_search_utable64(
+ struct uwx_env *env,
+ uint64_t text_base,
+ uint64_t unwind_start,
+ uint64_t unwind_end,
+ struct uwx_utable_entry *uentry)
+{
+ int lb;
+ int ub;
+ int mid = 0;
+ int len;
+ uint64_t ip;
+ uint64_t code_start;
+ uint64_t code_end;
+ uint64_t unwind_info;
+
+ /* Since the unwind table uses segment-relative offsets, convert */
+ /* the IP in the current context to a segment-relative offset. */
+
+ ip = env->context.special[UWX_REG_IP] - text_base;
+
+ /* Standard binary search. */
+ /* Might modify this to do interpolation in the future. */
+
+ lb = 0;
+ ub = (unwind_end - unwind_start) / (3 * DWORDSZ);
+ while (ub > lb) {
+ mid = (lb + ub) / 2;
+ len = COPYIN_UINFO_8((char *)&code_start, unwind_start+mid*3*DWORDSZ);
+ len += COPYIN_UINFO_8((char *)&code_end,
+ unwind_start+mid*3*DWORDSZ+DWORDSZ);
+ if (len != 2 * DWORDSZ)
+ return UWX_ERR_COPYIN_UTBL;
+ if (env->byte_swap) {
+ uwx_swap8(&code_start);
+ uwx_swap8(&code_end);
+ }
+ if (ip >= code_end)
+ lb = mid + 1;
+ else if (ip < code_start)
+ ub = mid;
+ else
+ break;
+ }
+ if (ub <= lb)
+ return UWX_ERR_NOUENTRY;
+ len = COPYIN_UINFO_8((char *)&unwind_info,
+ unwind_start+mid*3*DWORDSZ+2*DWORDSZ);
+ if (len != DWORDSZ)
+ return UWX_ERR_COPYIN_UTBL;
+ if (env->byte_swap)
+ uwx_swap8(&unwind_info);
+ uentry->code_start = text_base + code_start;
+ uentry->code_end = text_base + code_end;
+ uentry->unwind_info = text_base + unwind_info;
+ return UWX_OK;
+}
diff --git a/sys/contrib/ia64/libuwx/src/uwx_utable.h b/sys/contrib/ia64/libuwx/src/uwx_utable.h
new file mode 100644
index 0000000..a6b09a3
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_utable.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+struct uwx_utable_entry {
+ uint64_t code_start;
+ uint64_t code_end;
+ uint64_t unwind_info;
+ uint64_t unwind_flags;
+};
+
+extern int uwx_search_utable(
+ struct uwx_env *env,
+ uint64_t *uvec,
+ struct uwx_utable_entry *uentry);
diff --git a/sys/contrib/ia64/libuwx/test/Makefile b/sys/contrib/ia64/libuwx/test/Makefile
new file mode 100644
index 0000000..040d17b
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/test/Makefile
@@ -0,0 +1,13 @@
+UWXINCDIR = ../include
+UWXLIBDIR = ../lib/ipf32
+
+CFLAGS = -O -I $(UWXINCDIR)
+LDFLAGS = -L $(UWXLIBDIR)
+
+dumpmyself: dumpmyself.o dump_context.o
+ $(CC) -o dumpmyself $(LDFLAGS) dumpmyself.o dump_context.o -luwx
+
+
+dumpmyself.o: $(UWXINCDIR)/uwx.h $(UWXINCDIR)/uwx_self.h
+
+dump_context.o:
diff --git a/sys/contrib/ia64/libuwx/test/dump_context.c b/sys/contrib/ia64/libuwx/test/dump_context.c
new file mode 100644
index 0000000..4084c26
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/test/dump_context.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <inttypes.h>
+
+void dump_context(uint64_t *context)
+{
+ int i, j;
+ uint64_t val;
+ static char *names[] = {
+ "ip", "sp", "bsp", "cfm",
+ "rp", "psp", "pfs", "preds",
+ "priunat", "bspstore", "rnat", "unat",
+ "fpsr", "lc",
+ "gr4", "gr5", "gr6", "gr7",
+ "br1", "br2", "br3", "br4", "br5"
+ };
+ static int order[] = {
+ 0, 14,
+ 1, 15,
+ 2, 16,
+ 3, 17,
+ 7, 18,
+ 8, 19,
+ 10, 20,
+ 11, 21,
+ 12, 22,
+ 13, -1
+ };
+
+ for (i = 0; i < 20; i += 2) {
+ j = order[i];
+ if (j >= 0) {
+ val = context[j+1];
+ printf(" %-8s %08x %08x", names[j],
+ (unsigned int)(val >> 32),
+ (unsigned int)val);
+ }
+ else
+ printf(" ");
+ j = order[i+1];
+ if (j >= 0) {
+ val = context[j+1];
+ printf(" %-8s %08x %08x", names[j],
+ (unsigned int)(val >> 32),
+ (unsigned int)val);
+ }
+ putchar('\n');
+ }
+}
diff --git a/sys/contrib/ia64/libuwx/test/dumpmyself.c b/sys/contrib/ia64/libuwx/test/dumpmyself.c
new file mode 100644
index 0000000..696798a
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/test/dumpmyself.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx.h"
+#include "uwx_self.h"
+
+struct uwx_env *uenv;
+struct uwx_self_info *cbinfo;
+
+extern int uwx_get_frame_info(struct uwx_env *uenv);
+
+extern void dump_context(uint64_t *context);
+
+int main(int argc, char **argv)
+{
+ int status;
+ unsigned int *wp;
+ uenv = uwx_init();
+ printf("uwx_init returned %08x\n", uenv);
+ cbinfo = uwx_self_init_info(uenv);
+ status = uwx_register_callbacks(
+ uenv,
+ (intptr_t)cbinfo,
+ uwx_self_copyin,
+ uwx_self_lookupip);
+ printf("uwx_register_callbacks returned %d\n", status);
+ uwx_self_init_context(uenv);
+ printf("In main():\n");
+ dump_context((uint64_t *)uenv);
+ (void) f1();
+ uwx_free(uenv);
+ return 0;
+}
+
+int f1(void)
+{
+ uwx_self_init_context(uenv);
+ printf("In f1():\n");
+ dump_context((uint64_t *)uenv);
+ return f2();
+}
+
+int f2(void)
+{
+ uwx_self_init_context(uenv);
+ printf("In f2():\n");
+ dump_context((uint64_t *)uenv);
+ return f3();
+}
+
+int f3(void)
+{
+ uwx_self_init_context(uenv);
+ printf("In f3():\n");
+ dump_context((uint64_t *)uenv);
+ return f4();
+}
+
+int f4(void)
+{
+ int status;
+ int foo[10];
+ f5(foo);
+ uwx_self_init_context(uenv);
+ printf("In f4():\n");
+ dump_context((uint64_t *)uenv);
+ for (;;) {
+ status = uwx_step(uenv);
+ printf("uwx_step returned %d\n", status);
+ if (status != UWX_OK)
+ break;
+ printf("After step:\n");
+ dump_context((uint64_t *)uenv);
+ }
+ return 0;
+}
+
+int f5(int *foo)
+{
+ foo[0] = 0;
+ return 0;
+}
OpenPOWER on IntegriCloud