|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 7491 (0x1d43) Types: TextFile Names: »tables.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦3f75c1919⟧ »EurOpenD3/utils/decomp.tar.Z« └─⟦510c4d5ee⟧ └─⟦this⟧ »decomp/tables.c«
/* * 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; } }