diff --git a/CMakeLists.txt b/CMakeLists.txt index 052b007..99c1839 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,11 @@ if (UNIX AND NOT APPLE) endif() endif() +find_package(PkgConfig REQUIRED) +pkg_check_modules(CAPSTONE REQUIRED capstone>=4.0.1) +include_directories(${CAPSTONE_INCLUDE_DIRS}) +link_directories(${CAPSTONE_LIBRARY_DIRS}) + add_subdirectory("${PROJECT_SOURCE_DIR}/cpu/ppc/") add_subdirectory("${PROJECT_SOURCE_DIR}/debugger/") add_subdirectory("${PROJECT_SOURCE_DIR}/devices/") @@ -64,7 +69,7 @@ target_link_libraries(dingusppc "${PROJECT_SOURCE_DIR}/thirdparty/SDL2/lib/x64/S cubeb) else() #target_link_libraries(dingusppc libsoundio_static ${LIBSOUNDIO_LIBS} ${SDL2_LIBRARIES}) -target_link_libraries(dingusppc cubeb ${SDL2_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(dingusppc cubeb ${SDL2_LIBRARIES} ${CAPSTONE_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) endif() @@ -80,7 +85,7 @@ target_link_libraries(testppc "${PROJECT_SOURCE_DIR}/thirdparty/SDL2/lib/x64/SDL cubeb) else() #target_link_libraries(testppc libsoundio_static ${LIBSOUNDIO_LIBS} ${SDL2_LIBRARIES}) -target_link_libraries(testppc cubeb ${SDL2_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) +target_link_libraries(testppc cubeb ${SDL2_LIBRARIES} ${CAPSTONE_LIBRARIES} ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) endif() add_custom_command( diff --git a/cpu/ppc/ppcemu.h b/cpu/ppc/ppcemu.h index 54f595d..7270bbc 100644 --- a/cpu/ppc/ppcemu.h +++ b/cpu/ppc/ppcemu.h @@ -481,7 +481,7 @@ extern void ppc_b(); extern void ppc_ba(); extern void ppc_bl(); extern void ppc_bla(); -extern void ppc_bc(); +extern void ppc_bc1(); extern void ppc_bca(); extern void ppc_bcl(); extern void ppc_bcla(); diff --git a/cpu/ppc/ppcexec.cpp b/cpu/ppc/ppcexec.cpp index 066ccfc..ee20032 100644 --- a/cpu/ppc/ppcexec.cpp +++ b/cpu/ppc/ppcexec.cpp @@ -82,7 +82,7 @@ static PPCOpcode OpcodeGrabber[] = { ppc_psq_st, ppc_psq_stu, ppc_illegalop, ppc_opcode63}; /** Lookup tables for branch instructions. */ -static PPCOpcode SubOpcode16Grabber[] = {ppc_bc, ppc_bcl, ppc_bca, ppc_bcla}; +static PPCOpcode SubOpcode16Grabber[] = {ppc_bc1, ppc_bcl, ppc_bca, ppc_bcla}; static PPCOpcode SubOpcode18Grabber[] = {ppc_b, ppc_bl, ppc_ba, ppc_bla}; diff --git a/cpu/ppc/ppcopcodes.cpp b/cpu/ppc/ppcopcodes.cpp index bcfd278..0094db5 100644 --- a/cpu/ppc/ppcopcodes.cpp +++ b/cpu/ppc/ppcopcodes.cpp @@ -1416,7 +1416,7 @@ void ppc_bla() { bb_kind = BB_end_kind::BB_BRANCH; } -void ppc_bc() { +void ppc_bc1() { uint32_t ctr_ok; uint32_t cnd_ok; uint32_t br_bo = (ppc_cur_instruction >> 21) & 31; diff --git a/debugger/debugger.cpp b/debugger/debugger.cpp index 1c0ee2e..a041ba6 100644 --- a/debugger/debugger.cpp +++ b/debugger/debugger.cpp @@ -19,9 +19,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "../cpu/ppc/ppcdisasm.h" -#include "../cpu/ppc/ppcemu.h" -#include "../cpu/ppc/ppcmmu.h" #include #include #include @@ -30,6 +27,10 @@ along with this program. If not, see . #include #include #include +#include +#include "../cpu/ppc/ppcdisasm.h" +#include "../cpu/ppc/ppcemu.h" +#include "../cpu/ppc/ppcmmu.h" using namespace std; @@ -88,6 +89,42 @@ static void disasm(uint32_t count, uint32_t address) { } } +static void disasm_68k(uint32_t count, uint32_t address) { + csh cs_handle; + uint8_t code[8]; + size_t code_size; + uint64_t dis_addr; + + if (cs_open(CS_ARCH_M68K, CS_MODE_M68K_040, &cs_handle) != CS_ERR_OK) { + cout << "Capstone initialization error" << endl; + return; + } + + cs_insn* insn = cs_malloc(cs_handle); + + for (; count > 0; count--) { + for (int i = 0; i < sizeof(code); i++) { + code[i] = mem_read_dbg(address + i, 1); + } + + const uint8_t *code_ptr = code; + code_size = sizeof(code); + dis_addr = address; + + if (cs_disasm_iter(cs_handle, &code_ptr, &code_size, &dis_addr, insn)) { + cout << uppercase << hex << insn->address; + cout << " " << insn->mnemonic << " " << insn->op_str << endl; + address = dis_addr; + } else { + cout << "DS.W " << hex << ((code[0] << 8) | code[1]) << endl; + address += 2; + } + } + + cs_free(insn, 1); + cs_close(&cs_handle); +} + static void dump_mem(string& params) { int cell_size, chars_per_line; bool is_char; @@ -181,13 +218,42 @@ static void dump_mem(string& params) { cout << endl << endl; } +void print_68k_regs() +{ + int i; + string reg; + + for (i = 0; i < 8; i++) { + reg = "R" + to_string(i + 8); + cout << "D" << dec << i << " : " << uppercase << hex << get_reg(reg) << endl; + } + + for (i = 0; i < 7; i++) { + reg = "R" + to_string(i + 16); + cout << "A" << dec << i << " : " << uppercase << hex << get_reg(reg) << endl; + } + reg = "R1"; + cout << "A7 : " << uppercase << hex << get_reg(reg) << endl; + + reg = "R24"; + cout << "PC: " << uppercase << hex << get_reg(reg) - 2 << endl; + + reg = "R25"; + cout << "SR: " << uppercase << hex << ((get_reg(reg) & 0xFF) << 8) << endl; + + reg = "R26"; + cout << "CCR: " << uppercase << hex << get_reg(reg) << endl; +} + void enter_debugger() { string inp, cmd, addr_str, expr_str, reg_expr, last_cmd, reg_value_str, inst_string, inst_num_str; uint32_t addr, inst_grab; std::stringstream ss; - int log_level; + int log_level, context; size_t separator_pos; + context = 1; /* start with the PowerPC context */ + cout << "Welcome to the DingusPPC command line debugger." << endl; cout << "Please enter a command or 'help'." << endl << endl; @@ -220,7 +286,11 @@ void enter_debugger() { } #endif else if (cmd == "regs") { - print_gprs(); + if (context == 2) { + print_68k_regs(); + } else { + print_gprs(); + } } else if (cmd == "set") { ss >> expr_str; @@ -278,27 +348,52 @@ void enter_debugger() { } catch (invalid_argument& exc) { try { /* number conversion failed, trying reg name */ - addr = get_reg(addr_str); + if (context == 2 && (addr_str == "pc" || addr_str == "PC")) { + addr_str = "R24"; + addr = get_reg(addr_str) - 2; + } else { + addr = get_reg(addr_str); + } } catch (invalid_argument& exc) { cout << exc.what() << endl; continue; } } try { - disasm(inst_grab, addr); + if (context == 2) { + disasm_68k(inst_grab, addr); + } else { + disasm(inst_grab, addr); + } } catch (invalid_argument& exc) { cout << exc.what() << endl; } } else { /* disas without arguments defaults to disas 1,pc */ - addr_str = "PC"; - addr = get_reg(addr_str); - disasm(1, addr); + if (context == 2) { + addr_str = "R24"; + addr = get_reg(addr_str); + disasm_68k(1, addr - 2); + } else { + addr_str = "PC"; + addr = get_reg(addr_str); + disasm(1, addr); + } } } else if (cmd == "dump") { expr_str = ""; ss >> expr_str; dump_mem(expr_str); + } else if (cmd == "context") { + expr_str = ""; + ss >> expr_str; + if (expr_str == "ppc" || expr_str == "PPC") { + context = 1; + } else if (expr_str == "68k" || expr_str == "68K") { + context = 2; + } else { + cout << "Unknown debugging context: " << expr_str << endl; + } } else { cout << "Unknown command: " << cmd << endl; continue; diff --git a/devices/atirage.cpp b/devices/atirage.cpp index e85f0e6..f9e1eb7 100644 --- a/devices/atirage.cpp +++ b/devices/atirage.cpp @@ -170,6 +170,8 @@ uint32_t ATIRage::read_reg(uint32_t offset, uint32_t size) { uint32_t res; switch (offset & ~3) { + case ATI_GP_IO: + break; case ATI_DAC_REGS: if (offset == ATI_DAC_DATA) { this->block_io_regs[ATI_DAC_DATA] =