| /*
COPYRIGHT (C) 1994 BY
DIGITAL EQUIPMENT CORPORATION, MAYNARD
MASSACHUSETTS. ALL RIGHTS RESERVED.
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE INCLUSION
OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER COPIES
THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY OTHER
PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
NO RESPONSIBILITY IS ASSUMED FOR THE USE OR RELIABILITY OF SOFTWARE
ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL EQUIPMENT CORPORATION.
SUPPORT FOR THIS SOFTWARE IS NOT COVERED UNDER ANY DIGITAL SOFTWARE
PRODUCT SUPPORT CONTRACT, BUT MAY BE PROVIDED UNDER THE TERMS OF THE
CONSULTING AGREEMENT UNDER WHICH THIS SOFTWARE WAS DEVELOPED.
*/
#pragma module dbgdmp "V1.0-00"
#include <starlet.h> /* defines system services */
#include <lib$routines> /* defines the lib$ rtl routines */
#include <descrip.h> /* defines the various descriptors offsets */
#include <string.h> /* for the memcpy call */
#include <stdlib.h> /* for the malloc, free, exit calls */
#include <stdio.h> /* for the printf call */
struct ascic {
unsigned char len;
char faostr[3];
};
/* Define length of data to be dumped */
typedef enum {LONG_LENGTH,WORD_LENGTH,BYTE_LENGTH} length;
/* Define radices */
typedef enum {OCTAL,DECIMAL,HEXADECIMAL,BINARY} radices;
#define dump$c_maxlisiz 80 /* Maximum screen's output size */
#define max_fao_size 40 /* Size of largest of faotables' expanded fao strings */
#define screenwidth 80 /* Width of one full dump listing line */
#define maxlines 20
#define CH$COPY(bytesleft,buffer,a,bytesperline,tempbuffer) \
lib$movc5 (&(bytesleft),(buffer),&(a),&(bytesperline),(tempbuffer));
#define CH$MOVE(length,pointer1,pointer2) \
memcpy ((pointer2),(pointer1),(length));
#define CH$FILL(bytefill,padlength,pointer) \
{ char *src; \
for (src=(pointer);src<(pointer)+(padlength);src++) \
*src=(bytefill);}
#define cstring(data,string) \
{ char *src,*start,*dst = (data).faostr; \
for (src=start=(string); *src !='\0';src++) \
*dst++ = *src; \
(data).len = src - start; \
}
void dump$fao_line(char *buff,int numentperline,int size,
int byte_offset,int num_entries,int format,
struct dsc$descriptor_s *fao,
struct dsc$descriptor_s *outbuff,
unsigned char binary_dump)
{
int i,j;
unsigned char *cp;
unsigned short *cp1;
unsigned long *cp2 ;
unsigned long *ptr;
unsigned long *ptr1;
unsigned char *ptr2;
int min;
int bit_length;
unsigned char *start_of_ptr2;
/* get the minimum of numentperline and num_entries */
min = (numentperline < num_entries ? numentperline : num_entries);
/* allocate a dynamic buffer which hold the values to be converted by the
* sys$faol routine.
*/
if (binary_dump)
ptr = (unsigned long *) malloc ((3+2*numentperline)*sizeof(unsigned long));
else
ptr = (unsigned long *) malloc ((3+numentperline*size)*sizeof(unsigned long));
/* intialize the buffer to all zero's. */
for (i=0; i < 3 + numentperline*size; i++) ptr[i] = 0;
/* For binary format dumping set up the bit length
* and allocates a buffer that will hold the bit value to ASCII
* representation '0' or '1'. Do not forget the space separator (+1)
*/
if (binary_dump){
switch (format) {
case 0 : bit_length = 32;
break;
case 1 : bit_length = 16;
break;
case 2 : bit_length = 8;
}
ptr2= (unsigned char *)malloc(numentperline*(bit_length+1));
start_of_ptr2 = ptr2;
}
/*
* ptr value will be modified by increments. For the sys$faol and the free
* calls save ptr. Copy each byte to a longword, each word to a longword
* and each longword to a longword depending on the format. In order to
* to display data from right to left like the dump command setup the
* pointer to the last data and decrement it. When displayed this will
* give a reading a dumped data from rigth to left. For a binary dump,
* the highest bit must be displayed first and lower bit last.
*/
ptr1 = ptr;
if (!(binary_dump)){
switch (format) {
case 0 : cp2 = (unsigned long *)buff+ min -1;
for (i=0;i<min;i++)
*ptr++ = *cp2--;
break;
case 1 : cp1 = ((unsigned short *)buff)+ min -1;
for (i=0;i<min;i++){
*ptr = (unsigned long)(*cp1--);
ptr++;
}
break;
case 2 : cp = (unsigned char *)buff+min-1;
for (i=0;i<min;i++) {
*ptr = (unsigned long) (*cp--);
ptr++;
}
}/* end switch */
}
else {
switch (format) {
case 0 : cp2 = (unsigned long *)buff+ min -1;
for (i=0;i<min;i++){
for (j=0;j<bit_length;j++)
*ptr2++ = (((*cp2<<j) & (1<<(bit_length-1)))
>>(bit_length-1)) + '0';
cp2--;
*ptr2++ = ' ';
}
break;
case 1 : cp1 = ((unsigned short *)buff)+ min -1;
for (i=0;i<min;i++){
for (j=0;j<bit_length;j++)
*ptr2++ = (((*cp1<<j) & (1<<bit_length))
>>(bit_length-1)) + '0';
cp1--;
*ptr2++ = ' ';
}
break;
case 2 : cp = (unsigned char *)buff+min-1;
for (i=0;i<min;i++) {
for (j=0;j<bit_length;j++)
*ptr2++ = (((*cp<<j) & (1<<(bit_length-1)))
>>(bit_length-1)) + '0';
cp--;
*ptr2++ = ' ';
}
}/* end switch */
for (i=0;i<min;i++){
*ptr++ = bit_length+1;
*ptr++ = (unsigned long)(start_of_ptr2 + (bit_length+1)*i);
}
}
/*
* This last three arguments are expected by the FAO directive. Include them
*/
*ptr++ = (unsigned long)byte_offset;
*ptr++ = (unsigned long)numentperline*size;
*ptr++ = (unsigned long)(buff);
ptr = ptr1;
/*
* The fao directive is contained in the variable fao (passed by descriptor)
* The output buffer when sys$faol will store the result is contained in
* outbuff and ptr is a buffer containing data to be converted to ASCII.
*/
sys$faol (fao,outbuff,outbuff,ptr);
if (binary_dump)
free (start_of_ptr2);
free (ptr1);
}
void dump_buffer (struct dsc$descriptor_s *bufdesc, unsigned int mem_address,
int radix,int length)
{
struct ascic offtable[4] ;
struct ascic *faotable;
$DESCRIPTOR(descr0,"!!!ZL(!AC) |!!!AC| !!!ZLAF");
$DESCRIPTOR(descr1,"!!!!!!ZL(!AC) |!!!!!AC| !!!!!ZLAF");
struct dsc$descriptor_s dump$gl_outdesc = {
0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
char dump$ab_outbuf [dump$c_maxlisiz];
struct dsc$descriptor_s buffer_desc ;
char tempbuffer [512];
struct dsc$descriptor_s tempdesc ;
char tempfaobuf [max_fao_size];
int additional;
int padbytes;
char *buffer;
char *bufferpointer;
struct dsc$descriptor_s *faopointer;
int buffer_length;
unsigned short bytesperline;
unsigned short bytesleft;
int dumpmode;
int dumpwidth;
int mempointer = mem_address;
int modeindex; /* Index into faotable */
int number;
unsigned int entry;
int entrysize; /* Size of one entry */
int entsinbuf;
int entsperline; /* Number of entries on one line */
char plinfaostring [max_fao_size]; /* FAO string for partial lines */
struct dsc$descriptor_s plinfaodesc = { /* Desciptor for partial line fao control string */
0,DSC$K_DTYPE_T, DSC$K_CLASS_S,0};
char faoctrstring [max_fao_size]; /* FAO control string */
struct dsc$descriptor_s faoctrdesc = { /* FAO control string descriptor */
0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
int sizetbl[12] = {9,5,3,11,6,4,12,7,4,33,17,9};
int charsperbyte[4] = {2,3,3,8}; /* Number of ascii chars/byte based on radix */
int sizetable[11] = {
1, /* Table to round entry's per */
2, /* line to nearest lower power*/
4, /* of two. Max length is 32. */
8,
16,
32,
64,
128,
256,
512,
1024};
/* ! FAO control to print buffer offsets */
cstring(offtable[0],"9XL");
cstring(offtable[1],"SL");
cstring(offtable[2],"9OL");
cstring(offtable[3],"9AF");
/*
* The faotable contains in the order an longword, word and byte format
* for the hexadecimal, decimal, octal, binary radices.
*/
faotable = (struct ascic *) malloc (12*sizeof(struct ascic));
cstring(faotable[0],"9XL"); /* Longword hexadecimal */
cstring(faotable[1],"5XW"); /* Word hexadecimal */
cstring(faotable[2],"3XB"); /* Byte hexadecimal */
cstring(faotable[3],"11SL");/* longword decimal */
cstring(faotable[4],"6SW"); /* word decimal */
cstring(faotable[5],"4SB"); /* byte decimal */
cstring(faotable[6],"12OL");/* Longword octal */
cstring(faotable[7],"7OW"); /* word octal */
cstring(faotable[8],"4OB"); /* byte octal */
cstring(faotable[9],"AD"); /* Longword binary */
cstring(faotable[10],"AD"); /* word binary */
cstring(faotable[11],"AD"); /* byte binary */
plinfaodesc.dsc$w_length = max_fao_size;
plinfaodesc.dsc$a_pointer = (char *)plinfaostring;
faoctrdesc.dsc$w_length = max_fao_size;
faoctrdesc.dsc$a_pointer = (char *)faoctrstring;
entry = 0; /* used for entry size calc.*/
if (radix == DECIMAL)
modeindex = 3; /* modeindex index of faotable */
else if (radix == OCTAL)
modeindex = 6;
else if (radix == BINARY)
modeindex = 9;
else
modeindex = 0; /* Default to hex dump */
if (length == LONG_LENGTH) {
dumpmode = 0; /* Dumpmode is the format in dump$fao_line */
entrysize = 4; /* A longword is 4 bytes */
}
else if (length == WORD_LENGTH){
entrysize = 2;
dumpmode = 1;
modeindex = modeindex + 1;
}
else if (length == BYTE_LENGTH){
entrysize = 1;
dumpmode = 2;
modeindex = modeindex + 2;
}
/* Find entries per line and make it the nearest lower power of 2.
*/
entsperline = ((screenwidth - 7)/(sizetbl[modeindex]+entrysize))& (~1);
if (entsperline > 64 ) /* Make sure entsperline is reasonable */
{
printf ("DBGDMP\\DUMP_BUFFER\\ entsperline greater than 64\n");
return;
}
if (entsperline == 0)
entry = 1;
while (entsperline >= sizetable[entry]) /* Find nearest largest power of 2 */
entry = entry + 1; /* from entsperline. */
entsperline = sizetable[entry-1]; /* Make entsperline nearest lower */
/* power of two. */
dumpwidth = entsperline*(sizetbl[modeindex] + entrysize) + 8 + 5;
faoctrdesc.dsc$w_length = max_fao_size;
/*
* convert the fao directive contained in descr0 to a simpler fao directive
* that contains the correct number of entries and the radix.
* This is for plain lines (i.e. lines not completed by spaces)
*/
sys$fao(&descr0,
&faoctrdesc,
&faoctrdesc,
entsperline,
&faotable[modeindex],
&offtable[0],
entsperline * entrysize);
/* Set up FAO control string to be used for partial lines.
*/
sys$fao(&descr1,
&plinfaodesc,
&plinfaodesc,
&faotable[modeindex],
&offtable[0],
entsperline * entrysize);
number = 0;
buffer = bufdesc->dsc$a_pointer;
dump$gl_outdesc.dsc$a_pointer = dump$ab_outbuf;
dump$gl_outdesc.dsc$w_length = dump$c_maxlisiz;
faopointer = &faoctrdesc;
bytesperline = entsperline*entrysize;
entsinbuf = ((bufdesc->dsc$w_length + entrysize - 1)
& (~(entrysize-1)))/entrysize;
bytesleft = bufdesc->dsc$w_length;
while (entsinbuf > 0) {
if (bytesleft < bytesperline) {
/* Copy partial line, zero fill to end */
CH$COPY(bytesleft,buffer +number,0,bytesperline,tempbuffer);
/* Set up work area for partial lines */
tempdesc.dsc$w_length = max_fao_size;
tempdesc.dsc$a_pointer = tempfaobuf;
/* Set up fao with # of entries for partial line */
sys$fao(&plinfaodesc,&tempdesc,&tempdesc,entsinbuf);
/* Use this fao control string instead */
faopointer = &tempdesc;
bufferpointer = tempbuffer;
/* Set output length to default value */
dump$gl_outdesc.dsc$w_length = screenwidth;
/* Format the output line */
dump$fao_line(bufferpointer,entsperline,entrysize,
mempointer+number,entsinbuf,dumpmode,faopointer,
&dump$gl_outdesc,(radix==BINARY));
additional = 0;
/* Calculate padding (word offset)*/
padbytes = dumpwidth - dump$gl_outdesc.dsc$w_length;
if (!(radix == DECIMAL)){
/* Find additional offset */
if ((additional = bytesleft % entrysize) > 0)
{
/* Customize it to type of dump */
additional = (entrysize - additional) *
charsperbyte[modeindex/3] + 1;
padbytes = padbytes + additional;
}
}
CH$MOVE(dump$gl_outdesc.dsc$w_length - additional,
dump$gl_outdesc.dsc$a_pointer + additional,
dump$gl_outdesc.dsc$a_pointer + padbytes);
/* Move blanks to pad areas */
CH$FILL(' ',padbytes,dump$gl_outdesc.dsc$a_pointer);
/* Set output length to */
dump$gl_outdesc.dsc$w_length = dumpwidth;
}
else
{
/* Dump full line */
bufferpointer = &buffer[number];
/* Set output length to default value */
dump$gl_outdesc.dsc$w_length = screenwidth ;
/* Format the output line */
dump$fao_line(bufferpointer,entsperline,entrysize,
mempointer+number,entsinbuf,dumpmode,faopointer,
&dump$gl_outdesc,(radix == BINARY));
}
printf ("\n%.*s",dump$gl_outdesc.dsc$w_length,dump$gl_outdesc.dsc$a_pointer);
/* Calculate next index */
number = number + bytesperline;
/* Update # of entry's in buffer */
entsinbuf = entsinbuf - entsperline;
/* Calculate how many bytes left in buffer */
bytesleft = bytesleft - (entsperline*entrysize);
}
free (faotable);
}
|
|
Why not use STEP/RET? Why do they need to know how many steps? The number
of steps could easily vary with compiler version. Note that with RISC
machine like AXP, the compilers have many more choices to make on how to
"package" machine instructions (many more instructions per line) into lines.
This is good for performance optimizations...and some optimization seems
to creep through even with the /NOOPT switch. Look at the .LIS file created
by the compiler with /LIST/MACHINE switchs...that should show you how the
compiler has organized the instructions and lines. Also, from the debugger
source and instruction view:
12: FUNCTION SUM (a,b,c,d,e)
13: SUM=a
14: 1 + b
15: 2 + c
16: 3 + d
17: 4 +e
-> 18: RETURN
19: END
Line 12: BIS R31,FP,R24
: BIS R31,R27,FP
: BIS R31,R16,R23
: BIS R31,R17,R22
: BIS R31,R18,R21
: BIS R31,R19,R1
: BIS R31,R20,R0
Line 13: LDF F0,(R23)
Line 14: LDF F10,(R22)
Line 13: ADDF F0,F10,F0
Line 15: LDF F11,(R21)
Line 13: ADDF F0,F11,F0
Line 16: LDF F10,(R1)
Line 13: ADDF F0,F10,F0
Line 17: LDF F11,(R0)
Line 13: ADDF F0,F11,F1
-> Line 18: CPYS F1,F1,F0
: BIS R31,R24,FP
: RET R31,(R26)
You can see that the compiler has organized the first LDF and all the ADDFs
into line 13 and all the remaining LDFs into separte lines. The point is,
that you're issue needs to be taken to the compiler folks. The debugger is
merely stepping the lines that the compiler generated. I nonetheless feel
that this is just one of the "things" to get used to with this newer RISCer
archetecture.
Lon
|