Merge pull request #1659 from npwoods/dasmstream_arm

Changed the ARM disassembler to use 'std::ostream &' internally
This commit is contained in:
Vas Crabb 2016-11-12 17:49:15 +11:00 committed by GitHub
commit a261e9f4f2

View File

@ -9,7 +9,7 @@
#include "emu.h"
#include "arm.h"
static char *WriteImmediateOperand( char *pBuf, uint32_t opcode )
static void WriteImmediateOperand( std::ostream &stream, uint32_t opcode )
{
/* rrrrbbbbbbbb */
uint32_t imm;
@ -18,69 +18,70 @@ static char *WriteImmediateOperand( char *pBuf, uint32_t opcode )
imm = opcode&0xff;
r = ((opcode>>8)&0xf)*2;
imm = (imm>>r)|(r?(imm<<(32-r)):0);
pBuf += sprintf( pBuf, ", #$%x", imm );
return pBuf;
util::stream_format( stream, ", #$%x", imm );
}
static char *WriteDataProcessingOperand( char *pBuf, uint32_t opcode, int printOp0, int printOp1, int printOp2 )
static void WriteDataProcessingOperand( std::ostream &stream, uint32_t opcode, int printOp0, int printOp1, int printOp2 )
{
/* ccccctttmmmm */
static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" };
if (printOp0)
pBuf += sprintf(pBuf,"R%d, ", (opcode>>12)&0xf);
util::stream_format(stream, "R%d, ", (opcode>>12)&0xf);
if (printOp1)
pBuf += sprintf(pBuf,"R%d, ", (opcode>>16)&0xf);
util::stream_format(stream, "R%d, ", (opcode>>16)&0xf);
/* Immediate Op2 */
if( opcode&0x02000000 )
return WriteImmediateOperand(pBuf-2,opcode);
if (opcode & 0x02000000)
{
stream.seekp(-2, std::ios_base::cur);
WriteImmediateOperand(stream, opcode);
return;
}
/* Register Op2 */
if (printOp2)
pBuf += sprintf(pBuf,"R%d, ", (opcode>>0)&0xf);
util::stream_format(stream, "R%d, ", (opcode>>0)&0xf);
pBuf += sprintf(pBuf, "%s ", pRegOp[(opcode>>5)&3] );
util::stream_format(stream, "%s ", pRegOp[(opcode>>5)&3]);
if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */
{
pBuf += sprintf( pBuf, "R%d", (opcode>>8)&0xf );
util::stream_format( stream, "R%d", (opcode>>8)&0xf );
}
else /* Shift amount immediate 5 bit unsigned integer */
{
int c=(opcode>>7)&0x1f;
if( c==0 ) c = 32;
pBuf += sprintf( pBuf, "#%d", c );
util::stream_format( stream, "#%d", c );
}
return pBuf;
}
static char *WriteRegisterOperand1( char *pBuf, uint32_t opcode )
static void WriteRegisterOperand1( std::ostream &stream, uint32_t opcode )
{
/* ccccctttmmmm */
static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" };
pBuf += sprintf(
pBuf,
util::stream_format(
stream,
", R%d %s ", /* Operand 1 register, Operand 2 register, shift type */
(opcode>> 0)&0xf,
pRegOp[(opcode>>5)&3] );
pRegOp[(opcode>>5)&3]);
if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */
{
pBuf += sprintf( pBuf, "R%d", (opcode>>7)&0xf );
util::stream_format( stream, "R%d", (opcode>>7)&0xf );
}
else /* Shift amount immediate 5 bit unsigned integer */
{
int c=(opcode>>7)&0x1f;
if( c==0 ) c = 32;
pBuf += sprintf( pBuf, "#%d", c );
util::stream_format( stream, "#%d", c );
}
return pBuf;
} /* WriteRegisterOperand */
static char *WriteBranchAddress( char *pBuf, uint32_t pc, uint32_t opcode )
static void WriteBranchAddress( std::ostream &stream, uint32_t pc, uint32_t opcode )
{
opcode &= 0x00ffffff;
if( opcode&0x00800000 )
@ -88,24 +89,18 @@ static char *WriteBranchAddress( char *pBuf, uint32_t pc, uint32_t opcode )
opcode |= 0xff000000; /* sign-extend */
}
pc += 8+4*opcode;
sprintf( pBuf, "$%x", pc );
return pBuf;
util::stream_format( stream, "$%x", pc );
} /* WriteBranchAddress */
static char *WritePadding( char *pBuf, const char *pBuf0 )
static void WritePadding(std::ostream &stream, std::streampos start_position)
{
pBuf0 += 8;
while( pBuf<pBuf0 )
{
*pBuf++ = ' ';
}
return pBuf;
std::streamoff difference = stream.tellp() - start_position;
for (std::streamoff i = difference; i < 8; i++)
stream << ' ';
}
static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
static uint32_t arm_disasm( std::ostream &stream, uint32_t pc, uint32_t opcode )
{
const char *pBuf0;
static const char *const pConditionCodeTable[16] =
{
"EQ","NE","CS","CC",
@ -122,9 +117,9 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
};
const char *pConditionCode;
uint32_t dasmflags = 0;
std::streampos start_position = stream.tellp();
pConditionCode= pConditionCodeTable[opcode>>28];
pBuf0 = pBuf;
if( (opcode&0x0fc000f0)==0x00000090u )
{
@ -132,28 +127,28 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
/* xxxx0000 00ASdddd nnnnssss 1001mmmm */
if( opcode&0x00200000 )
{
pBuf += sprintf( pBuf, "MLA" );
util::stream_format( stream, "MLA" );
}
else
{
pBuf += sprintf( pBuf, "MUL" );
util::stream_format( stream, "MUL" );
}
pBuf += sprintf( pBuf, "%s", pConditionCode );
util::stream_format( stream, "%s", pConditionCode );
if( opcode&0x00100000 )
{
*pBuf++ = 'S';
stream << 'S';
}
pBuf = WritePadding( pBuf, pBuf0 );
WritePadding(stream, start_position);
pBuf += sprintf( pBuf,
util::stream_format(stream,
"R%d, R%d, R%d",
(opcode>>16)&0xf,
(opcode&0xf),
(opcode>>8)&0xf );
(opcode>>8)&0xf);
if( opcode&0x00200000 )
{
pBuf += sprintf( pBuf, ", R%d", (opcode>>12)&0xf );
util::stream_format( stream, ", R%d", (opcode>>12)&0xf );
}
}
else if( (opcode&0x0c000000)==0 )
@ -164,17 +159,17 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
/* xxxx001a aaaSnnnn ddddrrrr bbbbbbbb */
/* xxxx000a aaaSnnnn ddddcccc ctttmmmm */
pBuf += sprintf(
pBuf, "%s%s",
util::stream_format(stream,
"%s%s",
pOperation[op],
pConditionCode );
pConditionCode);
if( (opcode&0x01000000) )
{
*pBuf++ = 'S';
stream << 'S';
}
pBuf = WritePadding( pBuf, pBuf0 );
WritePadding(stream, start_position);
switch (op) {
case 0x00:
@ -187,20 +182,20 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
case 0x07:
case 0x0c:
case 0x0e:
WriteDataProcessingOperand(pBuf, opcode, 1, 1, 1);
WriteDataProcessingOperand(stream, opcode, 1, 1, 1);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
WriteDataProcessingOperand(pBuf, opcode, 0, 1, 1);
WriteDataProcessingOperand(stream, opcode, 0, 1, 1);
break;
case 0x0d:
/* look for mov pc,lr */
if (((opcode >> 12) & 0x0f) == 15 && ((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02000000) == 0)
dasmflags = DASMFLAG_STEP_OUT;
case 0x0f:
WriteDataProcessingOperand(pBuf, opcode, 1, 0, 1);
WriteDataProcessingOperand(stream, opcode, 1, 0, 1);
break;
}
}
@ -212,17 +207,17 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
/* xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form */
if( opcode&0x00100000 )
{
pBuf += sprintf( pBuf, "LDR" );
util::stream_format( stream, "LDR" );
}
else
{
pBuf += sprintf( pBuf, "STR" );
util::stream_format( stream, "STR" );
}
pBuf += sprintf( pBuf, "%s", pConditionCode );
util::stream_format( stream, "%s", pConditionCode );
if( opcode&0x00400000 )
{
pBuf += sprintf( pBuf, "B" );
util::stream_format( stream, "B" );
}
if( opcode&0x00200000 )
@ -231,36 +226,36 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
if( opcode&0x01000000 )
{
/* pre-indexed addressing */
pBuf += sprintf( pBuf, "!" );
util::stream_format( stream, "!" );
}
else
{
/* post-indexed addressing */
pBuf += sprintf( pBuf, "T" );
util::stream_format( stream, "T" );
}
}
pBuf = WritePadding( pBuf, pBuf0 );
pBuf += sprintf( pBuf, "R%d, [R%d",
WritePadding(stream, start_position);
util::stream_format( stream, "R%d, [R%d",
(opcode>>12)&0xf, (opcode>>16)&0xf );
if( opcode&0x02000000 )
{
/* register form */
pBuf = WriteRegisterOperand1( pBuf, opcode );
pBuf += sprintf( pBuf, "]" );
WriteRegisterOperand1( stream, opcode );
util::stream_format( stream, "]" );
}
else
{
/* immediate form */
pBuf += sprintf( pBuf, "]" );
util::stream_format( stream, "]" );
if( opcode&0x00800000 )
{
pBuf += sprintf( pBuf, ", #$%x", opcode&0xfff );
util::stream_format( stream, ", #$%x", opcode&0xfff );
}
else
{
pBuf += sprintf( pBuf, ", -#$%x", opcode&0xfff );
util::stream_format( stream, ", -#$%x", opcode&0xfff );
}
}
}
@ -271,33 +266,33 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
if( opcode&0x00100000 )
{
pBuf += sprintf( pBuf, "LDM" );
util::stream_format( stream, "LDM" );
}
else
{
pBuf += sprintf( pBuf, "STM" );
util::stream_format( stream, "STM" );
}
pBuf += sprintf( pBuf, "%s", pConditionCode );
util::stream_format( stream, "%s", pConditionCode );
if( opcode&0x01000000 )
{
pBuf += sprintf( pBuf, "P" );
util::stream_format( stream, "P" );
}
if( opcode&0x00800000 )
{
pBuf += sprintf( pBuf, "U" );
util::stream_format( stream, "U" );
}
if( opcode&0x00400000 )
{
pBuf += sprintf( pBuf, "^" );
util::stream_format( stream, "^" );
}
if( opcode&0x00200000 )
{
pBuf += sprintf( pBuf, "W" );
util::stream_format( stream, "W" );
}
pBuf = WritePadding( pBuf, pBuf0 );
pBuf += sprintf( pBuf, "[R%d], {",(opcode>>16)&0xf);
WritePadding(stream, start_position);
util::stream_format( stream, "[R%d], {",(opcode>>16)&0xf);
{
int j=0,last=0,found=0;
@ -308,20 +303,20 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
}
else if ((opcode&(1<<j))==0 && found) {
if (last==j-1)
pBuf += sprintf( pBuf, " R%d,",last);
util::stream_format( stream, " R%d,",last);
else
pBuf += sprintf( pBuf, " R%d-R%d,",last,j-1);
util::stream_format( stream, " R%d-R%d,",last,j-1);
found=0;
}
}
if (found && last==15)
pBuf += sprintf( pBuf, " R15,");
util::stream_format( stream, " R15,");
else if (found)
pBuf += sprintf( pBuf, " R%d-R%d,",last,15);
util::stream_format( stream, " R%d-R%d,",last,15);
}
pBuf--;
pBuf += sprintf( pBuf, " }");
stream.seekp(-1, std::ios_base::cur);
util::stream_format( stream, " }");
}
else if( (opcode&0x0e000000)==0x0a000000 )
{
@ -329,19 +324,19 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
/* xxxx101L oooooooo oooooooo oooooooo */
if( opcode&0x01000000 )
{
pBuf += sprintf( pBuf, "BL" );
util::stream_format( stream, "BL" );
dasmflags = DASMFLAG_STEP_OVER;
}
else
{
pBuf += sprintf( pBuf, "B" );
util::stream_format( stream, "B" );
}
pBuf += sprintf( pBuf, "%s", pConditionCode );
util::stream_format( stream, "%s", pConditionCode );
pBuf = WritePadding( pBuf, pBuf0 );
WritePadding(stream, start_position);
pBuf = WriteBranchAddress( pBuf, pc, opcode );
WriteBranchAddress( stream, pc, opcode );
}
else if( (opcode&0x0f000000) == 0x0e000000 )
{
@ -351,50 +346,59 @@ static uint32_t arm_disasm( char *pBuf, uint32_t pc, uint32_t opcode )
{
if( (opcode&0x0f100010)==0x0e100010 )
{
pBuf += sprintf( pBuf, "MRC" );
util::stream_format( stream, "MRC" );
}
else if( (opcode&0x0f100010)==0x0e000010 )
{
pBuf += sprintf( pBuf, "MCR" );
util::stream_format( stream, "MCR" );
}
else
{
pBuf += sprintf( pBuf, "???" );
util::stream_format( stream, "???" );
}
pBuf += sprintf( pBuf, "%s", pConditionCode );
pBuf = WritePadding( pBuf, pBuf0 );
pBuf += sprintf( pBuf, "R%d, CR%d {CRM%d, q%d}",(opcode>>12)&0xf, (opcode>>16)&0xf, (opcode>>0)&0xf, (opcode>>5)&0x7);
util::stream_format( stream, "%s", pConditionCode );
WritePadding(stream, start_position);
util::stream_format( stream, "R%d, CR%d {CRM%d, q%d}",(opcode>>12)&0xf, (opcode>>16)&0xf, (opcode>>0)&0xf, (opcode>>5)&0x7);
/* Nb: full form should be o, p, R, CR, CRM, q */
}
else if( (opcode&0x0f000010)==0x0e000000 )
{
pBuf += sprintf( pBuf, "CDP" );
pBuf += sprintf( pBuf, "%s", pConditionCode );
pBuf = WritePadding( pBuf, pBuf0 );
pBuf += sprintf( pBuf, "%08x", opcode );
util::stream_format( stream, "CDP" );
util::stream_format( stream, "%s", pConditionCode );
WritePadding(stream, start_position);
util::stream_format( stream, "%08x", opcode );
}
else
{
pBuf += sprintf( pBuf, "???" );
util::stream_format( stream, "???" );
}
}
else if( (opcode&0x0f000000) == 0x0f000000 )
{
/* Software Interrupt */
pBuf += sprintf( pBuf, "SWI%s $%x",
util::stream_format( stream, "SWI%s $%x",
pConditionCode,
opcode&0x00ffffff );
dasmflags = DASMFLAG_STEP_OVER;
}
else
{
pBuf += sprintf( pBuf, "Undefined" );
util::stream_format( stream, "Undefined" );
}
return dasmflags | DASMFLAG_SUPPORTED;
}
static uint32_t arm_disasm(char *buffer, uint32_t pc, uint32_t opcode)
{
std::ostringstream stream;
uint32_t result = arm_disasm(stream, pc, opcode);
std::string stream_str = stream.str();
strcpy(buffer, stream_str.c_str());
return result;
}
CPU_DISASSEMBLE( arm )
{
uint32_t opcode = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);