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 t

⟦2ae191a6c⟧ TextFile

    Length: 7491 (0x1d43)
    Types: TextFile
    Names: »tables.c«

Derivation

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

TextFile

/*
 * Module: tables.c
 *
 * Author: J. Reuter
 *
 * The functions in this module are used to make the first pass over
 * a functions code and add information to the symbol and label tables.
 */

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

/*
 * The tables() function makes a pass through a function's code.
 * While processing the code, it builds several tables.  These
 * include register and automatic (stack) local variable usage,
 * branch targets (for building basic blocks), and global symbol
 * usage (to determine type).
 */

tables( addr, end_addr )
address addr, end_addr;
{
    unsigned char ins;
    address insaddr;
    unsigned char mode;
    register int argtype, amode, argno, argval;
    register int rn, type, fl;
    short offset;
    struct nlist *s;
    struct relocation_info *r;

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

    /* loop across all the instructions in this function */
    while ( addr < end_addr ) {

	argval = 0;
	ins = get_byte( addr );
	addr += 1;

	/* process all the operands for the instruction */
	for (argno = 0; argno < opcode[ins].numargs; argno++) {

	    argtype = opcode[ins].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 );

	    fl = 0;

	    if ( acctype( argtype ) == ACCW || acctype( argtype ) == ACCM )
		fl |= C_WRITTEN;
	    if ( type & T_UNSIGNED )
		fl |= T_UNSIGNED;

	    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 ) {
			fprintf( stderr, "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:
			    fprintf( stderr, "ERR: strange relo autoinc %d\n",
				    type );
			    break;
			}
		    }

		} else {
		    fprintf( stderr, "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 == AUTOINC ) {
			    reg_add( rn, T_LONG, 0 );
			    ext_add( r->r_symbolnum, type, argval, fl );
			} else if ( amode == LONGDISPDEF ) {
			    reg_add( rn, T_LONG, 0 );
			    ext_add( r->r_symbolnum, type | T_POINTER,
				    argval, fl );
			} else {
			    fprintf( stderr, "ERR: ext relo mode %d\n", amode );
			}
		    } else {
			fprintf( stderr, "ERR: ext relo type %d\n", s->n_type );
		    }

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

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

			if ( amode == LONGDISPDEF )
			    type |= T_POINTER;

			if ( rn == PC ) {
			    switch ( r->r_symbolnum ) {
			    case 4:
				/* static function */
				int_add( argval, type, C_STATIC, C_TEXT );
				break;
			    case 5:
				/* global function */
				int_add( argval, type, 0, C_TEXT );
				break;
			    case 6:
				/* static data, const, string */
				int_add( argval, type, C_STATIC+fl, C_DATA );
				break;
			    case 7:
				/* global data, const, string */
				int_add( argval, type, fl, C_DATA );
				break;
			    case 8:
				/* static bss */
				int_add( argval, type, C_STATIC+fl, C_BSS );
				break;
			    default:
				fprintf( stderr, "ERR: bad relo symbolnum %d\n",
					r->r_symbolnum );
				break;
			    }
			} else {
			    /* other registers? */
			}

		    } else if ( amode == AUTOINC ) {

			switch ( r->r_symbolnum ) {
			case 6:
			    /* static data */
			    int_add( argval, type, C_STATIC+fl, C_DATA );
			    break;
			case 8:
			    /* static bss */
			    int_add( argval, type, C_STATIC+fl, C_BSS );
			    break;
			default:
			    fprintf( stderr, "ERR: auto relo symnum %d\n",
				    r->r_symbolnum );
			    break;
			}

		    } else {
			fprintf( stderr, "ERR: int relo mode %d\n", amode );
		    }
		}

	    } else {		/* no relo info */

		switch (amode) {
		case LITSHORT:
		case LITUPTO31:
		case LITUPTO47:
		case LITUPTO63:
		    argval = mode;
		    break;

		case INDEX:
		    reg_add( rn, T_LONG, 0 );
		    argno--;
		    break;

		case REG:
		    reg_add( rn, type, fl );
		    break;

		case REGDEF:
		    reg_add( rn, type | T_POINTER, 0 );
		    break;

		case AUTODEC:
		    reg_add( rn, type | T_POINTER, 0 );
		    break;

		case AUTOINC:
		    if ( rn != PC ) {
			reg_add( rn, type | T_POINTER, 0 );
		    } 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;
			}
		    }
		    break;

		case AUTOINCDEF:
		    if ( rn == PC ) {
			/* immediate deferred */
			argval = getdisp(addr, 4, rn, amode);
			addr += 4;
		    } else {
			reg_add( rn, type | T_POINTER, 0 );
		    }
		    break;

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

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

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

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

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

		case LONGDISPDEF:
		    argval = getdisp(addr, 4, rn, amode);
		    regdisp( rn, argval, type, fl );
		    addr += 4;
		    break;
		}
		if ( is_branch_disp( argtype ) )
		    llb_add( argval, FALSE );
	    }
	}
	if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
	    insaddr = addr;
	    for (argno = 0; argno <= argval; argno++) {
		offset = get_word( addr );
		addr += 2;
		llb_add( insaddr+offset, TRUE );
	    }
	}
    }
}


/*
 * Get 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, fl )
int rn, offset, type, fl;
{
    switch ( rn ) {

    /* arguments */
    case AP:
	if ( offset < 0 )
	    fprintf( stderr, "bad argument offset %d\n", offset );
	else
	    arg_add( offset, type, fl );
	break;

    /* locals */
    case FP:
	if ( offset > 0 )
	    fprintf( stderr, "bad local offset %d\n", offset );
	else
	    loc_add( -offset, type, fl );
	break;

    case PC:
	/* do nothing */
	break;

    /* everything else */
    default:
	reg_add( rn, type | T_POINTER, 0 );
	break;
    }
}