diff options
Diffstat (limited to 'src/devices/cpu/arm/armdasm.cpp')
-rw-r--r-- | src/devices/cpu/arm/armdasm.cpp | 196 |
1 files changed, 100 insertions, 96 deletions
diff --git a/src/devices/cpu/arm/armdasm.cpp b/src/devices/cpu/arm/armdasm.cpp index 08a0b282afe..b93b509789e 100644 --- a/src/devices/cpu/arm/armdasm.cpp +++ b/src/devices/cpu/arm/armdasm.cpp @@ -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); |