}
}
-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;
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;
}
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;
}
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;
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)
{
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;
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;