📄 dis.c
字号:
default :
error = SHELL_ERROR_OPTION;
shell_error_data = argv[arg];
ok = FALSE;
break;
}
break;
case SHELL_TOKEN_NUMBER :
if( !address_valid )
{
address_valid = TRUE;
*address = decode.number;
}
else if( !count_valid )
{
count_valid = TRUE;
*count = decode.number;
}
else
ok = FALSE;
break;
default :
ok = FALSE;
break;
}
}
if(!address_valid)
ok = FALSE;
return ok ?
sys_validate_range( *address, (*count) * 4, sizeof(UINT32), FALSE ) :
error;
}
/************************************************************************
* do_dis
************************************************************************/
static void
do_dis( void )
{
UINT32 i;
UINT32 char_count;
char ch;
char line[80]; // must be long enough to hold disassembled inst line
if (SHELL_PUTC( '\n' )) return;
for (i=0; i<count; i++)
{
disassemble(line, address, REG32(address));
address += sizeof(UINT32);
if (!more)
SHELL_DISABLE_MORE;
if (SHELL_PUTS(line)) break;
}
SHELL_PUTC( '\n' );
}
/* Command definition for dis */
static t_cmd cmd_def =
{
"dis",
dis,
"dis [-m] <address> [<count>]",
#if 0
/* Does not work yet -- '.' always invokes 'dump': */
"Disassemble address range starting at 'address' (only MIPS32 instructions).\n"
"'count' (default 16) specifies the number of data units to disassemble.\n"
"More data may be disassembled by typing '.'",
#else
"Disassemble code starting at <address> (only MIPS32 instructions).\n"
"<count> (default 16) specifies the number of instructions to disassemble.",
#endif
options,
OPTION_COUNT,
FALSE
};
#if 0
/* Command definition for '.' */
static t_cmd cmd_def_dot =
{
".",
dis_dot,
".",
"Continue dis following previous address.",
NULL,
0,
TRUE
};
#endif
/************************************************************************
* disassemble
************************************************************************/
static int
disassemble(
char *dest, /* destination line */
UINT32 addr, /* virtual address */
UINT32 inst) /* instruction */
{
UINT32 op; /* Opcode */
UINT32 rs, rt, rd; /* Reg src target dest */
INT32 immed; /* Signed immediate */
UINT32 target; /* Target for jumps */
UINT32 shamt, funct; /* ShiftAmount / funct */
UINT32 sel; /* Select field in COPz */
char const *opc; /* Pointer to opcode */
int i;
int dix; /* dest index */
dix = 0;
if ((UINT32)addr & 3)
{
dix += sprintf(dest+dix,
"You can only disassemble from word boundaries.\n");
return -1;
};
dix += sprintf(dest+dix,
"%08X: %08X ", addr, inst);
/* Isolate all instruction fields */
op = (inst >> 26) & 0x3f;
rs = (inst >> 21) & 0x1f;
rt = (inst >> 16) & 0x1f;
rd = (inst >> 11) & 0x1f;
immed = (INT32) (
(inst & 0x0000ffff) |
((inst & 0x00008000) ? 0xffff0000 : 0));
target = inst & 0x03ffffff;
shamt = (inst >> 6) & 0x1f;
funct = inst & 0x3f;
sel = inst & 0x7;
if (op==0) opc = special[funct]; else
if (op==1) opc = bcond[rt]; else
if ((op==16) && (rs >= 16)) opc = cop0co[funct]; else
if ((op==16) && (rs < 8)) opc = cop0[rs]; else
if ((op==17) && (rs == 16)) opc = cop1s[funct]; else
if ((op==17) && (rs == 17)) opc = cop1d[funct]; else
if ((op==17) && (rs == 20)) opc = cop1w[funct]; else
if ((op==17) && (rs < 16)) opc = cop1[rs]; else
if (op==28) opc = spec2[funct]; else
opc = opcode[op];
if (!*opc) opc = " resvd"; else
if (inst==0) opc = " nop"; else
if ((op==0) && (funct==33) && ((rs==0) || (rt==0)))
{
opc = "jmove";
if (rs==0) rs=rt;
}
dix += sprintf(dest+dix, "%s",opc+1);
i = strlen(opc+1) ;
while (i++<10) dix += sprintf(dest+dix, " ");
addr += 4;
switch (*opc)
{
/* Formats for 'normal' instructions */
case 'o':
dix += sprintf(dest+dix, "%s,%d(%s)",
regs[rt], immed, regs[rs]);
break;
case 'i':
dix += sprintf(dest+dix, "%s,%s,%d",
regs[rt], regs[rs], immed);
break;
case 'I':
dix += sprintf(dest+dix, "%s,0x%X",
regs[rt], (immed<<16));
break;
case 't':
dix += sprintf(dest+dix, "0x%08X",
(target<<2) | (addr & 0xc0000000));
break;
case 'b':
dix += sprintf(dest+dix, "%s,%s,0x%08X",
regs[rs], regs[rt],( (INT32)addr+4*immed) );
break;
case 'c':
dix += sprintf(dest+dix, "0x%X", target);
break;
/* Formats for special instructions */
case 's':
dix += sprintf(dest+dix, "%s,%s,%d",
regs[rd], regs[rt], shamt);
break;
case 'v':
dix += sprintf(dest+dix, "%s,%s,%s",
regs[rd], regs[rt], regs[rs]);
break;
case 'j':
dix += sprintf(dest+dix, "%s,%s",
regs[rd], regs[rs]);
break;
case 'B':
dix += sprintf(dest+dix, "%d",
(UINT32) target>>6);
break;
case 'D':
dix += sprintf(dest+dix, "%s",
regs[rd]);
break;
case 'S':
dix += sprintf(dest+dix, "%s",
regs[rs]);
break;
case 'm':
dix += sprintf(dest+dix, "%s,%s",
regs[rs], regs[rt]);
break;
case 'r':
dix += sprintf(dest+dix, "%s,%s,%s",
regs[rd], regs[rs], regs[rt]);
break;
/* Formats for branch conditionals */
case 'C':
dix += sprintf(dest+dix, "%s,0x%X",
regs[rs], (INT32)addr + 4*immed );
break;
/* Formats for Coprocessor 0 */
case '0':
dix += sprintf(dest+dix, "%s,%s",
regs[rt], cp0regs[rd]);
if (sel)
dix += sprintf(dest+dix, ",%d", sel);
break;
/* Formats for Coprocessor 1 */
case '1':
dix += sprintf(dest+dix, "%s,%s",
regs[rt], fpregs[rd]);
if (sel)
dix += sprintf(dest+dix, ",%d", sel);
break;
case '2':
dix += sprintf(dest+dix, "%s,%s",
fpregs[rt], fpregs[rd]);
if (sel)
dix += sprintf(dest+dix, ",%d", sel);
break;
default:
// do nothing
break;
}
#if 1
dix += sprintf(dest+dix, "\n");
#else
dix += sprintf(dest+dix, "%c", LF);
#endif
return 0;
}
/************************************************************************
* Implementation : Public functions
************************************************************************/
/************************************************************************
*
* shell_dis_init
* Description :
* -------------
*
* Initialise command
*
* Return values :
* ---------------
*
* void
*
************************************************************************/
t_cmd *
shell_dis_init( void )
{
return &cmd_def;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -