Added
authorceriel <none@none>
Mon, 16 Sep 1991 11:47:43 +0000 (11:47 +0000)
committerceriel <none@none>
Mon, 16 Sep 1991 11:47:43 +0000 (11:47 +0000)
mach/m68020/libdb/.distr [new file with mode: 0644]
mach/m68020/libdb/machdep.s [new file with mode: 0644]
mach/proto/grind/.distr [new file with mode: 0644]
mach/proto/grind/READ_ME [new file with mode: 0644]
mach/proto/grind/atlin.c [new file with mode: 0644]
mach/proto/grind/lib.e [new file with mode: 0644]
mach/proto/grind/par_misc.e [new file with mode: 0644]

diff --git a/mach/m68020/libdb/.distr b/mach/m68020/libdb/.distr
new file mode 100644 (file)
index 0000000..af5eda4
--- /dev/null
@@ -0,0 +1 @@
+machdep.s
diff --git a/mach/m68020/libdb/machdep.s b/mach/m68020/libdb/machdep.s
new file mode 100644 (file)
index 0000000..d6269c8
--- /dev/null
@@ -0,0 +1,63 @@
+.define ___Get_PC, ___Set_PC, ___u_LiB
+.sect .text; .sect .rom; .sect .data
+
+! $Header$
+
+! This is the machine-dependant part of the ACK debugger support.
+! ___Get_PC takes a frame pointer (local base) argument and returns the
+!          return address from this frame.
+! ___Set_PC takes a frame pointer (local base) argument plus a return
+!          address and sets the return address of this frame to the
+!          return address supplied.
+! ___u_LiB  saves the scratch registers and then calls ___uX_LiB;
+!          when ___uX_LiB returns, the scratch registers are restored.
+!          ___u_LiB is the solution chosen for the MC68020 back-end.
+!          Other back-ends could choose different solutions.
+
+! The local base of ___uX_LiB is kind of special: because of ___u_LiB,
+! the "interesting" return address of this particular stack-frame is found
+! in a different place than the one of a normal stack-frame:
+! the "interesting" return address is in fact the return address of
+! ___u_LiB. Therefore, we save the local base of ___uX_LiB in sv_a6.
+
+.sect .data
+sv_a6:
+       .data4 0
+
+.sect .text
+___Get_PC:
+       move.l  (4,sp),d0
+       beq     1f
+       move.l  d0,a0
+       cmp.l   (sv_a6),d0
+       beq     2f
+       move.l  (4,a0),d0
+1:
+       rts
+2:
+       move.l  (32,a0),d0
+       rts
+
+___Set_PC:
+       move.l  (4,sp),d0
+       beq     1f
+       move.l  d0,a0
+       cmp.l   (sv_a6),d0
+       beq     2f
+       move.l  (8,sp),(4,a0)
+1:
+       rts
+2:
+       move.l  (8,sp),(32,a0)
+       rts
+
+___u_LiB:
+       movem.l d0/d1/d2/a0/a1,-(sp)
+       move.l  (sv_a6),-(sp)
+       move.l  sp,d0
+       sub.l   #8,d0
+       move.l  d0,(sv_a6)      ! this is the LB of __uX_LiB
+       jsr (___uX_LiB)
+       move.l  (sp)+,(sv_a6)
+       movem.l (sp)+,d0/d1/d2/a0/a1
+       rts
diff --git a/mach/proto/grind/.distr b/mach/proto/grind/.distr
new file mode 100644 (file)
index 0000000..b57d195
--- /dev/null
@@ -0,0 +1,4 @@
+READ_ME
+atlin.c
+lib.e
+par_misc.e
diff --git a/mach/proto/grind/READ_ME b/mach/proto/grind/READ_ME
new file mode 100644 (file)
index 0000000..9307a3a
--- /dev/null
@@ -0,0 +1,17 @@
+$Header$
+
+The machine-dependant part of the ACK debugger support requires three
+routines:
+___Get_PC takes a frame pointer (local base) argument and returns the
+         return address from this frame.
+___Set_PC takes a frame pointer (local base) argument plus a return
+         address and sets the return address of this frame to the
+         return address supplied.
+???      a third routine which is called at every line (see for
+         instance mach/m68020/ncg/mach.c for an example of how to
+         do this). This routine must save the scratch registers
+         and then call (or jump to) ___uX_LiB. If this is a call,
+         ___Get_PC and ___Set_PC are complicated by the existance
+         of a procedure frame that we do not want the "grind" user
+         to know about. See for instance the mach/m68020/libdb version
+         for how to solve this problem.
diff --git a/mach/proto/grind/atlin.c b/mach/proto/grind/atlin.c
new file mode 100644 (file)
index 0000000..e4f526a
--- /dev/null
@@ -0,0 +1,508 @@
+/* $Header$ */
+
+#define DEBUGGEE
+#include "message.h"
+
+#define MAXBP  128
+#define MAXTRACE 16
+
+static int     nbp;                    /* # of breakpoints */
+static char    *bp[MAXBP];
+static int     ntrace;
+static struct trace {
+  char *begin_trace, *end_trace;
+} trace_buf[MAXTRACE];
+
+static struct message_hdr ok_message;
+
+#define OFF    0
+#define SS     1                       /* single stepping */
+#define SSF    2                       /* single stepping, counting functions
+                                          as single statements */
+
+static char *
+BUFTOA(p)
+  register char        *p;
+{
+  register long        l = 0;
+  register int i;
+
+  for (i = PS; i>0; i--) {
+       l = (l << 8) | (*p++ & 0377);
+  }
+  return (char *) l;
+}
+
+static long
+BUFTOL(p)
+  register char        *p;
+{
+  register long        l = 0;
+  register int i;
+
+  for (i = LS; i>0; i--) {
+       l = (l << 8) | (*p++ & 0377);
+  }
+  return l;
+}
+
+static
+ATOBUF(p, cp)
+  register char        *p;
+  char *cp;
+{
+  register int i;
+  register long l = (long) cp;
+
+  p += PS;
+  for (i = PS; i > 0; i--) {
+       *--p = l;
+       l >>= 8;
+  }
+}
+
+static
+LTOBUF(p, l)
+  register char        *p;
+  register long        l;
+{
+  register int i;
+
+  p += LS;
+  for (i = LS; i > 0; i--) {
+       *--p = l;
+       l >>= 8;
+  }
+}
+
+static int single_stepping = OFF;
+static int db_ss = 0;
+static int step_count = 0;
+static char    *savedlb;
+static int     break_flag = 0;
+static int     reading = 0;
+static char    *retaddr;
+static char    *LB;
+static char    *currbrk;
+
+extern char *__Get_LB();
+extern char *__Get_Hol0();
+extern char *__Get_PC();
+extern char *__Cvt_LB_AB();
+extern char *__Get_HP();
+extern char *_sbrk();
+extern int  etext;
+extern __Set_PC();
+static send_ok();
+
+#define        check_ptr(c)    (((c) >= (char *)&etext && (c) <= currbrk) || (c) >= LB)
+
+#define IN_FD  3
+#define OUT_FD 6
+
+static int
+ureceive(p, c)
+  char *p;
+  long c;
+{
+  int  i;
+  int  retval = 1;
+
+  reading = 1;
+  while (c >= 0x1000) {
+       i = _read(IN_FD, p, 0x1000);
+       if (i == 0) return 0;
+       if (i < 0) {
+               retval = 0;
+               c -= 0x1000;
+       }
+       else {
+               p += i;
+               c -= i;
+       }
+  }
+  while (c > 0) {
+       i = _read(IN_FD, p, (int)c);
+       if (i == 0) return 0;
+       if (i < 0) {
+               retval = 0;
+               break;
+       }
+       else {
+               p += i;
+               c -= i;
+       }
+  }
+  reading = 0;
+  return retval;
+}
+
+static int
+usend(p, c)
+  char *p;
+  long c;
+{
+  int  i;
+
+  while (c >= 0x1000) {
+       i = _write(OUT_FD, p, 0x1000);
+       if (i < 0) {
+               return 0;
+       }
+       p += i;
+       c -= i;
+  }
+  while (c > 0) {
+       i = _write(OUT_FD, p, (int)c);
+       if (i < 0) {
+               return 0;
+       }
+       p += i;
+       c -= i;
+  }
+  return 1;
+}
+
+static int
+ugetm(message)
+  struct message_hdr *message;
+{
+  if (! ureceive((char *) message, (long) sizeof(struct message_hdr))) {
+       return 0;
+  }
+  return 1;
+}
+
+static int
+uputm(message)
+  struct message_hdr *message;
+{
+  if (! usend((char *) message, (long) sizeof(struct message_hdr))) {
+       return 0;
+  }
+  return 1;
+}
+
+static int
+sendreply(m, p, sz)
+  struct message_hdr *m;
+  char *p;
+  long sz;
+{
+  if (! uputm(m) || ! (sz && p ? usend(p, sz) : 1)) {
+       return 0;
+  }
+  return 1;
+}
+
+static int
+do_request()
+{
+  /* obtain a request from the debugger and perform it */
+  int fail = 0;
+  register int i;
+  register char *c;
+  char *c1;
+  long sz;
+  struct message_hdr message;
+
+start:
+  if (! ugetm(&message)) {
+       /* failed to get a message. Something is wrong. Let process continue */
+       return 1;
+  }
+
+  if (message.m_type & M_DB_SS) db_ss = 1;
+  message.m_type &= 0177;
+  switch(message.m_type) {
+  case M_OK:
+       /* sometimes sent to child to see if it lives */
+       goto start;
+  case M_SETBP:
+       /* set a breakpoint */
+       if (nbp == MAXBP) {
+               fail = 1;
+               break;
+       }
+       bp[nbp++] = BUFTOA(message.m_buf+1);
+       break;
+  case M_SETTRACE:
+       if (ntrace == MAXTRACE) {
+               fail = 1;
+               break;
+       }
+       trace_buf[ntrace].begin_trace = BUFTOA(message.m_buf+1);
+       trace_buf[ntrace++].end_trace = BUFTOA(message.m_buf+(PS+1));
+       break;
+  case M_CLRBP:
+       i = 0;
+       c = BUFTOA(message.m_buf+1);
+       while (i < nbp && bp[i] != c) {
+                 i++;
+       }
+       if (i < nbp) {
+               while (i < nbp) {
+                       bp[i] = bp[i+1];
+                       i++;
+               }
+               nbp--;
+       }
+       else {
+               fail = 1;
+       }
+       break;
+  case M_CLRTRACE:
+       i = 0;
+       c = BUFTOA(message.m_buf+1);
+       c1 = BUFTOA(message.m_buf+(PS+1));
+       while (i < ntrace &&
+              trace_buf[i].begin_trace != c &&
+              trace_buf[i].end_trace != c1){
+                 i++;
+       }
+       if (i < ntrace) {
+               while (i < ntrace) {
+                       trace_buf[i] = trace_buf[i+1];
+                       i++;
+               }
+               ntrace--;
+       }
+       else {
+               fail = 1;
+       }
+       break;
+  case M_SETSS:
+       single_stepping = SS;
+       step_count = BUFTOL(message.m_buf+1);
+       return 1;
+  case M_CLRSS:
+       single_stepping = OFF;
+       break;
+  case M_SETSSF:
+       savedlb = __Get_LB(2);
+       step_count = BUFTOL(message.m_buf+1);
+       single_stepping = SSF;
+       return 1;
+  case M_GETBYTES:
+       message.m_type = M_DATA;
+       sz = BUFTOL(message.m_buf+1);
+       c = BUFTOA(message.m_buf+(LS+1));
+        currbrk = _sbrk(0);
+       if (! check_ptr(c) || ! check_ptr(c+sz-1)) {
+               fail = 1;
+               break;
+       }
+       return sendreply(&message, c, sz)
+               ? 0
+               : -1;
+
+  case M_GETSTR:
+       sz = BUFTOL(message.m_buf+1);
+       c1 = c = BUFTOA(message.m_buf+(LS+1));
+        currbrk = _sbrk(0);
+       if (check_ptr(c)) {
+               while (*c) {
+                       if (c - c1 + 1 >= sz) break;
+                       c++;
+                       if (! check_ptr(c)) {
+                               fail = 1;
+                               break;
+                       }
+               }
+       }
+       else    fail = 1;
+       if (fail) break;
+       message.m_type = M_DATA;
+       sz = c - c1 + 1;
+       LTOBUF(message.m_buf+1, sz);
+       return sendreply(&message, c1, sz)
+               ? 0
+               : -1;
+
+  case M_SETBYTES:
+       if (! ureceive(BUFTOA(message.m_buf+(LS+1)), BUFTOL(message.m_buf+1))) {
+               fail = 1;
+       }
+       break;
+
+  case M_GETEMREGS:
+       i = BUFTOL(message.m_buf+1);
+       c = __Get_LB(i+2);              /* local base */
+       c1 = __Get_LB(i+1);             /* needed to find PC and SP */
+       ATOBUF(message.m_buf+LB_OFF, c);
+       ATOBUF(message.m_buf+AB_OFF, __Cvt_LB_AB(c));
+       ATOBUF(message.m_buf+PC_OFF, __Get_PC(c1));
+       ATOBUF(message.m_buf+HP_OFF, __Get_HP());
+       ATOBUF(message.m_buf+SP_OFF, __Cvt_LB_AB(c1));
+       return sendreply(&message, (char *) 0, 0L) ? 0 : -1;
+
+  case M_SETEMREGS:
+       /* actually, only the program counter is settable */
+       i = BUFTOL(message.m_buf+1);
+       c = __Get_LB(i+1);
+       __Set_PC(c, BUFTOA(message.m_buf+PC_OFF));
+       break;
+
+  case M_CONT:
+       return 1;
+
+  case M_DUMP:
+       currbrk = _sbrk(0);
+       c = __Get_Hol0();
+       c1 = currbrk;
+       message.m_type = M_DGLOB;
+       sz = c1 - c;
+       LTOBUF(message.m_buf+1, sz);
+       ATOBUF(message.m_buf + HP_OFF, __Get_HP());
+       ATOBUF(message.m_buf + PC_OFF, __Get_PC(__Get_LB(1)));
+       ATOBUF(message.m_buf + LB_OFF, c1);
+
+       sendreply(&message, c, sz);
+       if (! ___topsave()) {
+               /* we get here after a ___topload() ! */
+               step_count = 0;
+               nbp = 0;
+               single_stepping = 0;
+               savedlb = 0;
+               break_flag = 0;
+               db_ss = 0;
+               break;
+       }
+       return 0;
+  case M_DGLOB:
+       _brk(BUFTOA(message.m_buf + LB_OFF));
+       __Set_HP(BUFTOA(message.m_buf+HP_OFF));
+       if (! ureceive(__Get_Hol0(), BUFTOL(message.m_buf+1))) {}
+       ___topload(BUFTOA(message.m_buf + SP_OFF));
+       /*NOTREACHED*/
+  }
+  send_ok(fail ? M_FAIL : M_OK);
+  return fail ? -1 : 0;
+}
+
+___sendtop(addr, SP, sz)
+  char *addr, *SP;
+  unsigned sz;
+{
+  struct message_hdr m;
+
+  m.m_type = M_DSTACK;
+  LTOBUF(m.m_buf+1, (long) sz);
+  ATOBUF(m.m_buf+SP_OFF, SP);
+  sendreply(&m, addr, (long)sz);
+}
+
+___restoretop(SP)
+  char *SP;
+{
+  struct message_hdr m;
+
+  if (! ugetm(&m)) {}
+  if (! ureceive(SP, BUFTOL(m.m_buf+1))) {}
+}
+
+static
+sigcatch()
+{
+  signal(7, sigcatch);
+  if (reading) send_ok(M_INTR);
+  else break_flag = 1;
+  db_ss = 0;
+}
+
+static int
+check_bp()
+{
+  register int i;
+
+  for (i = 0; i < nbp; i++) {
+       if (bp[i] == retaddr) {
+               return 1;
+       }
+  }
+  return 0;
+}
+
+static int
+check_trace()
+{
+  register int i;
+
+  for (i = 0; i < ntrace; i++) {
+       if (trace_buf[i].begin_trace <= retaddr &&
+           trace_buf[i].end_trace >= retaddr) {
+               return 1;
+       }
+  }
+  return 0;
+}
+
+static
+send_ok(type)
+{
+  register int i;
+
+  ok_message.m_type = type;
+  LTOBUF(ok_message.m_buf+1, (long) retaddr);
+  uputm(&ok_message);
+}
+
+void
+__uX_LiB()
+/* This function must be called after every LIN and LNI */
+{
+  int status = M_CONT;
+
+  LB = __Get_LB(0);
+  if ( retaddr) {
+       /* not the first time ... */
+       retaddr = __Get_PC(LB);
+
+       /* first, adjust step_count when single stepping
+       */
+       if (single_stepping == SS) step_count--;
+       else if (single_stepping == SSF) {
+               char *lb = __Get_LB(1);
+               if (!((char *) &lb < lb && lb >= savedlb ||
+                   (char *) &lb > lb && lb <= savedlb)) {
+               }
+               else {
+                       savedlb = lb;
+                       step_count--;
+               }
+       }
+
+       if (single_stepping != OFF && step_count <= 0) {
+               status = M_END_SS;
+               single_stepping = OFF;
+       }
+       else if (break_flag) status = M_INTR;
+  }
+  else {
+       signal(7, sigcatch);
+       retaddr = __Get_PC(LB);
+       status = M_OK;
+  }
+
+  if (status == M_CONT) {
+       if ((nbp != 0 && check_bp() != 0) ||
+           (ntrace != 0 && check_trace() != 0)) {
+               status = M_OK;
+       }
+       else if (break_flag) status = M_INTR;
+       else {
+               if (db_ss) {
+                       db_ss = 0;
+                       send_ok(M_DB_SS);
+                       while (do_request() <= 0) /* nothing */;
+               }
+               if (break_flag) status = M_INTR;
+               else return;
+       }
+  }
+
+  break_flag = 0;
+  send_ok(status);
+  db_ss = 0;
+  while (do_request() <= 0) /* nothing */;
+}
diff --git a/mach/proto/grind/lib.e b/mach/proto/grind/lib.e
new file mode 100644 (file)
index 0000000..b29796a
--- /dev/null
@@ -0,0 +1,58 @@
+#
+
+; $Header$
+
+ mes 2, EM_WSIZE, EM_PSIZE
+
+ exp $__Get_LB
+ pro $__Get_LB,0
+ lor 0
+1
+ lol 0
+ zlt *2
+ dup EM_PSIZE
+ zer EM_PSIZE
+ cmp
+ zeq *2
+ dch
+ del 0
+ bra *1
+2
+ ret EM_PSIZE
+ end
+
+ exp $__Get_Hol0
+ pro $__Get_Hol0,0
+ lae 0
+ ret EM_PSIZE
+ end
+
+ exp $__Get_HP
+ pro $__Get_HP,0
+ lor 2
+ ret EM_PSIZE
+ end
+
+ exp $__Set_HP
+ pro $__Set_HP,0
+ lal 0
+ loi EM_PSIZE
+ str 2
+ ret 0
+ end
+
+ exp $__Cvt_LB_AB
+ pro $__Cvt_LB_AB,0
+ lal 0
+ loi EM_PSIZE
+ zer EM_PSIZE
+ cmp
+ zeq *2
+ lal 0
+ loi EM_PSIZE
+ lpb
+ ret EM_PSIZE
+2
+ zer EM_PSIZE
+ ret EM_PSIZE
+ end
diff --git a/mach/proto/grind/par_misc.e b/mach/proto/grind/par_misc.e
new file mode 100644 (file)
index 0000000..7be77ea
--- /dev/null
@@ -0,0 +1,91 @@
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+
+;
+; Module:      coroutine primitives
+; Author:      Kees Bot, Edwin Scheffer, Ceriel Jacobs
+; Version:     $Header$
+;
+; This has been taken from the ACK Modula-2 runtime system and adapted.
+;
+
+ mes 2,EM_WSIZE,EM_PSIZE
+
+;
+; ___topsave: save the stack by sending it to the debugger
+;
+ exp $___topsave
+ pro $___topsave, 0
+ mes 11
+ loe 0
+ lae 4                 ; load line number and file name
+ loi EM_PSIZE
+ lim                   ; load ignore mask
+ lor 0                 ; load LB
+
+; now find the last argument base: first find the local base that has
+; dynamic link 0.
+
+ lor 0
+1
+ dup EM_PSIZE
+ dch
+ zer EM_PSIZE
+ cmp
+ zeq *2
+ dch
+ bra *1
+2
+ lpb                   ; last argument base
+
+; Now the stuff between the current stack pointer and this argument base
+; is saved by sending it to the debugger.
+
+ lor 1
+ sbs EM_WSIZE
+ loc EM_WSIZE
+ adu EM_WSIZE          ; gives size
+ lor 1                 ; SP (the SP BEFORE pushing)
+ lor 1                 ; SP (address of stack top to save)
+ cal $___sendtop       ; ___sendtop(char *address, char *SP, unsigned size)
+ asp 4*EM_PSIZE+3*EM_WSIZE     ; remove the lot from the stack
+ loc 1
+ ret EM_WSIZE                  ; return 1
+ end 0
+
+ exp $___topload
+ pro $___topload, 0
+
+ lal 0
+ loi EM_PSIZE
+
+ lxl 0
+2
+ dup EM_PSIZE
+ lal 0
+ loi EM_PSIZE          ; compare target SP with current LB to see if we must
+ loi EM_PSIZE
+ cmp                   ; find another LB first
+ zgt *1
+ dch                   ; just follow dynamic chain to make sure we find
+                       ; a legal one
+ bra *2
+1
+ str 0
+
+ str 1                 ; restore SP
+ lor 1
+ adp -EM_PSIZE
+ cal $___restoretop    ; ___restoretop(char *SP)
+ asp EM_PSIZE+EM_WSIZE
+ str 0                 ; restore local base
+ sim                   ; ignore mask
+ lae 4
+ sti EM_PSIZE
+ ste 0                 ; line and file
+ loc 0
+ ret EM_WSIZE          ; return 0
+ end 0