Logo Search packages:      
Sourcecode: lcrash version File versions  Download package

trace_s390x.c

/*
 * $Id: trace_s390x.c,v 1.1 2004/12/21 23:26:18 tjm Exp $
 *
 * This file is part of lcrash, an analysis tool for Linux memory dumps.
 *
 * Created by Silicon Graphics, Inc.
 * Contributions by IBM, and others
 *
 * Copyright (C) 1999 - 2002 Silicon Graphics, Inc. All rights reserved.
 * Copyright (C) 2001 - 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. See the file COPYING for more
 * information.
 */

#include <lcrash.h>

extern void print_active_stacks(FILE* ofp);

static int using_async_stack = 0; 

/*
 * function declarations
 */

static int check_alloca_patch(void);
static int init_async_stack_s390x(void*, trace_t*);
static kaddr_t intr_backchain_s390x(kaddr_t, trace_t*);
static kaddr_t intr_check_psw_s390x(kaddr_t);
static kaddr_t build_stack_strace_s390x(kaddr_t, trace_t*, int, int);
static void print_lowcore_s390x(void* lc, FILE* ofp);
static int get_stack_index(kaddr_t sp,trace_t *trace);

/*
 * function definitions
 */

/*
 * get_stack_index() - return index of stack for addr 'sp'
 *                 return -1 if sp is out of range
 */
static int
get_stack_index(kaddr_t sp,trace_t *trace)
{
      if((sp >= trace->stack[0].addr) && (sp < trace->stack[0].addr + trace->stack[0].size)){
            return 0;
      } else if((sp >= trace->stack[1].addr) && (sp < trace->stack[1].addr + trace->stack[1].size) && using_async_stack){
            return 1;
      } else {
            return -1;
      }
}

/*
 * check_alloca_patch() - determine if 2nd order alloca patch was applied
 */
static int
check_alloca_patch(void)
{
      if(kl_is_member("_lowcore", "task_struct")){
            return(1);
      } else {
            return(0);
      }
}

/*
 * init_async_stck() - get lower memory boundary for async_stack
 */
static int
init_async_stack_s390x(void* lc, trace_t *trace)
{
      kaddr_t saddr = 0;

      using_async_stack = 0;

      /* get start of async stack */
      if(!kl_is_member("_lowcore", "async_stack")){
            return(0);
      }
      
      if(!lc || !trace){
            return(0);
      }
      
      saddr = KL_GET_PTR(K_ADDR(lc, "_lowcore", "async_stack"));
      /* From the kernel code: */
      /* lowcore_ptr[i]->async_stack = async_stack + (ASYNC_SIZE) */
      /* Therefore we have to subtract ASYNC_SIZE here */
      trace->stack[1].addr = saddr - trace->stack[1].size;

      /* stack[1].ptr has been allocated before entering this func */
      GET_BLOCK(trace->stack[1].addr, trace->stack[1].size, trace->stack[1].ptr);
      if (KL_ERROR) {
            return(1);
      }
      using_async_stack = 1;
      return(0);
}

/*
 * intr_backchain_s390x() - determine backchain for interrupt stack frames
 */
static kaddr_t
intr_backchain_s390x(kaddr_t sp, trace_t* trace)
{
      int r15_off;
      kaddr_t new_sp;

      /* we just look for gr15 in stack frame */
        /* skip PSW and gr0 to gr14 */
      r15_off = STD_SFRAME_SIZE_S390X + kl_member_offset("pt_regs", "gprs") + 15 * KL_NBPW;
      if(get_stack_index(sp + r15_off, trace) != -1)
            new_sp = KL_VREAD_PTR(sp + r15_off);
      else 
            new_sp = -1;
      return (new_sp);
}


/*
 * intr_check_psw_s390x() - check for user(return(1)) or kernel (0) psw
 */
static kaddr_t
intr_check_psw_s390x(kaddr_t sp)
{
      int psw_off;
      kaddr_t psw_flags;

      /* we just look for the psw in stack frame */
      psw_off = STD_SFRAME_SIZE_S390X + kl_member_offset("pt_regs","psw");

      /* read first part of psw */
      psw_flags = KL_VREAD_PTR(sp + psw_off);
      return (IS_USER_PSW_S390X(psw_flags));
}


/* 
 * setup_trace_rec_s390x()
 */
