BSD 4_1c_2 release
[unix-history] / usr / src / old / sdb / opset.c
#ifndef lint
static char sccsid[] = "@(#)opset.c 4.2 10/27/82";
#endif lint
/*
* UNIX debugger
* Instruction printing routines.
* MACHINE DEPENDENT
*/
#ifdef ADB
#include "defs.h"
#endif ADB
#ifdef SDB
#include "head.h"
#endif SDB
L_INT dot;
INT dotinc;
L_INT insoutvar[36];
#ifdef ADB
L_INT var[36];
#endif ADB
#undef INSTTAB
#include "instrs.h"
STRING regname[];
STRING fltimm[];
POS type, space, incp;
/*
* Definitions for registers and for operand classes
*/
char *insregname(); /* how to print a register */
#define R_PC 0xF
#define OC_IMM0 0x0
#define OC_IMM1 0x1
#define OC_IMM2 0x2
#define OC_IMM3 0x3
#define OC_INDEX 0x4
#define OC_REG 0x5
#define OC_DREG 0x6
#define OC_ADREG 0x7
#define OC_AIREG 0x8
#define OC_DAIREG 0x9
#define OC_BDISP 0xA
#define OC_DBDISP 0xB
#define OC_WDISP 0xC
#define OC_DWDISP 0xD
#define OC_LDISP 0xE
#define OC_DLDISP 0xF
#define OC_SHIFT 4
#define OC_CONS(oc,reg) (((oc & 0xF) << OC_SHIFT) | (reg & 0xF))
#define OC_AMEXT(x) (((x) >> OC_SHIFT) & 0xF)
#define OC_REGEXT(x) ((x) & 0xF)
/*
* Definitions for large numbers
*/
#include "asnumber.h"
typedef struct as_number *numberp;
numberp snarf();
numberp snarfreloc();
/*
* Definitions for special instructions
*/
#define CASEB 0x8F
#define CASEW 0xAF
#define CASEL 0xCF
/*
* Definitions for converting TYP's into numbers, booleans, etc.
* These are shared with the assembler.
*/
extern int ty_NORELOC[];
extern int ty_float[];
extern int ty_nbyte[];
extern int ty_nlg[];
extern char *ty_string[];
short ioptab[3][256]; /* two level index by opcode into insttab */
int mapescbyte(byte)
u_char byte;
{
switch(byte){
default: return(0);
case ESCD: return(1);
case ESCF: return(2);
}
}
mkioptab()
{
REG struct insttab *p;
int mapchar;
for(p = insttab; p->iname; p++){
mapchar = mapescbyte(p->eopcode);
if (ioptab[mapchar][p->popcode])
continue;
ioptab[mapchar][p->popcode] = p - insttab;
}
}
u_char snarfuchar();
/*
* Global variables for communicating with the minions and printins
*/
static int idsp;
static short argno; /* which argument one is working on */
static char insoutfmt[2]; /* how to format the relocated symbols */
#ifdef SDB
static struct proct *procp;
#endif SDB
static savevar(val)
long val;
{
var[argno] = val;
insoutvar[argno] = val;
}
printins(fmt, Idsp, ins)
char fmt;
#ifndef vax
u_char ins;
#else
u_char ins;
#endif
int Idsp;
{
u_char mode; /* mode */
u_char ins2;
char *indexreg; /* print of which register indexes */
char *indexed; /* we indexed */
char *operandout();
REG u_char *ap;
REG struct insttab *ip;
u_char optype;
int mapchar;
idsp = Idsp;
type = DSYM;
space = idsp;
#ifdef SDB
procp = adrtoprocp(dot);
if (procp->paddr == dot){
printf("0x%04.4x", ins);
incp = 2;
goto ret;
}
#endif SDB
#ifdef ADB
insoutfmt[0] = 0;
#endif ADB
#ifdef SDB
insoutfmt[0] = fmt;
#endif SDB
incp = 1;
if ((mapchar = mapescbyte(ins)) != 0){
ins2 = snarfuchar();
if (ioptab[mapchar][ins2] == 0){
/*
* Oops; not a defined instruction;
* back over this escape byte.
*/
incp -= 1;
mapchar = 0;
} else {
ins = ins2;
}
}
if (ioptab[mapchar][ins] == 0){
printf("<undefined operator byte>: %x", ins);
goto ret;
}
ip = &insttab[ioptab[mapchar][ins]];
printf("%s\t", ip->iname);
for (ap = ip->argtype, argno = 0; argno < ip->nargs; argno++, ap++) {
savevar(0x80000000); /* an illegal symbol */
optype = *ap;
if (argno != 0)
printc(',');
indexreg = 0;
indexed = 0;
do{
if (A_ACCEXT(optype) & ACCB){
switch(A_TYPEXT(optype)){
case TYPB:
mode = OC_CONS(OC_BDISP, R_PC);
break;
case TYPW:
mode = OC_CONS(OC_WDISP, R_PC);
break;
}
} else {
mode = snarfuchar();
}
indexreg = operandout(mode, optype);
if (indexed)
printf("[%s]", indexed);
indexed = indexreg;
} while(indexed);
}
if (mapchar == 0){
switch(ins){
case CASEB:
case CASEW:
case CASEL:
casebody(insoutvar[1], insoutvar[2]);
break;
default:
break;
}
}
ret: ;
#ifdef SDB
oincr = incp;
#endif SDB
#ifdef ADB
dotinc = incp;
#endif ADB
}
casebody(base, limit)
long base;
long limit;
{
int i;
POS baseincp;
POS advincp;
struct as_number *valuep;
#define OSIZE (sizeof(short))
argno = 0;
baseincp = incp;
for (i = 0; i <= limit; i++) {
printc(EOR);
#ifdef SDB
printf(" %d: ", i + base);
#endif SDB
#ifdef ADB
printf(" %R: ", i + base);
#endif ADB
valuep = snarfreloc(OSIZE, 0);
advincp = incp;
incp = baseincp;
dispaddress(valuep, OC_CONS(OC_WDISP, R_PC));
incp = advincp;
}
}
/*
* magic values to mung an offset to a register into
* something that psymoff can understand.. all magic
*/
/* 0 1 2 3 4 */
static long magic_masks[5] = {0, 0x80, 0x8000, 0, 0};
static long magic_compl[5] = {0, 0x100, 0x10000,0, 0};
/*
* Snarf up some bytes, and put in the magic relocation flags
*/
numberp snarfreloc(nbytes)
int nbytes;
{
numberp back;
back = snarf(nbytes);
if (back->num_ulong[0] & magic_masks[nbytes])
back->num_ulong[0] -= magic_compl[nbytes];
return(back);
}
/*
* The following code is NOT portable from the PDP 11 to the VAX
* because of the byte ordering problem.
*/
numberp snarf(nbytes)
int nbytes;
{
REG int i;
static struct as_number backnumber;
static struct as_number znumber; /* init'ed to 0 */
backnumber = znumber;
for (i = 0; i < nbytes; i++)
backnumber.num_uchar[i] = snarfuchar();
return(&backnumber);
}
/*
* Read one single character, and advance the dot
*/
u_char snarfuchar()
{
u_char back;
/*
* assert: bchkget and inkdot don't have side effects
*/
back = (u_char)bchkget(inkdot(incp), idsp);
incp += 1;
return(back);
}
/*
* normal operand; return non zero pointer to register
* name if this is an index instruction.
*/
char *operandout(mode, optype)
u_char mode;
u_char optype;
{
char *r;
int regnumber;
int nbytes;
regnumber = OC_REGEXT(mode);
r = insregname(regnumber);
switch (OC_AMEXT(mode)){
case OC_IMM0:
case OC_IMM1:
case OC_IMM2:
case OC_IMM3:
shortliteral(mode, optype);
return(0);
case OC_INDEX:
return(r); /* will be printed later */
case OC_REG:
printf("%s", r);
return(0);
case OC_DREG:
printf("(%s)", r);
return(0);
case OC_ADREG:
printf("-(%s)", r);
return(0);
case OC_DAIREG:
printc('*');
case OC_AIREG:
if (regnumber == R_PC){
pcimmediate(mode, optype);
} else {
printf("(%s)+", r);
}
return(0);
case OC_DBDISP:
printc('*');
case OC_BDISP:
nbytes = 1;
break;
case OC_DWDISP:
printc('*');
case OC_WDISP:
nbytes = 2;
break;
case OC_DLDISP:
printc('*');
case OC_LDISP:
nbytes = 4;
break;
}
dispaddress(snarfreloc(nbytes), mode);
return(0);
}
dispaddress(valuep, mode)
numberp valuep;
u_char mode;
{
int regnumber = OC_REGEXT(mode);
switch(OC_AMEXT(mode)){
case OC_BDISP:
case OC_DBDISP:
case OC_WDISP:
case OC_DWDISP:
case OC_LDISP:
case OC_DLDISP:
if (regnumber == R_PC){
/* PC offset addressing */
valuep->num_ulong[0] += inkdot(incp);
}
}
#ifdef ADB
psymoff(valuep->num_ulong[0], type, &insoutfmt[0]);
if (regnumber != R_PC){ /* } */
#endif ADB
#ifdef SDB
if(psymoff(valuep->num_ulong[0], regnumber, &insoutfmt[0])
&& (regnumber != R_PC)){
#endif SDB
printf("(%s)", insregname(regnumber));
}
savevar((long)valuep->num_ulong[0]);
}
/*
* get a register name
*/
char *insregname(regnumber)
int regnumber;
{
char *r;
r = regname[regnumber];
#ifdef SDB
if ( (insoutfmt[0] == 'i')
&& (regnumber >= 6)
&& (regnumber <= 11)
&& (adrtoregvar(regnumber, procp) != -1)) {
r = sl_name;
}
#endif SDB
return(r);
}
/*
* print out a short literal
*/
shortliteral(mode, optype)
u_char mode;
u_char optype;
{
savevar((long)mode);
switch(A_TYPEXT(optype)){
case TYPF:
case TYPD:
case TYPG:
case TYPH:
printf("$%s", fltimm[mode]);
break;
default:
#ifdef ADB
printf("$%r", mode);
#endif ADB
#ifdef SDB
printf("$%d", mode);
#endif SDB
break;
}
}
pcimmediate(mode, optype)
u_char mode;
u_char optype;
{
int nbytes;
printc('$');
if (mode == OC_DAIREG){ /* PC absolute, always 4 bytes*/
dispaddress(snarfreloc(4), mode);
return;
}
nbytes = ty_nbyte[A_TYPEXT(optype)];
if (! ty_NORELOC[A_TYPEXT(optype)]){
dispaddress(snarfreloc(nbytes), mode);
return;
}
bignumprint(nbytes, optype);
}
bignumprint(nbytes, optype)
int nbytes;
u_char optype;
{
numberp valuep;
int leading_zero = 1;
REG int bindex;
REG int nindex;
REG int ch;
valuep = snarf(nbytes);
switch(A_TYPEXT(optype)){
case TYPF:
printf("0f%f", valuep->num_num.numFf_float.Ff_value);
break;
case TYPD:
printf("0d%f", valuep->num_num.numFd_float.Fd_value);
break;
case TYPG:
printf("0g::"); goto qprint;
case TYPH:
printf("0h::"); goto qprint;
case TYPQ:
case TYPO:
qprint:
for (bindex = nbytes - 1; bindex >= 0; --bindex){
for (nindex = 4; nindex >= 0; nindex -= 4){
ch = (valuep->num_uchar[bindex] >> nindex);
ch &= 0x0F;
if ( ! (leading_zero &= (ch == 0) ) ){
if (ch <= 0x09)
printc(ch + '0');
else
printc(ch - 0x0A + 'a');
}
}
}
break;
}
}
#ifdef SDB
L_INT inkdot(incr)
int incr;
{
L_INT newdot;
newdot = dot + incr;
return(newdot);
}
printc(c)
char c;
{
printf("%c", c);
}
psymoff(v, regnumber, fmt)
L_INT v;
char *fmt;
{
struct proct *procp;
REG int diff;
if (fmt[0] == 'i') {
switch(regnumber){
case 12: /* parameter */
if ((diff = adrtoparam((ADDR) v, adrtoprocp(dot)))
!= -1) {
printf("%s", sl_name);
prdiff(diff);
return(0);
}
break;
case 13: /* local */
if ((diff = adrtolocal((ADDR) -v, adrtoprocp(dot))
) != -1) {
printf("%s", sl_name);
prdiff(diff);
return(0);
}
break;
default:
break;
}
if (v < firstdata) {
if ((procp = adrtoprocp((ADDR) v)) != badproc) {
prlnoff(procp, v);
return(0);
}
} else {
if ((diff = adrtoext((ADDR) v)) != -1) {
printf("%s", sl_name);
prdiff(diff);
return(0);
}
}
}
prhex(v);
return(1);
}
prdiff(diff)
{
if (diff) {
printf("+");
prhex(diff);
}
}
#endif SDB