summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ia64/libuwx/src/uwx_step.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ia64/libuwx/src/uwx_step.c')
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_step.c827
1 files changed, 0 insertions, 827 deletions
diff --git a/sys/contrib/ia64/libuwx/src/uwx_step.c b/sys/contrib/ia64/libuwx/src/uwx_step.c
deleted file mode 100644
index 42b8c93..0000000
--- a/sys/contrib/ia64/libuwx/src/uwx_step.c
+++ /dev/null
@@ -1,827 +0,0 @@
-/*
-Copyright (c) 2003-2006 Hewlett-Packard Development Company, L.P.
-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_uinfo.h"
-#include "uwx_scoreboard.h"
-#include "uwx_str.h"
-#include "uwx_step.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_freg(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_lookupip_hook: Hook routine so dynamic instrumentation */
-/* tools can intercept Lookup IP events. When not */
-/* intercepted, it just returns "Not found", so that */
-/* the callback routine is invoked. */
-
-/*ARGSUSED*/
-int uwx_lookupip_hook(int request, uint64_t ip, intptr_t tok, uint64_t **vecp,
- size_t uvecsize)
-{
- return UWX_LKUP_NOTFOUND;
-}
-
-
-/* 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;
- int cbcalled = 0;
- uint64_t ip;
- uint64_t *uvec;
- uint64_t *rstate;
- struct uwx_utable_entry uentry;
- uint64_t uvecout[UVECSIZE];
-
- if (env->copyin == 0 || env->lookupip == 0)
- return UWX_ERR_NOCALLBACKS;
-
- env->ptr_size = DWORDSZ;
- env->code_start = 0;
- env->function_offset = -1LL;
- env->function_name = 0;
- env->module_name = 0;
- env->abi_context = 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. */
-
- /* When self-unwinding, we call a hook routine before the */
- /* callback. If the application is running under control of */
- /* a dynamic instrumentation tool, that tool will have an */
- /* opportunity to intercept lookup IP requests. */
-
- i = 0;
- uvecout[i++] = UWX_KEY_VERSION;
- uvecout[i++] = UWX_VERSION;
- 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 = UWX_LKUP_NOTFOUND;
- ip = env->context.special[UWX_REG_IP];
- env->remapped_ip = ip;
-
- /* Call the hook routine. */
-
- if (env->remote == 0)
- cbstatus = uwx_lookupip_hook(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec,
- sizeof(uvecout));
-
- /* If the hook routine remapped the IP, use the new IP for */
- /* the callback instead of the original IP. */
-
- if (cbstatus == UWX_LKUP_REMAP) {
- for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
- switch ((int)uvec[i]) {
- case UWX_KEY_NEWIP:
- ip = uvec[i+1];
- break;
- }
- }
- env->remapped_ip = ip;
- }
-
- /* Now call the callback routine unless the hook routine gave */
- /* us all the info. */
-
- if (cbstatus == UWX_LKUP_NOTFOUND || cbstatus == UWX_LKUP_REMAP) {
- cbcalled = 1;
- cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, ip, env->cb_token, &uvec);
- }
-
- /* If the callback routine remapped the IP, call it one more time */
- /* with the new IP. */
-
- if (cbstatus == UWX_LKUP_REMAP) {
- for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
- switch ((int)uvec[i]) {
- case UWX_KEY_NEWIP:
- ip = uvec[i+1];
- break;
- }
- }
- env->remapped_ip = ip;
- cbstatus = (*env->lookupip)(UWX_LKUP_LOOKUP, 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, ip, uvec, &uentry);
- if (cbcalled)
- (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
- if (status == UWX_OK) {
- env->ptr_size = uentry.ptr_size;
- env->code_start = uentry.code_start;
- status = uwx_decode_uinfo(env, &uentry, &rstate);
- }
- if (status == UWX_ERR_NOUENTRY || status == UWX_ERR_NOUDESC)
- status = uwx_default_rstate(env, &rstate);
- if (status == UWX_OK)
- env->rstate = rstate;
- }
-
- /* If the callback returns an unwind info block, we can */
- /* proceed directly to decoding the unwind information. */
-
- else if (cbstatus == UWX_LKUP_UINFO) {
- uentry.ptr_size = DWORDSZ;
- uentry.code_start = 0;
- uentry.code_end = 0;
- uentry.unwind_info = 0;
- uentry.unwind_flags = 0;
- for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
- switch ((int)uvec[i]) {
- case UWX_KEY_UFLAGS:
- uentry.unwind_flags = uvec[i+1];
- if (uentry.unwind_flags & UNWIND_TBL_32BIT)
- uentry.ptr_size = WORDSZ;
- break;
- case UWX_KEY_UINFO:
- uentry.unwind_info = uvec[i+1];
- break;
- case UWX_KEY_GP:
- uwx_set_reg(env, UWX_REG_GP, uvec[i+1]);
- break;
- case UWX_KEY_MODULE:
- env->module_name =
- uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
- break;
- case UWX_KEY_FUNC:
- env->function_name =
- uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
- break;
- case UWX_KEY_FUNCSTART:
- uentry.code_start = uvec[i+1];
- env->code_start = uentry.code_start;
- break;
- }
- }
- env->ptr_size = uentry.ptr_size;
- if (cbcalled)
- (void) (*env->lookupip)(UWX_LKUP_FREE, 0, env->cb_token, &uvec);
- status = uwx_decode_uinfo(env, &uentry, &rstate);
- if (status == UWX_ERR_NOUDESC)
- 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);
- if (cbcalled)
- (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_restore_markers: Restores the stack markers -- PSP, RP, PFS */
-
-int uwx_restore_markers(struct uwx_env *env)
-{
- int status;
- uint64_t val;
- uint64_t hist;
-
- 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)
-
- 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;
- env->context.valid_regs |= 1 << UWX_REG_PSP;
- 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;
- env->context.valid_regs |= 1 << UWX_REG_RP;
- 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;
- env->context.valid_regs |= 1 << UWX_REG_PFS;
- TRACE_S_RESTORE_REG("PFS", env->rstate[SBREG_PFS], val)
- }
-
- return UWX_OK;
-}
-
-/* uwx_get_module_info: Gets module name and text base for current frame */
-
-int uwx_get_module_info(
- struct uwx_env *env,
- char **modp,
- uint64_t *text_base)
-{
- int i;
- int status;
- int cbstatus;
- uint64_t ip;
- uint64_t *uvec;
- uint64_t uvecout[UVECSIZE];
-
- if (env == 0)
- return UWX_ERR_NOENV;
-
- /* 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 module name from the lookup IP callback. */
- if (env->module_name == 0) {
- ip = env->remapped_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_MODULE, 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_TBASE:
- env->text_base = uvec[i+1];
- break;
- case UWX_KEY_MODULE:
- env->module_name =
- uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
- break;
- case UWX_KEY_FUNC:
- env->function_name =
- uwx_alloc_str(env, (char *)(intptr_t)(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;
- *text_base = env->text_base;
-
- return UWX_OK;
-}
-
-/* uwx_get_funcstart: Gets start address of function from current frame */
-
-int uwx_get_funcstart(
- struct uwx_env *env,
- uint64_t *funcstart)
-{
- int status;
-
- if (env == 0)
- return UWX_ERR_NOENV;
-
- /* 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;
- }
-
- *funcstart = env->remapped_ip - env->function_offset;
-
- return UWX_OK;
-}
-
-/* uwx_get_sym_info: Gets symbolic info from current frame */
-/* (Will make a UWX_LKUP_SYMBOLS callback if info */
-/* was not provided by UWX_LKUP_LOOKUP callback) */
-
-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[UVECSIZE];
- int i;
-
- if (env == 0)
- return UWX_ERR_NOENV;
-
- /* 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->remapped_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, 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 *)(intptr_t)(uvec[i+1]));
- break;
- case UWX_KEY_FUNC:
- env->function_name =
- uwx_alloc_str(env, (char *)(intptr_t)(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;
-
- /* Complete the current context by restoring the current values */
- /* of psp, rp, and pfs. */
-
- if (env->rstate == 0 ||
- (env->context.valid_regs & VALID_MARKERS) != VALID_MARKERS) {
- status = uwx_restore_markers(env);
- if (status != UWX_OK)
- return status;
- }
-
- /* 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_freg(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_AR_RNAT] = val;
- env->history.special[UWX_REG_AR_RNAT] = hist;
- env->context.valid_regs |= 1 << UWX_REG_AR_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_AR_UNAT] = val;
- env->history.special[UWX_REG_AR_UNAT] = hist;
- env->context.valid_regs |= 1 << UWX_REG_AR_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_AR_FPSR] = val;
- env->history.special[UWX_REG_AR_FPSR] = hist;
- env->context.valid_regs |= 1 << UWX_REG_AR_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_AR_LC] = val;
- env->history.special[UWX_REG_AR_LC] = hist;
- env->context.valid_regs |= 1 << UWX_REG_AR_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;
- env->context.valid_regs &= ~VALID_MARKERS;
-
- 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)
-{
- int i;
- int status;
-
- status = uwx_default_rstate(env, rstate);
- if (status != UWX_OK)
- return status;
-
- for (i = 0; uvec[i] != UWX_KEY_END; i += 2) {
- switch ((int)uvec[i]) {
- case UWX_KEY_CONTEXT:
- env->abi_context = (int)(uvec[i+1]);
- status = UWX_ABI_FRAME;
- break;
- case UWX_KEY_GP:
- uwx_set_reg(env, UWX_REG_GP, uvec[i+1]);
- break;
- case UWX_KEY_MODULE:
- env->module_name =
- uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
- break;
- case UWX_KEY_FUNC:
- env->function_name =
- uwx_alloc_str(env, (char *)(intptr_t)(uvec[i+1]));
- break;
- case UWX_KEY_FUNCSTART:
- env->function_offset = env->remapped_ip - uvec[i+1];
- break;
- default:
- return UWX_ERR_CANTUNWIND;
- }
- }
- return status;
-}
-
-
-/* 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 *)(intptr_t)(dest) = \
- *(uint64_t *)(intptr_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;
-}
-
-#define COPYIN_MSTACK_16(dest, src) \
- (env->remote? \
- (*env->copyin)(UWX_COPYIN_MSTACK, (dest), (src), \
- 2*DWORDSZ, env->cb_token) : \
- (*(uint64_t *)(intptr_t)(dest) = *(uint64_t *)(intptr_t)(src), \
- *(uint64_t *)(intptr_t)((dest)+8) = \
- *(uint64_t *)(intptr_t)((src)+8), \
- 2*DWORDSZ) )
-
-int uwx_restore_freg(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_SPREL(0):
- p = env->context.special[UWX_REG_SP] +
- UWX_GET_DISP_OFFSET(rstate);
- n = COPYIN_MSTACK_16((char *)valp, p);
- if (n != 2*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_16((char *)valp, p);
- if (n != 2*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;
-}
-
OpenPOWER on IntegriCloud