|
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 f
Length: 24082 (0x5e12) Types: TextFile Names: »format.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦3f75c1919⟧ »EurOpenD3/utils/decomp.tar.Z« └─⟦510c4d5ee⟧ └─⟦this⟧ »decomp/format.c«
/* * Module: format.c * * Author: J. Reuter * * This module takes the tree of C-specific control operators * and basic blocks produced by hll() and prints out almost-C * code. */ #include "defs.h" #include "nodes.h" #include "machine.h" #include "objfile.h" #include "vartab.h" #define LABEL(v) (node_array[v]->reach) static char bigstring[1000] = "string"; format() { treeprint( 0, 1 ); } static treeprint( v, tab ) register int v; register int tab; { register struct node *n; if ( !DEFINED(v) ) { tabover( tab ); printf( "; /* NONE */\n" ); return; } n = node_array[v]; if ( LABEL(v) ) { printf( "\n" ); tabover( tab - 1 ); printf( "G%04d:\n", v ); } switch ( n->node_type ) { case N_GOTO: tabover( tab ); printf( "goto G%04d;\n", n->arcs[0] ); break; case N_BREAK: tabover( tab ); printf( "break;\n" ); break; case N_CONTINUE: tabover( tab ); printf( "continue;\n" ); break; case N_CASELAB: tabover( tab - 1 ); printf( "case %d:\n", n->varpart[V_CASESLOT] ); break; case N_FLOW: case N_END: machprint( n->start_address, n->end_address, n->node_type, 0, tab ); break; case N_BRANCH: machprint( n->start_address, n->end_address, n->node_type, n->varpart[V_NEGATE], tab ); tabover( tab ); printf( "if ( %s ) {\n", bigstring ); treeprint( n->child[THEN_ARC], tab + 1 ); if ( DEFINED( n->child[ELSE_ARC] ) ) { tabover( tab ); printf( "} else {\n" ); treeprint( n->child[ELSE_ARC], tab + 1 ); } tabover( tab ); printf( "}\n\n" ); break; case N_IF: machprint( n->start_address, n->end_address, n->node_type, n->varpart[V_NEGATE], tab ); tabover( tab ); printf( "if ( %s ) {\n", bigstring ); treeprint( n->child[THEN_ARC], tab + 1 ); if ( DEFINED( n->child[ELSE_ARC] ) ) { tabover( tab ); printf( "} else {\n" ); treeprint( n->child[ELSE_ARC], tab + 1 ); } tabover( tab ); printf( "}\n\n" ); break; case N_ORIF: tabover( tab ); printf( "if ( " ); fmt_pred( n, NONE ); printf( " ) {\n" ); treeprint( n->child[THEN_ARC], tab + 1 ); if ( DEFINED( n->child[ELSE_ARC] ) ) { tabover( tab ); printf( "} else {\n" ); treeprint( n->child[ELSE_ARC], tab + 1 ); } tabover( tab ); printf( "}\n\n" ); break; case N_SWITCH: machprint( n->start_address, n->end_address, n->node_type, 0, tab ); tabover( tab ); printf( "switch ( %s ) {\n", bigstring ); treeprint( n->child[0], tab + 1 ); tabover( tab ); printf( "}\n\n" ); break; case N_CASE: break; case N_ITER: treeprint( n->child[0], tab ); break; case N_LOOP: tabover( tab ); printf( "while (1) {\n" ); treeprint( n->child[0], tab + 1 ); tabover( tab ); printf( "}\n\n" ); break; case N_WHILE: tabover( tab ); printf( "while ( " ); fmt_pred( node_array[ n->varpart[V_LOOP_PRED] ], NONE ); printf( " ) {\n" ); treeprint( n->child[0], tab + 1 ); tabover( tab ); printf( "}\n" ); break; case N_UNTIL: tabover( tab ); printf( "do {\n" ); treeprint( n->child[0], tab + 1 ); tabover( tab ); printf( "} while ( " ); fmt_pred( node_array[ n->varpart[V_LOOP_PRED] ], NONE ); printf( " );\n\n" ); break; } v = n->right_sibling; if ( DEFINED(v) ) treeprint( v, tab ); } /* * negate() propogates negated if predicates to the subpredicates * using DeMorgan's rule. That is, an N_ORIF node with a negated * predicate is converted to an ANDIF node and each of the two * subpredicates is inverted. Note that ANDIF is indicated by * leaving V_NEGATE set. * * This function recursively walks down the predicate tree until * no more N_ORIF nodes are found. */ static negate( n ) register struct node *n; { register struct node *p1, *p2; if ( n->node_type != N_ORIF ) return; p1 = node_array[ n->varpart[V_PRED1] ]; p2 = node_array[ n->varpart[V_PRED2] ]; if ( n->varpart[V_NEGATE] ) { p1->varpart[V_NEGATE] = !p1->varpart[V_NEGATE]; p2->varpart[V_NEGATE] = !p2->varpart[V_NEGATE]; } negate( p1 ); negate( p2 ); } /* * fmt_pred() prints a C formatted predicate for N_IF, N_ORIF, N_WHILE, * and N_UNTIL statements. */ static fmt_pred( n, fath_neg ) register struct node *n; register int fath_neg; { negate( n ); /* must use parens for precedence when mixing &&, || */ if ( fath_neg != NONE && n->varpart[V_NEGATE] != fath_neg && n->node_type == N_ORIF ) printf( "( " ); if ( n->node_type == N_ORIF ) { fmt_pred( node_array[ n->varpart[V_PRED1] ], n->varpart[V_NEGATE] ); if ( n->varpart[V_NEGATE] ) printf( " && " ); else printf( " || " ); fmt_pred( node_array[ n->varpart[V_PRED2] ], n->varpart[V_NEGATE] ); } else { machprint( n->start_address, n->end_address, n->node_type, n->varpart[V_NEGATE], 0 ); printf( "%s", bigstring ); } if ( fath_neg != NONE && n->varpart[V_NEGATE] != fath_neg && n->node_type == N_ORIF ) printf( " )" ); } static char tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; /* move over 'n' "tab stops" (one stop = 4 spaces, ASCII tab = 8 spaces) */ static tabover( n ) register int n; { register char *s; s = tabs + 15 - ( n / 2 ); printf( "%s", s ); if ( n & 1 ) printf( " " ); } 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]; static machprint( addr, end_addr, nodetype, negate, tab ) address addr, end_addr; int nodetype; int negate; int tab; { struct opcode *op; VaxOpcode ins; unsigned char mode; int argtype, amode, argno, argval; int rn, type; struct nlist *s; char *str; struct relocation_info *r; char tempstring1[100]; char tempstring2[100]; /* initialize pass */ relo_first(); r = relo_next(); /* the main loop */ while ( addr < end_addr ) { argval = 0; 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: /* machine code during N_FLOW or N_END is an error */ if ( nodetype == N_FLOW || nodetype == N_END ) { tabover( tab ); printf( "ERR! %s\t", op->cop1 ); for ( argno = 0; argno < op->numargs; argno++ ) { if ( argno != 0 ) printf( "," ); printf( "%s", operand[argno].opstring ); doindex(argno); } printf( "\n" ); } else if ( nodetype == N_SWITCH ) { if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) { /* skip case table */ for ( argno = 0; argno <= argval; argno++ ) addr += 2; sprintf( bigstring, "%s", operand[0].opstring ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } } } break; case COMP: if ( nodetype != N_IF ) fprintf( stderr, "cmp instruction not in N_IF block\n" ); if ( ins == O_CMPZV ) { if ( operand[0].op_argval != 0 ) { sprintf( bigstring, "( (%s", operand[2].opstring ); if ( operand[2].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[2].op_index_rn, operand[2].op_index_type ) ); strcat( bigstring, tempstring1 ); } sprintf( tempstring1, " >> %d)", operand[0].op_argval ); strcat( bigstring, tempstring1 ); } else { sprintf( bigstring, "( %s", operand[2].opstring ); if ( operand[2].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[2].op_index_rn, operand[2].op_index_type ) ); strcat( bigstring, tempstring1 ); } } if ( operand[1].op_argval != 32 ) { sprintf( tempstring1, " & 0x%x )", 0x7fffffff >> ( 31 - operand[1].op_argval ) ); strcat( bigstring, tempstring1 ); } else strcat( bigstring, " )" ); sprintf( tempstring1, "%s", operand[3].opstring ); if ( operand[3].op_indexed ) { sprintf( tempstring2, "[%s]", reg_sym( operand[3].op_index_rn, operand[3].op_index_type ) ); strcat( tempstring1, tempstring2 ); } } else { sprintf( bigstring, "%s", operand[0].opstring ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } sprintf( tempstring1, "%s", operand[1].opstring ); if ( operand[1].op_indexed ) { sprintf( tempstring2, "[%s]", reg_sym( operand[1].op_index_rn, operand[1].op_index_type ) ); strcat( tempstring1, tempstring2 ); } } break; case TEST: if ( nodetype != N_IF ) fprintf( stderr, "tst instruction not in N_IF block\n" ); sprintf( bigstring, "%s", operand[0].opstring ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } sprintf( tempstring1, "0" ); break; case CBRANCH: if ( nodetype == N_BRANCH ) { strcpy( bigstring, "@prev@" ); strcpy( tempstring1, "0" ); } if ( nodetype == N_IF || nodetype == N_BRANCH ) { if (ins == O_BNEQ && !negate || ins == O_BEQL && negate ) strcat( bigstring, " != " ); else if (ins == O_BEQL && !negate || ins == O_BNEQ && negate) strcat( bigstring, " == " ); else if (ins == O_BGTR && !negate || ins == O_BLEQ && negate) strcat( bigstring, " > " ); else if (ins == O_BLEQ && !negate || ins == O_BGTR && negate) strcat( bigstring, " <= " ); else if (ins == O_BGEQ && !negate || ins == O_BLSS && negate) strcat( bigstring, " >= " ); else if (ins == O_BLSS && !negate || ins == O_BGEQ && negate) strcat( bigstring, " < " ); else if (ins == O_BGTRU && !negate || ins == O_BLEQU && negate) strcat( bigstring, " >u " ); else if (ins == O_BLEQU && !negate || ins == O_BGTRU && negate) strcat( bigstring, " <=u " ); strcat( bigstring, tempstring1 ); } else fprintf( stderr, "bcnd instruction not in N_IF or N_BRANCH\n"); break; case BBRANCH: if ( nodetype != N_IF ) fprintf( stderr, "bbit instruction not in N_IF\n"); if ( ins == O_BBCC || ins == O_BBSS || ins == O_BBCS || ins == O_BBSC || ins == O_BBCCI || ins == O_BBSSI ) { sprintf( bigstring, "%s ", negate ? "!" : "" ); strcat( bigstring, op->cop1 ); sprintf( tempstring1, " %s", operand[0].opstring ); strcat( bigstring, tempstring1 ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } sprintf( tempstring1, ",%s", operand[1].opstring ); strcat( bigstring, tempstring1 ); if ( operand[1].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[1].op_index_rn, operand[1].op_index_type ) ); strcat( bigstring, tempstring1 ); } } else if ( ins == O_SOBGEQ || ins == O_SOBGTR ) { sprintf( bigstring, "--%s", operand[0].opstring ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } if ( ins == O_SOBGEQ && !negate ) strcat( bigstring, " >= 0" ); else if ( ins == O_SOBGEQ && negate ) strcat( bigstring, " < 0" ); else if ( ins == O_SOBGTR && !negate ) strcat( bigstring, " > 0" ); else if ( ins == O_SOBGTR && negate ) strcat( bigstring, " <= 0" ); } else if ( ins == O_AOBLSS || ins == O_AOBLEQ ) { sprintf( bigstring, "++%s", operand[1].opstring ); if ( operand[1].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[1].op_index_rn, operand[1].op_index_type ) ); strcat( bigstring, tempstring1 ); } if ( ins == O_AOBLSS && !negate ) strcat( bigstring, " < " ); else if ( ins == O_AOBLSS && negate ) strcat( bigstring, " >= " ); else if ( ins == O_AOBLEQ && !negate ) strcat( bigstring, " <= " ); else if ( ins == O_AOBLEQ && negate ) strcat( bigstring, " > " ); sprintf( tempstring1, "%s", operand[0].opstring ); strcat( bigstring, tempstring1 ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } } else if ( ins == O_ACBL || ins == O_ACBW || ins == O_ACBB || ins == O_ACBF || ins == O_ACBD ) { sprintf( bigstring, "( %s", operand[2].opstring ); if ( operand[2].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[2].op_index_rn, operand[2].op_index_type ) ); strcat( bigstring, tempstring1 ); } sprintf( tempstring1, " += %s", operand[1].opstring ); if ( operand[1].op_indexed ) { sprintf( tempstring2, "[%s]", reg_sym( operand[1].op_index_rn, operand[1].op_index_type ) ); strcat( tempstring1, tempstring2 ); } if ( operand[2].op_argval >= 0 ) if ( !negate ) { strcat( tempstring1, " ) <= " ); } else { strcat( tempstring1, " ) > " ); } else if ( !negate ) { strcat( tempstring1, " ) >= " ); } else { strcat( tempstring1, " ) < " ); } strcat( bigstring, tempstring1 ); sprintf( tempstring1, "%s", operand[0].opstring ); if ( operand[0].op_indexed ) { sprintf( tempstring2, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( tempstring1, tempstring2 ); } strcat( bigstring, tempstring1 ); } else { if ( ins == O_BLBS || ins == O_BLBC ) { sprintf( bigstring, "( %s", operand[0].opstring ); if ( operand[0].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[0].op_index_rn, operand[0].op_index_type ) ); strcat( bigstring, tempstring1 ); } } else if ( ins == O_BBS || ins == O_BBC ) { sprintf( bigstring, "( %s", operand[1].opstring ); if ( operand[1].op_indexed ) { sprintf( tempstring1, "[%s]", reg_sym( operand[1].op_index_rn, operand[1].op_index_type ) ); strcat( bigstring, tempstring1 ); } } if ( ins == O_BLBS && !negate || ins == O_BLBC && negate ) strcat( bigstring, " & 1 ) != 0" ); else if ( ins == O_BLBC && !negate || ins == O_BLBS && negate ) strcat( bigstring, " & 1 ) == 0" ); else if (ins == O_BBS && !negate || ins == O_BBC && negate) { sprintf( tempstring1, " & 0x%x ) != 0", 1 << operand[0].op_argval ); strcat( bigstring, tempstring1 ); } else if (ins == O_BBC && !negate || ins == O_BBS && negate) { sprintf( tempstring1, " & 0x%x ) != 0", 1 << operand[0].op_argval ); strcat( bigstring, tempstring1 ); } } break; case A1OPA0: tabover( tab ); printf( "%s", operand[1].opstring ); doindex(1); printf( "%s", op->cop1 ); printf( "%s", operand[0].opstring ); doindex(0); printf( ";\n" ); break; case A2EQ1OP0: tabover( tab ); printf( "%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: tabover( tab ); printf( "%s", operand[0].opstring ); doindex(0); printf( "%s;\n", op->cop1 ); break; case OPONLY: tabover( tab ); printf( "%s;\n", op->cop1 ); break; case CALLS: tabover( tab ); printf( "@val@ = %s", operand[1].opstring ); doindex(1); printf( "( @%s args@ );\n", operand[0].opstring ); break; case PUSH: tabover( tab ); printf( "@arg@ = %s", operand[0].opstring ); doindex(0); printf( ";\n" ); break; case PUSHA: tabover( tab ); printf( "@arg@ = &%s", operand[0].opstring ); doindex(0); printf( ";\n" ); break; case EXTZV: tabover( tab ); printf( "%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" ); break; } } } /* * 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( "ERR: 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; } }