DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T d

⟦83e2c3ee5⟧ TextFile

    Length: 11180 (0x2bac)
    Types: TextFile
    Names: »disasm.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦3f75c1919⟧ »EurOpenD3/utils/decomp.tar.Z« 
        └─⟦510c4d5ee⟧ 
            └─⟦this⟧ »decomp/disasm.c« 

TextFile

/*
 * Module: disasm.c
 *
 * Author: J. Reuter
 *
 * This module "disassembles" a function into pseudo-C code
 * for data manipulation and pseudo-assembler code for all
 * conditional test and branch instructions.  It makes no
 * attempt to structure the code.
 *
 * This disassembler is used as a fallback when the fancy
 * structuring code breaks.  This does not happen very often
 * with PCC output.  Occasionally the Unix peephole optimizer will
 * combine the last bits of code for several functions, causing
 * the structuring code to break.
 */

#include "defs.h"
#include "machine.h"
#include "labeltab.h"
#include "objfile.h"
#include "vartab.h"

extern char *typesuf[];

static struct operand {
    int op_argval;
    int op_indexed;
    int op_index_rn;
    int op_index_type;
    char opstring[40];
} operand[6];

disasm( addr, end_addr )
address addr, end_addr;
{
    struct opcode *op;
    VaxOpcode ins;
    address insaddr;
    unsigned char mode;
    int argtype, amode, argno, argval;
    int rn, type;
    short offset;
    struct nlist *s;
    char *str;
    struct llb *l;
    struct relocation_info *r;

    /* initialize pass */
    l = llb_first();
    relo_first();
    r = relo_next();

    /* the main loop */
    while ( addr < end_addr ) {
	argval = 0;

	while ( l->l_address < addr )
	    l = llb_next();

	if ( l != NULL && addr == l->l_address ) {
	    if ( l->caselab )
		printf( "C%04d:", addr );
	    else
		printf( "G%04d:", addr );
	}

	ins = get_byte( addr );
	addr += 1;
	op = &opcode[ins];

	for (argno = 0; argno < op->numargs; argno++)
	    operand[argno].op_indexed = FALSE;

	for (argno = 0; argno < op->numargs; argno++) {

	    str = operand[argno].opstring;

	    argtype = op->argtype[argno];
	    if (is_branch_disp(argtype)) {
		mode = 0xAF + ( (typelen(argtype) & ~T_UNSIGNED) << 4);
	    } else {
		mode = get_byte( addr );
		addr += 1;
	    }

	    while ( r != NULL && addr > r->r_address )
		r = relo_next();

	    rn = regnm( mode );
	    type = typelen( argtype );
	    amode = addrmode(mode);

	    if ( r != NULL && addr == r->r_address ) {

		if ( amode == LONGDISP || amode == LONGDISPDEF ) {

		    argval = getdisp(addr, 4, rn, amode);
		    addr += 4;

		} else if ( amode == AUTOINC ) {

		    if ( rn != PC ) {
			printf( "ERR: strange relo autoinc reg\n" );
		    } else {
			/* immediate values */
			switch ( type & ~T_UNSIGNED ) {
			case TYPL:
			    argval = getdisp(addr, 4, rn, amode);
			    addr += 4;
			    break;

			default:
			    printf( "ERR: strange relo autoinc %d\n", type );
			    break;
			}
		    }

		} else {
		    printf( "ERR: bad relo mode %d\n", amode );
		}

		if ( r->r_extern ) {

		    s = &symtab[r->r_symbolnum];

		    if ( s->n_type == (N_EXT+N_UNDF) ) {

			if ( amode == LONGDISP || amode == LONGDISPDEF ) {
			    char *def;

			    if ( amode == LONGDISPDEF ) {
				def = "*";
				type |= T_POINTER;
			    } else {
				def = "";
			    }

			    if ( rn == PC )
				sprintf( str, "%s%s", def,
					ext_sym( r->r_symbolnum, type, argval ) );
			    else
				sprintf( str, "%s%s(r%02d)", def,
					ext_sym( r->r_symbolnum, type, argval ),
					rn );

			} else if ( amode == AUTOINC ) {
			    sprintf( str, "%s", ext_sym( r->r_symbolnum, type,
							argval ) );
			} else {
			    printf( "ERR: ext relo mode %d\n", amode );
			}
		    } else {
			printf( "ERR: ext relo type %d\n", s->n_type );
		    }

		} else {		/* not r->r_extern */

		    if ( amode == LONGDISP || amode == LONGDISPDEF ) {
			char *def;

			if ( amode == LONGDISPDEF ) {
			    def = "*";
			    type |= T_POINTER;
			} else {
			    def = "";
			}

			if ( rn == PC ) {
			    switch ( r->r_symbolnum ) {
			    case 4:
				/* static function */
				sprintf( str, "%s%s", def,
					int_sym( argval, type, C_TEXT ) );
				break;
			    case 5:
				/* global function */
				sprintf( str, "%s%s", def,
					int_sym( argval, type, C_TEXT ) );
				break;
			    case 6:
				/* static data, const, string */
				sprintf( str, "%s%s", def,
					int_sym( argval, type, C_DATA ) );
				break;
			    case 7:
				/* global data, const, string */
				sprintf( str, "%s%s", def,
					int_sym( argval, type, C_DATA ) );
				break;
			    case 8:
				/* bss */
				sprintf( str, "%s%s", def,
					int_sym( argval, type, C_BSS ) );
				break;
			    default:
				printf( "ERR: bad relo symbolnum %d\n",
				       r->r_symbolnum );
				break;
			    }
			} else {
			    /* other registers? */
			    sprintf( str, "%s%d(r%02d)", def, argval, rn );
			    printf( "\targ %d int longdisp sym#%d pcrel %d len %d reg %d\n",
				   argno, r->r_symbolnum, r->r_pcrel, r->r_length, rn );
			}

		    } else if ( amode == AUTOINC ) {

			switch ( r->r_symbolnum ) {
			case 6:
			    /* static data */
			    sprintf( str, "%s", int_sym( argval, type, C_DATA ) );
			    break;
			case 8:
			    /* static bss */
			    sprintf( str, "%s", int_sym( argval, type, C_BSS ) );
			    break;
			default:
			    printf( "ERR: auto relo symnum %d\n", r->r_symbolnum );
			    break;
			}
		    } else {
			printf( "ERR: int relo mode %d\n", amode );
		    }
		}

	    } else {		/* no relo info */

		switch (amode) {
		case LITSHORT:
		case LITUPTO31:
		case LITUPTO47:
		case LITUPTO63:
		    if ( type == TYPF || type == TYPD )
			sprintf( str, "%s", fltimm[mode] );
		    else
			sprintf( str, "%d", mode );
		    argval = mode;
		    break;

		case INDEX:
		    operand[argno].op_indexed = TRUE;
		    operand[argno].op_index_rn = rn;
		    operand[argno].op_index_type = T_LONG;
		    argno--;
		    break;

		case REG:
		    sprintf( str, "%s", reg_sym( rn, type ) );
		    break;

		case REGDEF:
		    sprintf( str, "*%s", reg_sym( rn, type | T_POINTER ) );
		    break;

		case AUTODEC:
		    if ( rn == SP )
			sprintf( str, "@arg@" );
		    else
			sprintf( str, "*(--%s)",
				reg_sym( rn, type | T_POINTER) );
		    break;

		case AUTOINC:
		    if ( rn != PC ) {
			sprintf( str, "*%s++",
				reg_sym( rn, type | T_POINTER ) );
		    } else {
			/* immediate values */
			switch ( type & ~T_UNSIGNED ) {
			case TYPB:
			    argval = getdisp(addr, 1, rn, amode);
			    addr += 1;
			    break;

			case TYPW:
			    argval = getdisp(addr, 2, rn, amode);
			    addr += 2;
			    break;

			case TYPL:
			    argval = getdisp(addr, 4, rn, amode);
			    addr += 4;
			    break;

			default:
			    printf( "ERR: strange-autoinc %d\n", type );
			    break;
			}
			sprintf( str, "%d", argval );
		    }
		    break;

		case AUTOINCDEF:
		    if ( rn == PC ) {
			/* immediate deferred */
			argval = getdisp(addr, 4, rn, amode);
			addr += 4;
			sprintf( str, "*%d", argval );
		    } else {
			sprintf( str, "**(%s++)",
				reg_sym( rn, type | T_POINTER ) );
		    }
		    break;

		case BYTEDISP:
		    argval = getdisp(addr, 1, rn, amode);
		    regdisp( rn, argval, type, FALSE, str );
		    addr += 1;
		    break;

		case BYTEDISPDEF:
		    ;
		    argval = getdisp(addr, 1, rn, amode);
		    regdisp( rn, argval, type, TRUE, str );
		    addr += 1;
		    break;

		case WORDDISP:
		    argval = getdisp(addr, 2, rn, amode);
		    regdisp( rn, argval, type, FALSE, str );
		    addr += 2;
		    break;

		case WORDDISPDEF:
		    ;
		    argval = getdisp(addr, 2, rn, amode);
		    regdisp( rn, argval, type, TRUE, str );
		    addr += 2;
		    break;

		case LONGDISP:
		    argval = getdisp(addr, 4, rn, amode);
		    regdisp( rn, argval, type, FALSE, str );
		    addr += 4;
		    break;

		case LONGDISPDEF:
		    ;
		    argval = getdisp(addr, 4, rn, amode);
		    regdisp( rn, argval, type, TRUE, str );
		    addr += 4;
		    break;
		}
	    }
	    operand[argno].op_argval = argval;
	}

	/* print the decompiled instruction */

#define doindex( i ) if ( operand[i].op_indexed ) printf( "[%s]", \
		reg_sym( operand[i].op_index_rn, operand[i].op_index_type ) )

	switch( op->coptype ) {

	case MACRO:   /* print macro code */
	case COMP:
	case TEST:
	case BBRANCH:
	case CBRANCH:
	    printf( "\t%s\t", op->cop1 );
	    for ( argno = 0; argno < op->numargs; argno++ ) {
		if ( argno != 0 )
		    printf( "," );
		printf( "%s", operand[argno].opstring );
		doindex(argno);
	    }

	    if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
		insaddr = addr;
		for (argno = 0; argno <= argval; argno++) {
		    offset = get_word( addr );
		    addr += 2;
		    printf( "\n\t\tC%04d", offset+insaddr );
		}
	    }
	    printf( "\n" );
	    break;

	case A1OPA0:
	    printf( "\t%s", operand[1].opstring );
	    doindex(1);
	    printf( "%s", op->cop1 );
	    printf( "%s", operand[0].opstring );
	    doindex(0);
	    printf( ";\n" );
	    break;

	case A2EQ1OP0:
	    printf( "\t%s", operand[2].opstring );
	    doindex(2);
	    printf( " = %s", operand[1].opstring );
	    doindex(1);
	    printf( "%s", op->cop1 );
	    printf( "%s", operand[0].opstring );
	    doindex(0);
	    printf( ";\n" );
	    break;

	case A0OP:
	    printf( "\t%s", operand[0].opstring );
	    doindex(0);
	    printf( "%s;\n", op->cop1 );
	    break;

	case OPONLY:
	    printf( "\t%s;\n", op->cop1 );
	    break;

	case CALLS:
	    printf( "\t@val@ = %s", operand[1].opstring );
	    doindex(1);
	    printf( "( @%s args@ );\n", operand[0].opstring );
	    break;

	case PUSH:
	    printf( "\t@arg@ = %s", operand[0].opstring );
	    doindex(0);
	    printf( ";\n" );
	    break;

	case PUSHA:
	    printf( "\t@arg@ = &%s", operand[0].opstring );
	    doindex(0);
	    printf( ";\n" );
	    break;

	case EXTZV:
	    printf( "\t%s", operand[3].opstring );
	    doindex(3);
	    printf( " = " );
	    if ( operand[0].op_argval != 0 ) {
		printf( "( %s", operand[2].opstring );
		doindex(2);
		printf( " >> %d )", operand[0].op_argval );
	    } else {
		printf( "%s", operand[2].opstring );
		doindex(2);
	    }
	    if ( operand[1].op_argval != 32 )
		printf( " & 0x%x;\n",
		       0x7fffffff >> ( 31 - operand[1].op_argval ) );
	    else
		printf( ";\n" );
	}
    }
}


