Use 'ao-dbg' instead of 's51' to communicate with TeleMetrum
[fw/sdcc] / debugger / mcs51 / cmd.c
index 4cae0c91c5ec1284ef09a7437c965a3744e58e3b..cd038fffea32bcf9665469ffdfa2ba1671a79186 100644 (file)
@@ -1053,7 +1053,16 @@ static int stack_change(unsigned addr)
        }
 }
 
-static int pc_change(unsigned addr, unsigned addrs[2])
+static void
+do_indent(int indent);
+
+#if 1
+#define DPC(x)
+#else
+#define DPC(x) do { do_indent(indent); printf x; } while (0);
+#endif
+
+static int pc_change(unsigned addr, unsigned addrs[2], int indent)
 {
        unsigned char insn;
        unsigned new_addr;
@@ -1072,6 +1081,7 @@ static int pc_change(unsigned addr, unsigned addrs[2])
        if (insn == LJMP_addr16) {
                addrs[0] = ((simGetValue(addr+1, 'C', 1) << 8) |
                          (simGetValue(addr+2, 'C', 1)));
+               DPC(("0x%04x LJMP 0x%04x\n", addr, addrs[0]));
                return 1;
        }
        
@@ -1080,6 +1090,7 @@ static int pc_change(unsigned addr, unsigned addrs[2])
                unsigned char   direct = simGetValue(addr+1,'C', 1);
 
                addrs[0] = ((addr + 2) & 0xf800) | ((insn & 0xe0) << 3) | direct;
+               DPC(("0x%04x AJMP 0x%04x\n", addr, addrs[0]));
                return 1;
        }
 
@@ -1089,23 +1100,44 @@ static int pc_change(unsigned addr, unsigned addrs[2])
        delta = (signed char) simGetValue(addr+len-1, 'C', 1);
        new_addr = (addr + len) + delta;
        
-       if (insn == SJMP_rel) {
+       if (insn == SJMP_rel || (addr + len) == new_addr) {
                addrs[0] = new_addr;
+               DPC(("0x%04x SJMP 0x%04x\n", addr, addrs[0]));
                return 1;
        }
+       addrs[0] = (addr + len) & 0xffff;
+       addrs[1] = new_addr & 0xffff;
 
-       addrs[0] = addr + len;
-       addrs[1] = new_addr;
+       DPC(("0x%04x SJMP 0x%04x 0x%04x\n", addr, addrs[0], addrs[1]));
        return 2;
 }
 
-#define SEARCH_FAILED  0x8000
+#define SEARCH_LOOP    0x8000
+#define SEARCH_EXPIRED 0x8001
+
+#define MAX_STACK_BRANCH_TRACE 8192
+static unsigned stack_branch_trace[MAX_STACK_BRANCH_TRACE];
 
 static int
-stack_depth(unsigned pc, int search)
+been_here(unsigned pc, int ntrace)
+{
+       int t;
+       
+       for (t = 0; t < ntrace; t++)
+               if (stack_branch_trace[t] == pc)
+                       return 1;
+       return 0;
+}
+
+#define MAX_SEARCH     100
+
+#define indent (MAX_SEARCH - search)
+
+static int
+stack_depth(unsigned pc, int search, int ntrace)
 {
        unsigned new_pc[2];
-       unsigned max_pc = pc;
+       int d[2];
        int n;
        int s;
        int change;
@@ -1113,35 +1145,62 @@ stack_depth(unsigned pc, int search)
        change = 0;
        for (;;) {
                change += stack_change(pc);
-               n = pc_change(pc, new_pc);
+               n = pc_change(pc, new_pc, MAX_SEARCH - search);
                if (n == 0)
                        return change;
                if (n != 1)
                        break;
+               if (new_pc[0] <= pc) {
+                       if (been_here(pc, ntrace)) {
+                               DPC(("0x%04x loop 1\n", pc));
+                               return SEARCH_LOOP;
+                       }
+                       stack_branch_trace[ntrace++] = pc;
+               }
                pc = new_pc[0];
-               /* detect infinite loop */
-               if (pc == max_pc)
-                       return change;
-               if (pc > max_pc)
-                       max_pc = pc;
        }
        
-       if (search == 0)
-               return SEARCH_FAILED;
+       if (search == 0) {
+               DPC(("0x%04x max depth\n", pc));
+               return SEARCH_EXPIRED;
+       }
        
+       if (been_here(pc, ntrace))
+       {
+               DPC(("0x%04x loop 2\n", pc));
+               return SEARCH_LOOP;
+       }
+       stack_branch_trace[ntrace++] = pc;
+
        for (s = 0; s < search - 1; s++) {
-               int d;
-               int i;
-               d = SEARCH_FAILED;
-               for (i = 0; i < n; i++) {
-                       d = stack_depth(new_pc[i], search-1);
-                       if (d != SEARCH_FAILED)
+               int i, j, d;
+               
+               i = 0;
+               while (i < n) {
+                       d = stack_depth(new_pc[i], search-1, ntrace);
+                       if (d == SEARCH_LOOP) {
+                               for (j = i; j < n-1; j++)
+                                       new_pc[j] = new_pc[j+1];
+                               n--;
+                               continue;
+                       }
+                       if (d != SEARCH_EXPIRED) {
+                               DPC(("success %d\n", d + change));
                                return d + change;
+                       }
+                       i++;
+               }
+               if (n == 0) {
+                       DPC(("0x%04x loop 3\n", pc));
+                       return SEARCH_LOOP;
                }
        }
-       return SEARCH_FAILED;
+       DPC(("search expired\n"));
+       return SEARCH_EXPIRED;
 }
 
+#undef indent
+
 unsigned int
 stack_start(void)
 {
@@ -1162,10 +1221,11 @@ frameStart(unsigned int *bpp, unsigned int *pcp)
 
        pc = simGetPC();
        sp = simGetValue(0x81,'I',1);
-       depth = stack_depth(pc, 100);
-       bp = sp + depth;
-       if (bp < stack_start())
-               return 0;
+       depth = stack_depth(pc, MAX_SEARCH, 0);
+       if (depth == SEARCH_LOOP || depth == SEARCH_EXPIRED)
+               bp = 0;
+       else
+               bp = sp + depth;
        *bpp = bp;
        *pcp = pc;
        return 1;
@@ -1182,8 +1242,13 @@ frameNext(unsigned int *bpp, unsigned int *pcp)
        if (bp < stack_start())
                return 0;
        pc = simGetValue(bp - 1, 'B', 2);
-       depth = stack_depth(pc, 100);
-       bp = bp - 2 + depth;
+       if (pc == 0xffff)
+               return 0;
+       depth = stack_depth(pc, MAX_SEARCH, 0);
+       if (depth == SEARCH_LOOP || depth == SEARCH_EXPIRED)
+               bp = 0;
+       else
+               bp = bp - 2 + depth;
        *bpp = bp;
        *pcp = pc;
        return 1;