int
setup_trace_rec_s390x(kaddr_t saddr, kaddr_t task, int flag, trace_t *trace)
{
      int aflag = K_TEMP;
      kl_reset_error();
      if (flag & C_PERM) {
            aflag = K_PERM;
      }

      if (task) {
            trace->tsp = kl_alloc_block(TASK_STRUCT_SZ, aflag);
            if (kl_get_task_struct(task, 2, trace->tsp)) {
                  kl_free_block(trace->tsp);
                  trace->tsp = NULL;
                  return(1);
            }
                if(KL_LINUX_RELEASE >= LINUX_2_6_0){
                        saddr = kl_kaddr(trace->tsp,"task_struct","thread_info");
                } else {
                  saddr=task;
                }
      }

      trace->frame = NULL;
      trace->stack[0].type = S_KERNELSTACK;
      trace->stack[0].size = STACK_SIZE;

      /* Get the base address of the stack (is task)
       */
      trace->stack[0].addr = saddr;
      trace->stack[0].ptr = kl_alloc_block(trace->stack[0].size, aflag);
      if (KL_ERROR) {
            clean_trace_rec(trace);
            return(1);
      }
      GET_BLOCK(trace->stack[0].addr, trace->stack[0].size, trace->stack[0].ptr);
      if (KL_ERROR) {
            clean_trace_rec(trace);
            return(1);
      }

      trace->stack[1].type = S_ASYNCSTACK;
      trace->stack[1].size = STACK_SIZE;

      trace->stack[1].addr = 0;
      trace->stack[1].ptr = kl_alloc_block(trace->stack[1].size, aflag);
      if (KL_ERROR) {
            clean_trace_rec(trace);
            return(1);
      }

      return(0);
}

/*
 * print_trace_s390x()
 */
void
print_trace_s390x(trace_t *trace, int flags, FILE *ofp)
{
      int offset;
      sframe_t *frmp;
      if ((frmp = trace->frame)) {
            do {
                  fprintf(ofp, "%2d %s", frmp->level, frmp->funcname);
                  offset = pc_offset(frmp->pc);
                  if (offset > 0) {
                        fprintf(ofp, "+%d", offset);
                  } else if (offset < 0) {
                        fprintf(ofp, "+<ERROR>");
                  }
                  fprintf(ofp, " [%#"FMTPTR"x]\n", (uint64_t) frmp->pc);
                  if (flags & C_FULL) {
                        fprintf(ofp, "\n");
                        fprintf(ofp, "   SP=%#"FMTPTR"x, "
                              "FP=%#"FMTPTR"x, SIZE=%d\n\n",
                              (uint64_t) frmp->sp, 
                              (uint64_t) frmp->fp,
                              frmp->frame_size);
                        if(frmp->asp){
                              dump_stack_frame(trace, frmp, ofp);
                        }
                  }
                  if (frmp->error) {
                        fprintf(ofp, "TRACE ERROR %#"FMT64"x\n", 
                              (uint64_t) frmp->error);
                  }
                  frmp = frmp->next;
            } while (frmp != trace->frame);
      }
}


/*
 * build_stack_strace_s390x()
 *   -sp:     stack-pointer where to start the trace
 *   -trace:  pointer to trace structure
 *   -flags:  trace options
 *   -skip:   number of stackframes to skip
 */
