disppc.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,470 行 · 第 1/3 页
C
1,470 行
break;
default:
break;
}
return( DHR_DONE );
}
dis_handler_return PPCNull( dis_handle *h, void *d, dis_dec_ins *ins )
{
ins->num_ops = 0;
return( DHR_DONE );
}
static unsigned PPCInsHook( dis_handle *h, void *d, dis_dec_ins *ins,
dis_format_flags flags, char *name )
{
const char *new;
const char *more;
if( !(flags & DFF_PSEUDO) ) return( 0 );
new = NULL;
more = NULL;
switch( ins->type ) {
// Comparison statements.
case DI_PPC_cmpi:
if( ins->op[1].value == 0 ) {
ins->num_ops = 3;
ins->op[1] = ins->op[2];
ins->op[2] = ins->op[3];
new = "cmpwi";
}
break;
case DI_PPC_cmp:
if( ins->op[1].value == 0 ) {
ins->num_ops = 3;
ins->op[1] = ins->op[2];
ins->op[2] = ins->op[3];
new = "cmpw";
}
break;
case DI_PPC_cmpli:
if( ins->op[1].value == 0 ) {
ins->num_ops = 3;
ins->op[1] = ins->op[2];
ins->op[2] = ins->op[3];
new = "cmplwi";
}
break;
case DI_PPC_cmpl:
if( ins->op[1].value == 0 ) {
ins->num_ops = 3;
ins->op[1] = ins->op[2];
ins->op[2] = ins->op[3];
new = "cmplw";
}
break;
// Trap statements.
//NYI: handle trap double extended stuff
case DI_PPC_twi:
ins->num_ops = 2;
switch( ins->op[0].value ) {
case 1: new = "twlgti"; break;
case 2: new = "twllti"; break;
case 4: new = "tweqi"; break;
case 5: new = "twlgei"; break;
case 6: new = "twllei"; break;
case 8: new = "twgti"; break;
case 12: new = "twgei"; break;
case 16: new = "twlti"; break;
case 20: new = "twlei"; break;
case 24: new = "twnei"; break;
default:
ins->num_ops = 3;
}
if( ins->num_ops == 2 ) {
ins->op[0] = ins->op[1];
ins->op[1] = ins->op[2];
}
break;
case DI_PPC_tw:
ins->num_ops = 2;
switch( ins->op[0].value ) {
case 1: new = "twlgt"; break;
case 2: new = "twllt"; break;
case 4: new = "tweq"; break;
case 5: new = "twlge"; break;
case 6: new = "twlle"; break;
case 8: new = "twgt"; break;
case 12: new = "twge"; break;
case 16: new = "twlt"; break;
case 20: new = "twle"; break;
case 24: new = "twne"; break;
case 31: new = "trap";
ins->num_ops = 0;
break;
default:
ins->num_ops = 3;
}
if( ins->num_ops == 2 ) {
ins->op[0] = ins->op[1];
ins->op[1] = ins->op[2];
}
break;
case DI_PPC_addi:
// load 16-bit immediate value.
if( ins->op[1].base == DR_PPC_r0 ) {
new = "li";
ins->num_ops = 2;
ins->op[1] = ins->op[2];
break;
}
// adding negative value.
if( ins->op[2].value < 0 ) {
new = "subi";
ins->op[2].value = -ins->op[2].value;
}
break;
// load 16-bit shifted immediate value.
case DI_PPC_addis:
if( ins->op[1].base == DR_PPC_r0 ) {
new = "lis";
ins->num_ops = 2;
ins->op[1] = ins->op[2];
break;
}
break;
// Move register and compliment.
case DI_PPC_or:
if( ins->op[1].base == ins->op[2].base ) {
new = "mr";
ins->num_ops = 2;
}
break;
case DI_PPC_nor:
if( ins->op[1].base == ins->op[2].base ) {
new = "not";
ins->num_ops = 2;
}
break;
// nop.
case DI_PPC_ori:
if( ins->opcode == 0x60000000) { /* ori r0, r0, 0 */
new = "nop"; /* not no-op! */
ins->num_ops = 0;
}
break;
// SPR statements
case DI_PPC_mtspr:
ins->num_ops = 1;
case DI_PPC_mfspr:
ins->num_ops--; // ins->num_ops = 0 for mtspr, 1 for mfspr.
switch( ins->op[ins->num_ops].value ) {
case 1:
more = "xer";
break;
case 8:
more = "lr";
break;
case 9:
more = "ctr";
break;
case 18:
more = "dsisr";
break;
case 19:
more = "dar";
break;
case 22:
more = "dec";
break;
case 25:
more = "sdr1";
break;
case 26:
more = "srr0";
break;
case 27:
more = "srr1";
break;
case 272:
case 273:
case 274:
case 275:
more = "sprg";
ins->op[ins->num_ops].value -= 272;
ins->num_ops += 3; // To be fixed below
break;
case 282:
more = "ear";
break;
case 287:
if( ins->type == DI_PPC_mfspr ) {
more = "pvr";
} else {
ins->num_ops = 2;
}
break;
case 528:
case 530:
case 532:
case 534:
more = "ibatu";
ins->op[ins->num_ops].value = (ins->op[ins->num_ops].value - 528)/2;
ins->num_ops += 3;
break;
case 529:
case 531:
case 533:
case 535:
more = "ibatl";
ins->op[ins->num_ops].value = (ins->op[ins->num_ops].value - 529)/2;
ins->num_ops += 3;
break;
default:
ins->num_ops = 2;
}
switch( ins->num_ops ) {
case 0:
ins->op[0] = ins->op[1];
ins->num_ops = 1;
new = "mt";
break;
case 3:
new = "mt";
ins->num_ops = 2;
break;
case 4:
ins->num_ops = 2;
case 1:
new = "mf";
break;
}
break;
// Branch statements
case DI_PPC_bc:
if( (ins->op[0].value & 0x14) == 0x14 ) {
new = "b";
ins->op[0] = ins->op[2];
ins->num_ops = 1;
break;
}
case DI_PPC_bclr:
if( (ins->op[0].value & 0x14) == 0x14 ) {
new = "blr";
ins->num_ops = 0;
break;
}
ins->num_ops = 2;
switch( ins->op[0].value >> 1 ) {
case 0:
new = "bdnzf";
break;
case 1:
new = "bdzf";
break;
case 4:
new = "bdnzt";
break;
case 5:
new = "bdzt";
break;
case 8:
new = "bdnz";
ins->num_ops = 1;
ins->op[0] = ins->op[2];
break;
case 9:
new = "bdz";
ins->num_ops = 1;
ins->op[0] = ins->op[2];
break;
default:
ins->num_ops = 3;
}
if( ins->num_ops == 2 ) {
ins->op[0] = ins->op[1];
ins->op[1] = ins->op[2];
ins->op[0].base = (ins->op[0].value / 4) + DR_PPC_cr0;
ins->op[0].value %= 4;
}
if( ins->num_ops <= 2 ) {
if( ins->type == DI_PPC_bclr ) {
ins->num_ops--;
more = "lr";
}
break;
}
// else, fall through
case DI_PPC_bcctr:
if( (ins->op[0].value & 0x14) == 0x14 ) {
new = "bctr";
ins->num_ops = 0;
break;
}
if( (ins->op[0].value & 12) == 12 ) {
ins->num_ops = 2;
switch( ins->op[1].value % 4 ) {
case 0:
new = "blt";
break;
case 1:
new = "bgt";
break;
case 2:
new = "beq";
break;
case 3:
new = "bso";
break;
}
} else if( (ins->op[0].value & 4) == 4 ) {
ins->num_ops = 2;
switch( ins->op[1].value % 4 ) {
case 0:
new = "bge";
break;
case 1:
new = "ble";
break;
case 2:
new = "bne";
break;
case 3:
new = "bns";
break;
}
}
if( ins->num_ops == 2 ) {
ins->op[0] = ins->op[1];
ins->op[1] = ins->op[2];
ins->op[0].type = DO_REG;
ins->op[0].base = (ins->op[0].value / 4) + DR_PPC_cr0;
ins->op[0].value = 0;
if( ins->op[0].base == DR_PPC_cr0 ) {
ins->num_ops = 1;
ins->op[0] = ins->op[1];
}
switch( ins->type ) {
case DI_PPC_bclr:
ins->num_ops--;
more = "lr";
break;
case DI_PPC_bcctr:
ins->num_ops--;
more = "ctr";
break;
default:
break;
}
}
break;
default:
break;
}
if( name != NULL && new != NULL ) {
strcpy( name, new );
if( more != NULL ) {
strcat( name, more );
}
return( strlen( name ) );
}
return 0;
}
static unsigned PPCFlagHook( dis_handle *h, void *d, dis_dec_ins *ins,
dis_format_flags flags, char *name )
{
char *p;
p = name;
if( ins->flags & DIF_PPC_OE ) *p++ = 'o';
if( ins->flags & DIF_PPC_RC ) *p++ = '.';
if( ins->flags & DIF_PPC_LK ) *p++ = 'l';
if( ins->flags & DIF_PPC_AA ) *p++ = 'a';
*p='\0';
return( p-name );
}
static const char ConditionField[4][3] = {
"lt", "gt", "eq", "so"
};
static unsigned PPCOpHook( dis_handle *h, void *d, dis_dec_ins *ins,
dis_format_flags flags, unsigned op_num, char *op_buff )
{
char *p;
int val;
char ch;
const char *src;
dis_operand *op;
p = op_buff;
switch( ins->op[op_num].type ) {
// somewhat pointless to print out much more than this for
// these cases.
case DO_IMMED:
switch( ins->type ) {
case DI_PPC_cmp:
case DI_PPC_cmpl:
case DI_PPC_cmpi:
case DI_PPC_cmpli:
if( op_num == 1 ) {
// The 1-bit L parameter.
*p++ = ins->op[op_num].value + '0';
*p='\0';
}
break;
case DI_PPC_bc:
case DI_PPC_bcctr:
case DI_PPC_bclr:
if( (flags & DFF_PSEUDO) && op_num == 0 ) {
// pretty-printed BI parameter
if( ins->op[op_num].base != DR_PPC_cr0 ) {
p = DisAddReg( ins->op[op_num].base, p, flags );
*p++ = '+';
}
src = ConditionField[ins->op[op_num].value % 4];
for( ;; ) {
ch = *src;
*p = ch;
if( ch == '\0' ) break;
++src;
++p;
}
break;
}
// else, fall through
// The 5-bit BO and BI parameters.
//NYI: have to use client to get numeric prefix right
*p++ = '0';
*p++ = 'x';
val = ins->op[op_num].value;
*p++ = (val >> 4) + '0';
if( (val & 0xf) > 9 ) {
*p++ = (val & 0xf) + 'a' - 0xa;
} else {
*p++ = (val & 0xf) + '0';
}
*p='\0';
break;
default:
break;
}
default:
break;
}
if( flags & DFF_SYMBOLIC_REG ) {
op = &ins->op[op_num];
switch( op->base ) {
case DR_PPC_r1:
op->base = DR_PPC_sp;
break;
case DR_PPC_r2:
op->base = DR_PPC_rtoc;
break;
default:
break;
}
}
return( p-op_buff );
}
static dis_handler_return PPCDecodeTableCheck( int page, dis_dec_ins *ins )
{
return( DHR_DONE );
}
static void ByteSwap( dis_handle *h, void *d, dis_dec_ins *ins )
{
if( h->need_bswap ) {
SWAP_32( ins->opcode );
}
}
static void PPCPreprocHook( dis_handle *h, void *d, dis_dec_ins *ins )
{
ByteSwap( h, d, ins );
}
static unsigned PPCPostOpHook( dis_handle *h, void *d, dis_dec_ins *ins,
dis_format_flags flags, unsigned op_num, char *op_buff )
{
// Nothing to do
return( 0 );
}
const dis_cpu_data PPCData = {
PPCRangeTable, PPCRangeTablePos, PPCPreprocHook, PPCDecodeTableCheck, PPCInsHook, PPCFlagHook, PPCOpHook, PPCPostOpHook, &PPCMaxInsName, 4
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?