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] =