|
|
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;
}
}