/*
 * Print the displacement of an instruction that uses displacement
 * addressing.
 */
static int
getdisp(addr, nbytes, rn, mode)
address addr;
int nbytes;
int rn;
int mode;
{
    int argval;

    switch (nbytes) {
    case 1:
	argval = get_byte( addr );
	break;

    case 2:
	argval = get_word( addr );
	break;

    case 4:
	argval = get_long( addr );
	break;
    }
    if (rn == PC && mode >= BYTEDISP) {
	argval += addr + nbytes;
    }
    return argval;
}

static
regdisp( rn, offset, type, defr, str )
int rn, offset, type, defr;
char *str;
{
    char *ds;

    if ( defr )
	ds = "*";
    else
	ds = "";

    switch ( rn ) {

    /* arguments */
    case AP:
	if ( offset < 0 )
	    printf( "ERR: bad argument offset %d\n", offset );
	else
	    sprintf( str, "%s%s", ds, arg_sym( offset, type ) );
	break;

    /* locals */
    case FP:
	if ( offset > 0 )
	    printf( "bad local offset %d\n", offset );
	else
	    sprintf( str, "%s%s", ds, loc_sym( -offset, type ) );
	break;

    case PC:
	if ( defr )
	    printf( "ERR: PC deferred\n" );
	sprintf( str, "G%04d", offset );
	break;

    /* everything else */
    default:
	sprintf( str, "%s%s->O%03d%s", ds, reg_sym( rn, type | T_POINTER ),
		offset, typesuf[ type ] );
	break;
    }
}