debugger.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. MSP430 Emulator
  3. Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)
  4. "MSP430 Emulator" is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. "MSP430 Emulator" is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "debugger.h"
  16. extern uint8_t* MEMSPACE;
  17. Emulator *local_emu = NULL;
  18. bool exec_cmd (Emulator *emu, char *line, int len)
  19. {
  20. Cpu *cpu = emu->cpu;
  21. Debugger *deb = emu->debugger;
  22. char cmd[100] = {0};
  23. unsigned int op1 = 0, op2 = 0, op3 = 0;
  24. int ops;
  25. char bogus1[100] = {0};
  26. uint32_t bogus2 = 0, bogus3 = 0;
  27. ops = sscanf(line, "%s %u %u", cmd, &op1, &op2);
  28. //printf("Got %s, %u, %u - ops %d\n", cmd, op1, op2, ops);
  29. /* RESET / RESTART
  30. Resets the entire virtual machine to it's starting state.
  31. Puts the starting address back into Program Counter
  32. */
  33. if ( !strncasecmp("reset", cmd, sizeof "reset") ||
  34. !strncasecmp("restart", cmd, sizeof "restart"))
  35. {
  36. cpu->pc = 0xC000;
  37. display_registers(emu);
  38. disassemble(emu, cpu->pc, 1);
  39. }
  40. // s [NUM], step NUM instructions forward, defaults to 1 //
  41. else if ( !strncasecmp("s", cmd, sizeof "s") ||
  42. !strncasecmp("step", cmd, sizeof "step"))
  43. {
  44. int steps = 1; // 1 step by default
  45. uint32_t i;
  46. if (ops == 2) {
  47. steps = (int) op1;
  48. }
  49. for (i = 0;i < steps;i++) {
  50. decode(emu, fetch(emu), EXECUTE);
  51. // Handle Peripherals
  52. handle_bcm(emu);
  53. handle_timer_a(emu);
  54. handle_port_1(emu);
  55. handle_usci(emu);
  56. }
  57. display_registers(emu);
  58. disassemble(emu, cpu->pc, 1);
  59. }
  60. // Quit program //
  61. else if ( !strncasecmp("quit", cmd, sizeof "quit") ||
  62. !strncasecmp("q", cmd, sizeof "q"))
  63. {
  64. // This flag stops the main loop in main.c
  65. deb->quit = true;
  66. }
  67. // run the program until a breakpoint is hit //
  68. else if ( !strncasecmp("run", cmd, sizeof "run") ||
  69. !strncasecmp("r", cmd, sizeof "r"))
  70. {
  71. cpu->running = true;
  72. deb->debug_mode = false;
  73. update_register_display(emu);
  74. }
  75. // Display disassembly of N at HEX_ADDR: dis [N] [HEX_ADDR] //
  76. else if ( !strncasecmp("disas", cmd, sizeof "disas") ||
  77. !strncasecmp("dis", cmd, sizeof "dis") ||
  78. !strncasecmp("disassemble", cmd, sizeof "disassemble")) {
  79. uint16_t start_addr = cpu->pc;
  80. uint32_t num = 10;
  81. ops = sscanf(line, "%s %u %X", bogus1, &bogus2, &bogus3);
  82. if (ops == 2) {
  83. sscanf(line, "%s %u", bogus1, &num);
  84. }
  85. else if (ops == 3) {
  86. sscanf(line, "%s %u %X", bogus1, &num, (unsigned int *)&start_addr);
  87. }
  88. disassemble(emu, start_addr, num);
  89. }
  90. else if ( !strncasecmp("dump", cmd, sizeof "dump" ))
  91. {
  92. char str[100] = {0};
  93. uint16_t start_addr = cpu->pc;
  94. uint32_t stride;
  95. sscanf(line, "%s %s", bogus1, str);
  96. // Is it a direct address or an adress in a register being spec'd
  97. if (str[0] >= '0' && str[0] <= '9') {
  98. sscanf(str, "%X", (unsigned int *) &start_addr);
  99. }
  100. else if (str[0] == '%' || str[0] == 'r' || str[0] == 'R')
  101. {
  102. uint16_t *p = (uint16_t *)get_reg_ptr(emu, reg_name_to_num(str));
  103. start_addr = *p;
  104. }
  105. stride = BYTE_STRIDE;
  106. dump_memory(emu, MEMSPACE, 0x0, start_addr, stride);
  107. }
  108. // Set REG/LOC VALUE
  109. else if ( !strncasecmp("set", cmd, sizeof "set") )
  110. {
  111. uint16_t value = 0;
  112. char reg_name_or_addr[50] = {0};
  113. char *reg_name = NULL;
  114. char *addr_str = NULL;
  115. //print_console(emu, "Not yet implemented.\n");
  116. sscanf(line, "%s %s %X", bogus1, reg_name_or_addr,
  117. (unsigned int*)&value);
  118. //printf("Got %s and %X\n", reg_name_or_addr, value);
  119. // Figure out if the value given is a reg name or addr
  120. int res = reg_name_to_num(reg_name_or_addr);
  121. if (res != -1) { // If its a reg name
  122. reg_name = reg_name_or_addr;
  123. printf("In reg part...\n");
  124. if (res == 2) { // SR (R2)
  125. set_sr_value(emu, value);
  126. }
  127. else { // All others
  128. uint16_t *p = (uint16_t*)get_reg_ptr(emu, res);
  129. *p = value;
  130. }
  131. display_registers(emu);
  132. disassemble(emu, cpu->pc, 1);
  133. }
  134. else {
  135. addr_str = reg_name_or_addr;
  136. printf("In addr part...\n");
  137. uint16_t virtual_addr = (uint16_t) strtol(addr_str, NULL, 0);
  138. uint16_t *p = get_addr_ptr(virtual_addr);
  139. *p = value;
  140. }
  141. }
  142. // break BREAKPOINT_ADDRESS - set breakpoint //
  143. else if ( !strncasecmp("break", cmd, sizeof "break") )
  144. {
  145. if (deb->num_bps >= MAX_BREAKPOINTS) {
  146. //printf("Breakpoints are full.\n");
  147. print_console(emu, "Breakpoints are full.\n");
  148. return true;
  149. }
  150. ops = sscanf(line, "%s %X", bogus1, &bogus2);
  151. char entry[100] = {0};
  152. if (ops == 2) {
  153. sscanf(line, "%s %X", bogus1, (unsigned int *)
  154. &deb->bp_addresses[deb->num_bps]);
  155. sprintf(entry, "\n\t[Breakpoint [%d] Set]\n", deb->num_bps + 1);
  156. //printf("%s", entry);
  157. print_console(emu, entry);
  158. ++deb->num_bps;
  159. }
  160. else {
  161. //printf("error\n");
  162. print_console(emu, "error\n");
  163. }
  164. }
  165. // Display all breakpoints //
  166. else if ( !strncasecmp("bps", cmd, sizeof "bps" ))
  167. {
  168. char entry[100] = {0};
  169. if (deb->num_bps > 0) {
  170. deb->current_bp = 0;
  171. while (deb->current_bp < deb->num_bps) {
  172. sprintf(entry, "\t[%d] 0x%04X\n",
  173. deb->current_bp+1, deb->bp_addresses[deb->current_bp]);
  174. //printf("%s", entry);
  175. print_console(emu, entry);
  176. ++deb->current_bp;
  177. }
  178. }
  179. else {
  180. //printf("You have not set any breakpoints!\n");
  181. print_console(emu, "You have not set any breakpoints!\n");
  182. }
  183. }
  184. // Display registers //
  185. else if ( !strncasecmp("regs", cmd, sizeof "regs"))
  186. {
  187. display_registers(emu);
  188. disassemble(emu, cpu->pc, 1);
  189. }
  190. // help, display a list of debugger cmds //
  191. else if ( !strncasecmp("help", cmd, sizeof "help") ||
  192. !strncasecmp("h", cmd, sizeof "h") )
  193. {
  194. display_help(emu);
  195. }
  196. // End the line loop, next instruction
  197. else
  198. {
  199. print_console(emu, "\t[Invalid command, type \"help\".]\n");
  200. }
  201. return true;
  202. }
  203. /* Main command loop */
  204. bool command_loop (Emulator *emu, char *buf, int len)
  205. {
  206. /*
  207. Cpu *cpu = emu->cpu;
  208. Debugger *debugger = emu->debugger;
  209. static uint16_t breakpoint_addresses[MAX_BREAKPOINTS];
  210. static uint8_t cur_bp_number = 0;
  211. char cmd[512];
  212. char *line;
  213. // Check for breakpoints //
  214. int i;
  215. for (i = 0;i < cur_bp_number;i++) {
  216. if (cpu->pc == breakpoint_addresses[i]) {
  217. debugger->run = 0; // Stop fast execution //
  218. debugger->debug_mode = true;
  219. printf("\n\t[Breakpoint %d hit]\n\n", i + 1);
  220. break;
  221. }
  222. }
  223. if (!debugger->disassemble_mode && debugger->debug_mode) {
  224. display_registers(emu);
  225. disassemble(emu, cpu->pc, 1);
  226. }
  227. while (!debugger->run) {
  228. bzero(cmd, sizeof cmd);
  229. line = readline("\n>> ");
  230. if ( strlen(line) >= 1 ) {
  231. add_history(line);
  232. sscanf(line, "%s", cmd);
  233. line += strlen(cmd) + 1;
  234. }
  235. else {
  236. continue;
  237. }
  238. // reset the virtual machine
  239. if ( !strncasecmp("reset", cmd, sizeof "reset") ||
  240. !strncasecmp("restart", cmd, sizeof "restart")) {
  241. cpu->pc = 0xC000;
  242. break;
  243. }
  244. // s NUM_STEPS, step X instructions forward, defaults to 1
  245. else if ( !strncasecmp("s", cmd, sizeof "s") ||
  246. !strncasecmp("step", cmd, sizeof "step")) {
  247. unsigned int num_of_steps = 0;
  248. if (line[1] == ' ') {
  249. sscanf(line, "%u", &num_of_steps);
  250. printf("TODO:Stepping %u\n", num_of_steps);
  251. }
  252. break;
  253. }
  254. // run, run the program until a breakpoint is hit
  255. else if ( !strncasecmp("quit", cmd, sizeof "quit") ||
  256. !strncasecmp("q", cmd, sizeof "q")) {
  257. return false;
  258. }
  259. // run, run the program until a breakpoint is hit
  260. else if ( !strncasecmp("run", cmd, sizeof "run") ||
  261. !strncasecmp("r", cmd, sizeof "r")) {
  262. debugger->run = true;
  263. debugger->debug_mode = false;
  264. break;
  265. }
  266. // Display disassembly
  267. else if ( !strncasecmp("disas", cmd, sizeof "disas") ||
  268. !strncasecmp("dis", cmd, sizeof "dis") ||
  269. !strncasecmp("disassemble", cmd, sizeof "disassemble")) {
  270. uint16_t start_addr;
  271. uint32_t num;
  272. int res;
  273. res = sscanf(line, "%X%u", (unsigned int *) &start_addr, &num);
  274. if (res <= 0) {
  275. start_addr = cpu->pc;
  276. num = 10;
  277. }
  278. else if (res == 1) {
  279. num = 10;
  280. }
  281. if (num > 0)
  282. disassemble(emu, start_addr, num);
  283. continue;
  284. }
  285. // Display all 16 registers
  286. else if ( !strncasecmp("regs", cmd, sizeof "regs")) {
  287. display_registers(emu);
  288. continue;
  289. }
  290. // Display all breakpoints
  291. else if ( !strncasecmp("bps", cmd, sizeof "bps" )) {
  292. if (cur_bp_number > 0) {
  293. int i;
  294. for (i = 0;i < cur_bp_number;i++) {
  295. printf("\t[%d] 0x%04X\n", i + 1, breakpoint_addresses[i]);
  296. }
  297. }
  298. else {
  299. puts("You have not set any breakpoints!\n");
  300. }
  301. continue;
  302. }
  303. else if ( !strncasecmp("dump", cmd, sizeof "dump" )) {
  304. char param1[33] = {0};
  305. uint16_t start_addr;
  306. uint32_t stride;
  307. sscanf(line, "%s", param1);
  308. // Is it a direct address or a an address in a register being spec'd
  309. if (param1[0] >= '0' && param1[0] <= '9') {
  310. sscanf(param1, "%X", (unsigned int *) &start_addr);
  311. }
  312. else if (param1[0] == '%' || param1[0] == 'r' || param1[0] == 'R') {
  313. uint16_t *p = (uint16_t *)get_reg_ptr(emu, reg_name_to_num(param1));
  314. start_addr = *p;
  315. }
  316. stride = BYTE_STRIDE;
  317. dump_memory(MEMSPACE, 0x0, start_addr, stride);
  318. }
  319. // Set REG/LOC VALUE
  320. else if ( !strncasecmp("set", cmd, sizeof "set") ) {
  321. int value = 0;
  322. char reg_name_or_addr[33];
  323. sscanf(line, "%s %X", reg_name_or_addr, &value);
  324. if ( reg_name_to_num(reg_name_or_addr) != -1 ) {
  325. uint16_t *p = (uint16_t *)get_reg_ptr(emu, reg_name_to_num(reg_name_or_addr) );
  326. *p = value;
  327. display_registers(emu);
  328. disassemble(emu, cpu->pc, 1);
  329. }
  330. else {
  331. uint16_t virtual_addr = (uint16_t) strtol(reg_name_or_addr, NULL, 0);
  332. uint16_t *p = get_addr_ptr(virtual_addr);
  333. *p = value;
  334. }
  335. continue;
  336. }
  337. // break BREAKPOINT_ADDRESS
  338. else if ( !strncasecmp("break", cmd, sizeof "break") ) {
  339. if (cur_bp_number >= MAX_BREAKPOINTS) {
  340. printf("Too many breakpoints.\n");
  341. }
  342. else {
  343. sscanf(line, "%X", (unsigned int *)
  344. &breakpoint_addresses[cur_bp_number]);
  345. printf("\n\t[Breakpoint [%d] Set]\n", cur_bp_number + 1);
  346. ++cur_bp_number;
  347. }
  348. continue;
  349. }
  350. // help, display a list of debugger cmds
  351. else if ( !strncasecmp("help", cmd, sizeof "help") ||
  352. !strncasecmp("h", cmd, sizeof "h") ) {
  353. display_help(emu);
  354. }
  355. // End the line loop, next instruction
  356. else {
  357. puts("\t[Invalid command, type \"help\".]");
  358. continue;
  359. }
  360. }
  361. */
  362. return true;
  363. }
  364. //##########+++ Dump Memory Function +++##########
  365. void dump_memory ( Emulator *emu, uint8_t *MEM, uint32_t size, uint32_t start_addr, uint8_t stride)
  366. {
  367. uint32_t i, msp_addr = start_addr;
  368. MEM += start_addr;
  369. char str[100] = {0};
  370. puts("");
  371. print_console(emu, "\n");
  372. for (i = 0; i < 32; i += 8) {
  373. sprintf(str, "0x%04X:\t", msp_addr);
  374. printf("%s", str);
  375. print_console(emu, str);
  376. if ( stride == BYTE_STRIDE ) {
  377. sprintf(str, "0x%02X 0x%02X 0x%02X 0x%02X "\
  378. "0x%02X 0x%02X 0x%02X 0x%02X\n",
  379. *(MEM+0),*(MEM+1),*(MEM+2),*(MEM+3),
  380. *(MEM+4),*(MEM+5),*(MEM+6),*(MEM+7));
  381. printf("%s", str);
  382. print_console(emu, str);
  383. }
  384. else if ( stride == WORD_STRIDE ) {
  385. printf("0x%02X%02X 0x%02X%02X 0x%02X%02X 0x%02X%02X\n",
  386. *(MEM+0),*(MEM+1),*(MEM+2),*(MEM+3),*(MEM+4),
  387. *(MEM+5),*(MEM+6),*(MEM+7));
  388. }
  389. else if ( stride == DWORD_STRIDE ) {
  390. printf("0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
  391. *(MEM+0),*(MEM+1),*(MEM+2),*(MEM+3),*(MEM+4),
  392. *(MEM+5),*(MEM+6),*(MEM+7));
  393. }
  394. MEM += 8; // Increase character by 4
  395. msp_addr += 8; // Increase msp_addr by 4
  396. }
  397. puts("");
  398. }
  399. void setup_debugger(Emulator *emu)
  400. {
  401. local_emu = emu;
  402. Debugger *deb = emu->debugger;
  403. deb->debug_mode = true;
  404. deb->disassemble_mode = false;
  405. deb->quit = false;
  406. deb->web_interface = true;
  407. deb->web_server_ready = false;
  408. deb->web_firmware_uploaded = false;
  409. deb->console_interface = false;
  410. memset(deb->bp_addresses, 0, sizeof(deb->bp_addresses));
  411. deb->num_bps = 0;
  412. deb->current_bp = 0;
  413. }
  414. void handle_sigint(int sig)
  415. {
  416. if (local_emu == NULL) return;
  417. local_emu->cpu->running = false;
  418. local_emu->debugger->debug_mode = true;
  419. }
  420. void register_signal(int sig)
  421. {
  422. signal(sig, handle_sigint);
  423. }
  424. void handle_breakpoints (Emulator *emu)
  425. {
  426. int i;
  427. Cpu *cpu = emu->cpu;
  428. Debugger *deb = emu->debugger;
  429. char str[100] = {0};
  430. for (i = 0;i < deb->num_bps;i++) {
  431. if (cpu->pc == deb->bp_addresses[i]) {
  432. cpu->running = false;
  433. deb->debug_mode = true;
  434. sprintf(str, "\n\t[Breakpoint %d hit]\n\n", i + 1);
  435. printf("%s", str);
  436. print_console(emu, str);
  437. display_registers(emu);
  438. disassemble(emu, cpu->pc, 1);
  439. return;
  440. }
  441. }
  442. }