static kaddr_t
build_stack_strace_s390x(kaddr_t sp, trace_t* trace, int flags, int skip)
{
      sframe_t *curframe;
      char     *func_name;
      syment_t *sym;
      int       curstkidx = 0;
      int       frame_size;
      int       cur_fsize;
      kaddr_t   backchain;   /* next stack frame */
      kaddr_t   ip = 0;      /* instruction address */
      uaddr_t   sp_copy = 0; /* address in our stack-copy */
      int       stack_switch_count = 0; /* how often have we switched between kernel and async stack ? */
      int       si;
      int       backchain_offset, r14_offset;
      

      /* get offset for backchain and register 14 */

      if(kl_struct_len("stack_frame") != 0){
            /*
            The two stack frame layouts:

            struct stack_frame_old {
                  unsigned long back_chain;
                  unsigned long empty1[5];
                  unsigned long gprs[10];
                  unsigned int  empty2[8];
            };

            struct stack_frame_packed {
                  unsigned long empty1[5];
                  unsigned int  empty2[8];
                  unsigned long gprs[10];
                  unsigned long back_chain;
            };
            */
            backchain_offset = kl_member_offset("stack_frame","back_chain");
            r14_offset=kl_member_offset("stack_frame","gprs") + 8*8;
      } else {
            backchain_offset = 0;
            r14_offset=RA_OFFSET_S390X;
      }

      si = get_stack_index(sp,trace);

      if(si < 0) {
            func_name = "<invalid kernel stack>";
            curframe  = alloc_sframe(trace, flags);
            UPDATE_FRAME(func_name, ip, 0 , sp, sp + 96,
                       0, 0, 0, KL_NBPW);
            return 0;
      }

      sp_copy = (uaddr_t)trace->stack[si].ptr +
            (uaddr_t)(sp - trace->stack[si].addr);

      /* following cast should be replaced with something more portable? */
      backchain = KL_GET_PTR((void*)sp_copy + backchain_offset);

      /* check for interrupt stack frame */
      if(!backchain && !intr_check_psw_s390x(sp) && (si != 0)){
            /* found kernel psw */
            backchain = intr_backchain_s390x(sp,trace);
      }

      if(skip <= 0) {

            ip      = KL_GET_PTR((void*)(sp_copy + r14_offset));
            sym     = kl_lkup_symaddr(ip);
            if(!sym){
                  func_name = "<sym not found>";
            } else {
                  func_name = sym->s_name;
            }

            /* end of stack - sp, this is the maximal frame size*/
            frame_size = trace->stack[si].addr + STACK_SIZE - sp; 
            if(get_stack_index(backchain,trace) == si) {
                  /* we are still in same stack page frames */
                  cur_fsize = backchain - sp;
                  if( cur_fsize < frame_size ) {
                        frame_size = cur_fsize;
                  }
            }
            curframe  = alloc_sframe(trace, flags);
            UPDATE_FRAME(func_name, ip, 0 , sp, sp + 96, 
                       sp_copy, 0, 0, frame_size);
      }

      /* check if new backchain is valid */ 
      if( (sp >= backchain) && (backchain != 0) ) {
            if (!using_async_stack || stack_switch_count){
                  /* no switch from async to kernel stack allowed */
                  func_name = "<back chain invalid>";
                  curframe  = alloc_sframe(trace, flags);
                  UPDATE_FRAME(func_name, ip, 0 , backchain, 
                             backchain + 96, 0, 0, 0, KL_NBPW);
                  return 0;
            }
      }

      if((get_stack_index(sp,trace) == 1) 
            && (get_stack_index(backchain,trace) == 0))
            ++stack_switch_count;
            
      if(backchain) {
            return build_stack_strace_s390x(backchain, trace, flags, --skip);
      } else {
            return 0;
      }
}

/*
 * task_trace_s390x()
 */
int
task_trace_s390x(kaddr_t task, int flags, FILE *ofp)
{
      trace_t *trace;
      kaddr_t ksp;     /* kernel stack pointer */

      trace = (trace_t *)alloc_trace_rec(C_TEMP);     

      if (!trace) {
            fprintf(KL_ERRORFP, "Could not alloc trace rec!\n");
            return(1);
      } 
 
      setup_trace_rec_s390x(0, task, 0, trace);
      if (KL_ERROR) {
            fprintf(KL_ERRORFP, "Error setting up trace rec!\n");
            free_trace_rec(trace);
            return(1);
      }

      trace_banner(ofp);

      /* check if task was active. If yes, reset stack pointer */

      if(task_has_cpu(task,trace->tsp))
      {
            void* lc;
            char* comm;
            int processor;
            kaddr_t addr;

            comm = K_PTR(trace->tsp,"task_struct","comm");
            processor = task_cpu(trace->tsp);

            lc = get_cpu_lowcore_s390(processor);

            fprintf(ofp, "TASK HAS CPU (%i): %#"FMT64"x (%s):\n", 
                  processor, (uint64_t) task, comm);

            addr = KL_GET_PTR(K_ADDR(lc, "_lowcore",
                                         "st_status_fixed_logout"));


            if(IS_USER_PSW_S390X(addr)){
                        /* problem state bit set in current psw */
                        fprintf(ofp,"Seems to run in userspace.\n");
                        ksp = 0;
                } else {
                  /* register 15 contains stack pointer */
                  ksp = KL_GET_PTR(K_ADDR(lc, "_lowcore", 
                              "gpregs_save_area") + (15 * KL_NBPW));
                  init_async_stack_s390x(lc, trace);
            }
            print_lowcore_s390x(lc, ofp);
            fprintf(ofp,"\n");
            free_cpu_lowcore_s390(lc);
      } else {

            /* find out kernel stack pointer */

            if (LINUX_2_2_X(KL_LINUX_RELEASE)) {
                        ksp = KL_UINT(K_PTR(trace->tsp,"task_struct","tss"),
                               "thread_struct","ksp");
            }
            else{
                  ksp = KL_UINT(K_PTR(trace->tsp,"task_struct","thread"),
                               "thread_struct","ksp");
            }

            fprintf(ofp, "STACK TRACE FOR TASK: %#lx (%s)\n\n",
                  (unsigned long) task,
                  (char*)K_PTR(trace->tsp, "task_struct", "comm"));
      }

      if(!ksp) goto out;

      /* do the backtrace */
      if(task_has_cpu(task,trace->tsp)){
            /* we skip the first frame in case of an active process */
            build_stack_strace_s390x(ksp, trace, flags, 1);
      } else {
            build_stack_strace_s390x(ksp, trace, flags, 0);
      }
      if (KL_ERROR) {
            fprintf(KL_ERRORFP, "Error setting up trace rec!\n");
            free_trace_rec(trace);
            return -1;
      }
      fprintf(ofp, " STACK:\n");
      print_trace_s390x(trace, flags, ofp);
 out:
      free_trace_rec(trace);
      return 0;
}

