From 5e98a9fc723be6cab3e5d1b8648515f818bd4718 Mon Sep 17 00:00:00 2001 From: AJR Date: Sat, 7 Apr 2018 21:51:24 -0400 Subject: [PATCH] Further ARM disassembly improvements - Fix erroneous identification of S field in data processing opcodes - Calculate result of ADD/SUB Rn, R15, #imm --- src/devices/cpu/arm/armdasm.cpp | 88 +++++++++++++++++---------------- src/devices/cpu/arm/armdasm.h | 4 +- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/devices/cpu/arm/armdasm.cpp b/src/devices/cpu/arm/armdasm.cpp index 047fb2b3f70..af4a9be5bd7 100644 --- a/src/devices/cpu/arm/armdasm.cpp +++ b/src/devices/cpu/arm/armdasm.cpp @@ -9,58 +9,63 @@ #include "emu.h" #include "armdasm.h" -void arm_disassembler::WriteImmediateOperand( std::ostream &stream, uint32_t opcode ) const +uint32_t arm_disassembler::ExtractImmediateOperand(uint32_t opcode) const { - /* rrrrbbbbbbbb */ - uint32_t imm; - int r; - - imm = opcode&0xff; - r = ((opcode>>8)&0xf)*2; - imm = (imm>>r)|(r?(imm<<(32-r)):0); - util::stream_format( stream, ", #$%x", imm ); + // rrrrbbbbbbbb + uint32_t imm = opcode & 0xff; + uint8_t r = ((opcode >> 8) & 0xf) * 2; + return (imm >> r) | (r ? (imm << (32 - r)) : 0); } -void arm_disassembler::WriteDataProcessingOperand( std::ostream &stream, uint32_t opcode, bool printOp0, bool printOp1) const +void arm_disassembler::WriteDataProcessingOperand(std::ostream &stream, uint32_t opcode, bool printOp0, bool printOp1, offs_t pc) const { - /* ccccctttmmmm */ + // ccccctttmmmm static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" }; if (printOp0) - util::stream_format(stream, "R%d, ", (opcode>>12)&0xf); + util::stream_format(stream, "R%d, ", (opcode >> 12) & 0xf); if (printOp1) - util::stream_format(stream, "R%d, ", (opcode>>16)&0xf); + util::stream_format(stream, "R%d, ", (opcode >> 16) & 0xf); - /* Immediate Op2 */ + // Immediate Op2 if (opcode & 0x02000000) { - stream.seekp(-2, std::ios_base::cur); - WriteImmediateOperand(stream, opcode); - return; - } + uint32_t imm = ExtractImmediateOperand(opcode); + util::stream_format(stream, "#$%x", imm); - /* Register Op2 */ - util::stream_format(stream, "R%d", (opcode>>0)&0xf); - - int shiftop = (opcode >> 5) & 3; - if( opcode&0x10 ) /* Shift amount specified in bottom bits of RS */ - { - util::stream_format(stream, ", %s R%d", pRegOp[shiftop], (opcode >> 8) & 0xf); + // Calculate result of ADD/SUB Rn, R15, #imm + if ((opcode & 0x01ef0000) == 0x008f0000) + util::stream_format(stream, " ; =$%x", pc + 8 + imm); + else if ((opcode & 0x01ef0000) == 0x004f0000) + util::stream_format(stream, " ; =$%x", pc + 8 - imm); } - else /* Shift amount immediate 5 bit unsigned integer */ + else { - int c = (opcode >> 7) & 0x1f; - if (c == 0) + // Register Op2 + util::stream_format(stream, "R%d", (opcode >> 0) & 0xf); + + int shiftop = (opcode >> 5) & 3; + if ((opcode & 0x10) != 0) { - if (shiftop == 0) - return; - c = 32; + // Shift amount specified in bottom bits of RS + util::stream_format(stream, ", %s R%d", pRegOp[shiftop], (opcode >> 8) & 0xf); + } + else + { + // Shift amount immediate 5 bit unsigned integer + int c = (opcode >> 7) & 0x1f; + if (c == 0) + { + if (shiftop == 0) + return; + c = 32; + } + util::stream_format(stream, ", %s #%d", pRegOp[shiftop], c); } - util::stream_format( stream, ", %s #%d", pRegOp[shiftop], c); } } -void arm_disassembler::WriteRegisterOperand1( std::ostream &stream, uint32_t opcode ) const +void arm_disassembler::WriteRegisterOperand1(std::ostream &stream, uint32_t opcode) const { /* ccccctttmmmm */ static const char *const pRegOp[4] = { "LSL","LSR","ASR","ROR" }; @@ -89,7 +94,7 @@ void arm_disassembler::WriteRegisterOperand1( std::ostream &stream, uint32_t opc } /* WriteRegisterOperand */ -void arm_disassembler::WriteBranchAddress( std::ostream &stream, uint32_t pc, uint32_t opcode ) const +void arm_disassembler::WriteBranchAddress(std::ostream &stream, uint32_t pc, uint32_t opcode) const { opcode &= 0x00ffffff; if( opcode&0x00800000 ) @@ -144,10 +149,9 @@ offs_t arm_disassembler::disassemble(std::ostream &stream, offs_t pc, const data util::stream_format( stream, "MUL" ); } util::stream_format( stream, "%s", pConditionCode ); - if( opcode&0x00100000 ) - { + if ((opcode & 0x00100000) != 0) stream << 'S'; - } + WritePadding(stream, start_position); util::stream_format(stream, @@ -174,10 +178,8 @@ offs_t arm_disassembler::disassemble(std::ostream &stream, offs_t pc, const data pOperation[op], pConditionCode); - if( (opcode&0x01000000) ) - { + if ((opcode & 0x00100000) != 0) stream << 'S'; - } WritePadding(stream, start_position); @@ -192,20 +194,20 @@ offs_t arm_disassembler::disassemble(std::ostream &stream, offs_t pc, const data case 0x07: case 0x0c: case 0x0e: - WriteDataProcessingOperand(stream, opcode, true, true); + WriteDataProcessingOperand(stream, opcode, true, true, pc); break; case 0x08: case 0x09: case 0x0a: case 0x0b: - WriteDataProcessingOperand(stream, opcode, false, true); + WriteDataProcessingOperand(stream, opcode, false, true, pc); break; case 0x0d: /* look for mov pc,lr */ if (((opcode >> 12) & 0x0f) == 15 && ((opcode >> 0) & 0x0f) == 14 && (opcode & 0x02000000) == 0) dasmflags = STEP_OUT; case 0x0f: - WriteDataProcessingOperand(stream, opcode, true, false); + WriteDataProcessingOperand(stream, opcode, true, false, pc); break; } } diff --git a/src/devices/cpu/arm/armdasm.h b/src/devices/cpu/arm/armdasm.h index 4b20e7b79fb..15e66fe0323 100644 --- a/src/devices/cpu/arm/armdasm.h +++ b/src/devices/cpu/arm/armdasm.h @@ -12,8 +12,8 @@ public: virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; private: - void WriteImmediateOperand(std::ostream &stream, uint32_t opcode) const; - void WriteDataProcessingOperand(std::ostream &stream, uint32_t opcode, bool printOp0, bool printOp1) const; + uint32_t ExtractImmediateOperand(uint32_t opcode) const; + void WriteDataProcessingOperand(std::ostream &stream, uint32_t opcode, bool printOp0, bool printOp1, offs_t pc) const; void WriteRegisterOperand1(std::ostream &stream, uint32_t opcode) const; void WriteBranchAddress(std::ostream &stream, uint32_t pc, uint32_t opcode) const; void WritePadding(std::ostream &stream, std::streampos start_position) const;