ppcdisas.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 528 行 · 第 1/2 页
C
528 行
case 0xd:
if( !CTRZero( mr ) ) return( NOT_TAKEN );
break;
case 0xa:
case 0xb:
case 0xe:
case 0xf:
if( dest < dd->addr.mach.offset ) {
return( MDC_TAKEN_BACK );
} else {
return( MDC_TAKEN_FORWARD );
}
}
if( dest < dd->addr.mach.offset ) {
return( MDC_CONDITIONAL | MDC_TAKEN_BACK );
} else {
return( MDC_CONDITIONAL | MDC_TAKEN_FORWARD );
}
}
#define TRANS_REG( mr, r ) (*(unsigned_64 *)((unsigned_8*)(mr) + RegTrans[r - DR_PPC_FIRST]))
static unsigned TrapTest( mad_disasm_data *dd, mad_registers const *mr )
{
unsigned_64 a;
unsigned_64 b;
unsigned bits;
switch( dd->ins.type ) {
case DI_PPC_twi:
case DI_PPC_tdi:
b.u._32[I64LO32] = dd->ins.op[2].value;
if( dd->ins.op[2].value < 0 ) {
b.u._32[I64HI32] = -1;
} else {
b.u._32[I64HI32] = 0;
}
break;
default:
b = TRANS_REG( mr, dd->ins.op[2].base );
break;
}
a = TRANS_REG( mr, dd->ins.op[1].base );
bits = 0;
switch( dd->ins.type ) {
case DI_PPC_td:
case DI_PPC_tdi:
if( a.u._32[I64HI32] == b.u._32[I64HI32] ) {
if( a.u._32[I64LO32] == b.u._32[I64LO32] ) {
bits |= 0x04;
} else {
if( a.u._32[I64LO32] < b.u._32[I64LO32] ) {
bits |= 0x02;
if( a.u.sign.v ) {
bits |= 0x08;
} else {
bits |= 0x10;
}
} else {
bits |= 0x01;
if( a.u.sign.v ) {
bits |= 0x10;
} else {
bits |= 0x08;
}
}
}
} else if( a.u._32[I64HI32] < b.u._32[I64HI32] ) {
bits |= 0x02;
if( a.u.sign.v ) {
bits |= 0x08;
} else {
bits |= 0x10;
}
} else {
bits |= 0x01;
if( a.u.sign.v ) {
bits |= 0x10;
} else {
bits |= 0x08;
}
}
break;
default:
if( a.u._32[I64LO32] < b.u._32[I64LO32] ) bits |= 0x02;
if( a.u._32[I64LO32] > b.u._32[I64LO32] ) bits |= 0x01;
if( (signed_32)a.u._32[I64LO32] < (signed_32)b.u._32[I64LO32] ) bits |= 0x10;
if( (signed_32)a.u._32[I64LO32] > (signed_32)b.u._32[I64LO32] ) bits |= 0x08;
if( bits == 0 ) bits |= 0x04;
break;
}
return( bits );
}
mad_disasm_control DisasmControl( mad_disasm_data *dd, mad_registers const *mr )
{
mad_disasm_control c;
addr_off v;
switch( dd->ins.type ) {
case DI_PPC_b:
if( dd->ins.flags & DIF_PPC_LK ) {
c = MDC_CALL;
} else {
c = MDC_JUMP;
}
v = dd->ins.op[0].value;
if( dd->ins.op[0].type == DO_RELATIVE ) {
v += dd->addr.mach.offset;
}
if( v < dd->addr.mach.offset ) {
return( c | MDC_TAKEN_BACK );
} else {
return( c | MDC_TAKEN_FORWARD );
}
case DI_PPC_bc:
if( dd->ins.flags & DIF_PPC_LK ) {
c = MDC_CALL;
} else {
c = MDC_JUMP;
}
v = dd->ins.op[2].value;
if( dd->ins.op[2].type == DO_RELATIVE ) {
v += dd->addr.mach.offset;
}
return( c | Cond( dd, mr, v ) );
case DI_PPC_bcctr:
if( dd->ins.flags & DIF_PPC_LK ) {
c = MDC_CALL;
} else {
c = MDC_JUMP;
}
return( c | Cond( dd, mr, mr->ppc.ctr.u._32[I64LO32] ) );
case DI_PPC_bclr:
if( dd->ins.flags & DIF_PPC_LK ) {
c = MDC_CALL;
} else {
c = MDC_RET;
}
return( c | Cond( dd, mr, mr->ppc.lr.u._32[I64LO32] ) );
case DI_PPC_rfi:
return( MDC_SYSRET | MDC_TAKEN );
case DI_PPC_sc:
return( MDC_SYSCALL | MDC_TAKEN );
case DI_PPC_td:
case DI_PPC_tdi:
case DI_PPC_tw:
case DI_PPC_twi:
c = MDC_SYSRET | MDC_CONDITIONAL;
if( TrapTest( dd, mr ) & dd->ins.op[0].value ) {
c |= MDC_TAKEN;
}
return( c );
default:
break;
}
return( MDC_OPER | MDC_TAKEN );
}
mad_disasm_control DIGENTRY MIDisasmControl( mad_disasm_data *dd, mad_registers const *mr )
{
return( DisasmControl( dd, mr ) );
}
mad_status DIGENTRY MIDisasmInsNext( mad_disasm_data *dd, mad_registers const *mr, address *next )
{
mad_disasm_control dc;
memset( next, 0, sizeof( *next ) );
next->mach.offset = mr->ppc.iar.u._32[I64LO32] + sizeof( unsigned_32 );
dc = DisasmControl( dd, mr );
if( (dc & MDC_TAKEN_MASK) == MDC_TAKEN_NOT ) {
return( MS_OK );
}
switch( dc & MDC_TYPE_MASK ) {
case MDC_JUMP:
case MDC_CALL:
case MDC_RET:
//NYI:
return( MS_UNSUPPORTED );
}
return( MS_OK );
}
walk_result DIGENTRY MIDisasmMemRefWalk( mad_disasm_data *dd, MI_MEMREF_WALKER *wk, mad_registers const *mr, void *d )
{
address a;
unsigned i;
walk_result wr;
mad_memref_kind mmk;
if( dd->ins.type >= DI_PPC_lbz && dd->ins.type <= DI_PPC_lwzx ) {
mmk = MMK_READ;
} else if( dd->ins.type >= DI_PPC_stb && dd->ins.type <= DI_PPC_stwx ) {
mmk = MMK_WRITE;
} else {
return( WR_CONTINUE );
}
a = dd->addr;
for( i = 0; i < dd->ins.num_ops; ++i ) {
if( dd->ins.op[i].type == DO_MEMORY_ABS ) {
a.mach.offset = dd->ins.op[i].value;
if( dd->ins.op[i].base != DR_PPC_r0 ) {
a.mach.offset += TRANS_REG( mr, dd->ins.op[i].base ).u._32[I64LO32];
}
mmk &= (MMK_READ|MMK_WRITE);
if( dd->ins.op[i].base == DR_PPC_r1 ) {
mmk |= MMK_VOLATILE;
}
wr = wk( a, RefTrans[dd->ins.op[i].ref_type-DRT_PPC_FIRST], mmk, d );
return( wr );
} else if( dd->ins.op[i].extra & PE_XFORM ) {
a.mach.offset = 0;
if( dd->ins.op[i].base != DR_PPC_r0 ) {
a.mach.offset += TRANS_REG( mr, dd->ins.op[i].base ).u._32[I64LO32];
}
a.mach.offset += TRANS_REG( mr, dd->ins.op[i+1].base ).u._32[I64LO32];
mmk &= (MMK_READ|MMK_WRITE);
if( dd->ins.op[i].base == DR_PPC_r1 || dd->ins.op[i+1].base == DR_PPC_r1 ) {
mmk |= MMK_VOLATILE;
}
wr = wk( a, RefTrans[dd->ins.op[i].ref_type-DRT_PPC_FIRST], mmk, d );
return( wr );
}
}
return( WR_CONTINUE );
}
const mad_toggle_strings *DIGENTRY MIDisasmToggleList( void )
{
static const mad_toggle_strings list[] = {
{ MSTR_MPSEUDOINS, MSTR_PSEUDOINS, MSTR_RAWINS },
{ MSTR_MUPPER, MSTR_UPPER, MSTR_LOWER },
{ MSTR_NIL, MSTR_NIL, MSTR_NIL }
};
return( list );
}
unsigned DIGENTRY MIDisasmToggle( unsigned on, unsigned off )
{
unsigned toggle;
toggle = (on & off);
MADState->disasm_state ^= toggle;
MADState->disasm_state |= on & ~toggle;
MADState->disasm_state &= ~off | toggle;
return( MADState->disasm_state );
}
mad_status DIGENTRY MIDisasmInspectAddr( char *from, unsigned len, unsigned radix, mad_registers const *mr, address *a )
{
char *buff = __alloca( len * 2 );
char *to;
mr = mr;
to = buff;
while( len != 0 ) {
if( *from == '(' ) *to++ = '+';
*to++ = *from++;
--len;
}
return( MCMemExpr( buff, to - buff, radix, a ) );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?