/*
 * print_traces_s390x()
 *
 *   Output a list of all valid code addresses contained in a stack
 *   along with their function name and stack location.
 */
int
print_traces_s390x(kaddr_t saddr, int level, int flags, FILE *ofp)
{
      trace_t *trace;
      trace = (trace_t *)alloc_trace_rec(C_TEMP);
      if (!trace) {
            fprintf(KL_ERRORFP, "Could not alloc trace rec!\n");
            return -1;
      }
      setup_trace_rec_s390x(saddr, 0, 0, trace);
      init_async_stack_s390x(0, 0);
      build_stack_strace_s390x(saddr,trace,flags,0);

      if (trace->nframes >= level) {
                  trace_banner(ofp);
                  fprintf(ofp, "TRACE FOR STACK PTR: %#lx \n\n", 
                        (unsigned long) saddr);
                  print_trace_s390x(trace, flags, ofp);
                  trace_banner(ofp);
      }

      return(0);
}

/*
 * dumptask_trace_s390x()
 */
static int
dumptask_trace_s390x(kaddr_t curtask, int flags, FILE *ofp)
{
      print_active_stacks(ofp);
      return(0);
}

/*
 * trace_init_s390x()
 */
int
trace_init_s390x(void)
{
      SETUP_TRACE_REC = setup_trace_rec_s390x;
      PRINT_TRACE = print_trace_s390x;
      TASK_TRACE = task_trace_s390x;
      PRINT_TRACES = print_traces_s390x;
      DUMPTASK_TRACE  = dumptask_trace_s390x;   
      STACK_SEGMENTS = STACK_SEGMENTS_S390X;

      if(kl_struct_len("thread_union") != 0){
            STACK_SIZE = kl_struct_len("thread_union");
      } else if(kl_struct_len("kernel_stack_size") != 0) {
            /* try to get size of struct kernel_stack_size from kerntypes */
            STACK_SIZE = kl_struct_len("kernel_stack_size");
      } else if(check_alloca_patch()) {
            STACK_SIZE = ALLOCA_PATCH_STK_SZ;
      } else {
            STACK_SIZE = STACK_SIZE_S390X;
      }
      return(0);
}

/*
 * print s390x lowcore
 */
