Rename DumpMem function -> memory_dump
[emu8051.git] / src / common / cpu8051.c
index bf7bd99..b420f78 100644 (file)
@@ -24,7 +24,9 @@
 
 #include <stdio.h>
 #include <stdint.h>
+#include <stdbool.h>
 
+#include "common.h"
 #include "reg8051.h"
 #include "cpu8051.h"
 #include "memory.h"
@@ -44,11 +46,11 @@ IsBreakpoint(unsigned int address)
 
        for (k = 0; k < cpu8051.bp_count; k++) {
                if (cpu8051.bp[k] == address)
-                       return 1;
+                       return true;
        }
 
        /* The address was not found in the list of breakpoints */
-       return 0;
+       return false;
 }
 
 /* Check if the address is a stop point */
@@ -56,9 +58,9 @@ int
 IsStoppoint(unsigned int address)
 {
        if ((options.stop_address != 0) && (options.stop_address == address))
-               return 1;
+               return true;
        else
-               return 0;
+               return false;
 }
 
 /* Show Breakpoints list */
@@ -67,18 +69,27 @@ ShowBreakpoints(void)
 {
        int k;
 
-       for (k = 0; k < cpu8051.bp_count; k++)
-               printf("Breakpoint at address = %.4X\n", cpu8051.bp[k]);
+       if (cpu8051.bp_count) {
+               printf("Breakpoints:\n");
+               for (k = 0; k < cpu8051.bp_count; k++)
+                       printf("  $%.4X\n", cpu8051.bp[k]);
+       } else
+               printf("No breakpoints defined\n");
 }
 
 /* Set Breakpoint at address at the end of the breakpoint list */
 void
 SetBreakpoint(unsigned int address)
 {
-       if (IsBreakpoint(address))
-               return; /* Already a breakpoint */
+       int rc;
+
+       rc = memory_check_address(PGM_MEM_ID, address, DISPLAY_ERROR_YES);
+       if (rc == false)
+               return; /* Error */
 
-       if (cpu8051.bp_count < MAXBP)
+       /* Check if breakpoint is already defined. */
+       if ((IsBreakpoint(address) == false) &&
+           (cpu8051.bp_count < MAXBP))
                cpu8051.bp[cpu8051.bp_count++] = address;
 }
 
@@ -87,6 +98,17 @@ void
 ClearBreakpoint(unsigned int address)
 {
        int k;
+       int rc;
+
+       rc = memory_check_address(PGM_MEM_ID, address, DISPLAY_ERROR_YES);
+       if (rc == false)
+               return; /* Error */
+
+       /* Check if breakpoint is defined. */
+       if (IsBreakpoint(address) == false) {
+               log_err("No breakpoint defined at address $%X", address);
+               return;
+       }
 
        for (k = 0; k < cpu8051.bp_count; k++) {
                if (cpu8051.bp[k] == address) {
@@ -97,6 +119,13 @@ ClearBreakpoint(unsigned int address)
        }
 }
 
+/* Clear all breakpoints */
+void
+ClearAllBreakpoints(void)
+{
+       cpu8051.bp_count = 0;
+}
+
 /* Toggle the breakpoint at Address. */
 void
 ToggleBreakpoint(unsigned int address)
@@ -112,6 +141,8 @@ cpu8051_init(void)
 {
        memory_init();
 
+       gp_timer_reset();
+
        cpu8051.pc = 0;
        cpu8051.clock = 0;
        cpu8051.active_priority = -1;
@@ -295,13 +326,21 @@ cpu8051_CheckInterrupts(void)
 }
 
 /* Execute at address cpu8051.pc from PGMMem */
-void
+int
 cpu8051_Exec(void)
 {
        int i;
+       int rc;
        unsigned char opcode;
        int insttiming;
 
+       /* Basic address check (may fail later if opcode has operands). */
+       rc = memory_check_address(PGM_MEM_ID, cpu8051.pc, DISPLAY_ERROR_NO);
+       if (rc == false) {
+               log_err("Trying to run past program memory limit");
+               return false; /* Error */
+       }
+
        opcode = memory_read8(PGM_MEM_ID, cpu8051.pc);
        cpu8051.pc++;
        insttiming = (*opcode_table[opcode])(); /* Function callback. */
@@ -312,11 +351,66 @@ cpu8051_Exec(void)
         */
        psw_compute_parity_bit();
 
+       gp_timer_increment(insttiming);
+
        for (i = 0; i < insttiming; i++) {
                cpu8051_CheckInterrupts();
                timers_check();
                cpu8051.clock++;
        }
+
+       return true;
+}
+
+/*
+ * Run specified number of instructions, or when encountering a
+ * breakpoint or a stop point.
+ * Set instr_count to -1 to disable running for a specific number
+ * of instructions.
+ *
+ * Returns TRUE when a breakpoint is encountered.
+ */
+int
+cpu8051_run(int instr_count, int (*interface_stop)(void))
+{
+       int rc;
+       int stop = false;
+       int breakpoint_hit = false;
+
+       while (stop == false) {
+               rc = cpu8051_Exec();
+               if (rc == false)
+                       stop = true;
+               else {
+                       if (instr_count > 0)
+                               instr_count--;
+
+                       if (instr_count == 0) {
+                               stop = true;
+                               log_info("Number of instructions reached");
+                       }
+
+                       if (IsBreakpoint(cpu8051.pc)) {
+                               stop = true;
+                               breakpoint_hit = true;
+                               log_info("Breakpoint hit at %.4X", cpu8051.pc);
+                       }
+
+                       if (IsStoppoint(cpu8051.pc)) {
+                               stop = true;
+                               log_info("Stoppoint hit at %.4X", cpu8051.pc);
+                       }
+
+                       if (interface_stop != NULL) {
+                               if (interface_stop()) {
+                                       stop = true;
+                                       log_info("Caught break signal");
+                               }
+                       }
+               }
+       }
+
+       return breakpoint_hit;
 }
 
 /*