static void
print_lowcore_s390x(void* lc, FILE* ofp)
{
      syment_t* sym;
      void* ptr;
      kaddr_t tmp[4];

      fprintf(ofp," LOWCORE INFO:\n");
      ptr = K_PTR(lc,"_lowcore","st_status_fixed_logout");
      tmp[0]=KL_GET_PTR(ptr);
      tmp[1]=KL_GET_PTR(ptr + KL_NBPW);
      fprintf(ofp,"  -psw      : %#018"FMT64"x %#018"FMT64"x\n",
            tmp[0],     tmp[1]);

      sym = kl_lkup_symaddr(tmp[1]);
      if(sym && (ptr != 0)){
            fprintf(ofp,"  -function : %s+%u\n",sym->s_name,
                  pc_offset(tmp[1]));
      }
      else{
            fprintf(ofp,"  -function : not found in System map\n");
      }

      ptr = K_PTR(lc,"_lowcore","prefixreg_save_area");
      tmp[0] = KL_GET_UINT32(ptr);
      fprintf(ofp,"  -prefix   : %#010x\n", (uint32_t)tmp[0]);

      ptr = K_PTR(lc,"_lowcore","cpu_timer_save_area");     
      tmp[0]=KL_GET_UINT32(ptr);
      tmp[1]=KL_GET_UINT32(ptr + 4);
      fprintf(ofp,"  -cpu timer: %#010x %#010x\n", (uint32_t)tmp[0],
            (uint32_t)tmp[1]);

      ptr = K_PTR(lc,"_lowcore","clock_comp_save_area");
      tmp[0]=KL_GET_UINT32(ptr);
      tmp[1]=KL_GET_UINT32(ptr + 4);
      fprintf(ofp,"  -clock cmp: %#010x %#010x\n", (uint32_t)tmp[0],
            (uint32_t)tmp[1]);

      fprintf(ofp,"  -general registers:\n");
      ptr = K_PTR(lc,"_lowcore","gpregs_save_area");
      tmp[0]=KL_GET_PTR(ptr);
      tmp[1]=KL_GET_PTR(ptr + KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 2 * KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 3 * KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 4 * KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 5 * KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 6 * KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 7 * KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 8 * KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 9 * KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 10* KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 11* KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 12* KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 13* KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 14* KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 15* KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);

      fprintf(ofp,"  -access registers:\n");
      ptr = K_PTR(lc,"_lowcore","access_regs_save_area");
      tmp[0]=KL_GET_UINT32(ptr);
      tmp[1]=KL_GET_UINT32(ptr + 4);
      tmp[2]=KL_GET_UINT32(ptr + 2 * 4);
      tmp[3]=KL_GET_UINT32(ptr + 3 * 4);
      fprintf(ofp,"     %#010x %#010x %#010x %#010x\n", (uint32_t)tmp[0],
            (uint32_t)tmp[1], (uint32_t)tmp[2], (uint32_t)tmp[3]);
      tmp[0]=KL_GET_UINT32(ptr + 4 * 4);
      tmp[1]=KL_GET_UINT32(ptr + 5 * 4);
      tmp[2]=KL_GET_UINT32(ptr + 6 * 4);
      tmp[3]=KL_GET_UINT32(ptr + 7 * 4);
      fprintf(ofp,"     %#010x %#010x %#010x %#010x\n", (uint32_t)tmp[0],
            (uint32_t)tmp[1], (uint32_t)tmp[2], (uint32_t)tmp[3]);
      tmp[0]=KL_GET_UINT32(ptr + 8 * 4);
      tmp[1]=KL_GET_UINT32(ptr + 9 * 4);
      tmp[2]=KL_GET_UINT32(ptr + 10* 4);
      tmp[3]=KL_GET_UINT32(ptr + 11* 4);
      fprintf(ofp,"     %#010x %#010x %#010x %#010x\n", (uint32_t)tmp[0],
            (uint32_t)tmp[1], (uint32_t)tmp[2], (uint32_t)tmp[3]);
      tmp[0]=KL_GET_UINT32(ptr + 12* 4);
      tmp[1]=KL_GET_UINT32(ptr + 13* 4);
      tmp[2]=KL_GET_UINT32(ptr + 14* 4);
      tmp[3]=KL_GET_UINT32(ptr + 15* 4);
      fprintf(ofp,"     %#010x %#010x %#010x %#010x\n", (uint32_t)tmp[0],
            (uint32_t)tmp[1], (uint32_t)tmp[2], (uint32_t)tmp[3]);

      fprintf(ofp,"  -control registers:\n");
      ptr = K_PTR(lc,"_lowcore","cregs_save_area");
      tmp[0]=KL_GET_PTR(ptr);
      tmp[1]=KL_GET_PTR(ptr + KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 2 * KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 3 * KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 4 * KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 5 * KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 6 * KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 7 * KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 8 * KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 9 * KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 10* KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 11* KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 12* KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 13* KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 14* KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 15* KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      
      fprintf(ofp,"  -floating point registers:\n");
      ptr = K_PTR(lc,"_lowcore","floating_pt_save_area");
      tmp[0]=KL_GET_PTR(ptr);
      tmp[1]=KL_GET_PTR(ptr + KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 2 * KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 3 * KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 4 * KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 5 * KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 6 * KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 7 * KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 8 * KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 9 * KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 10* KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 11* KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
      tmp[0]=KL_GET_PTR(ptr + 12* KL_NBPW);
      tmp[1]=KL_GET_PTR(ptr + 13* KL_NBPW);
      tmp[2]=KL_GET_PTR(ptr + 14* KL_NBPW);
      tmp[3]=KL_GET_PTR(ptr + 15* KL_NBPW);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[0], tmp[1]);
      fprintf(ofp,"     %#018"FMT64"x %#018"FMT64"x\n", tmp[2], tmp[3]);
}

Generated by  Doxygen 1.6.0   Back to index