1/*  armrdi.c -- ARMulator RDI interface:  ARM6 Instruction Emulator.
2    Copyright (C) 1994 Advanced RISC Machines Ltd.
3
4    This program 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 2 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
17
18#include <string.h>
19#include <ctype.h>
20#include "armdefs.h"
21#include "armemu.h"
22#include "armos.h"
23#include "dbg_cp.h"
24#include "dbg_conf.h"
25#include "dbg_rdi.h"
26#include "dbg_hif.h"
27#include "communicate.h"
28
29/***************************************************************************\
30*                               Declarations                                *
31\***************************************************************************/
32
33#define Watch_AnyRead (RDIWatch_ByteRead+RDIWatch_HalfRead+RDIWatch_WordRead)
34#define Watch_AnyWrite (RDIWatch_ByteWrite+RDIWatch_HalfWrite+RDIWatch_WordWrite)
35
36static unsigned FPRegsAddr;	/* last known address of FPE regs */
37#define FPESTART 0x2000L
38#define FPEEND   0x8000L
39
40#define IGNORE(d) (d = d)
41#ifdef RDI_VERBOSE
42#define TracePrint(s) \
43 if (rdi_log & 1) ARMul_DebugPrint s
44#else
45#define TracePrint(s)
46#endif
47
48static ARMul_State *state = NULL;
49static unsigned BreaksSet;	/* The number of breakpoints set */
50
51static int rdi_log = 0;		/* debugging  ? */
52
53#define LOWEST_RDI_LEVEL 0
54#define HIGHEST_RDI_LEVEL 1
55static int MYrdi_level = LOWEST_RDI_LEVEL;
56
57typedef struct BreakNode BreakNode;
58typedef struct WatchNode WatchNode;
59
60struct BreakNode
61{				/* A breakpoint list node */
62  BreakNode *next;
63  ARMword address;		/* The address of this breakpoint */
64  unsigned type;		/* The type of comparison */
65  ARMword bound;		/* The other address for a range */
66  ARMword inst;
67};
68
69struct WatchNode
70{				/* A watchpoint list node */
71  WatchNode *next;
72  ARMword address;		/* The address of this watchpoint */
73  unsigned type;		/* The type of comparison */
74  unsigned datatype;		/* The type of access to watch for */
75  ARMword bound;		/* The other address for a range */
76};
77
78BreakNode *BreakList = NULL;
79WatchNode *WatchList = NULL;
80
81void
82ARMul_DebugPrint_i (const Dbg_HostosInterface * hostif, const char *format,
83		    ...)
84{
85  va_list ap;
86  va_start (ap, format);
87  hostif->dbgprint (hostif->dbgarg, format, ap);
88  va_end (ap);
89}
90
91void
92ARMul_DebugPrint (ARMul_State * state, const char *format, ...)
93{
94  va_list ap;
95  va_start (ap, format);
96  if (!(rdi_log & 8))
97    state->hostif->dbgprint (state->hostif->dbgarg, format, ap);
98  va_end (ap);
99}
100
101#define CONSOLE_PRINT_MAX_LEN 128
102
103void
104ARMul_ConsolePrint (ARMul_State * state, const char *format, ...)
105{
106  va_list ap;
107  int ch;
108  char *str, buf[CONSOLE_PRINT_MAX_LEN];
109  int i, j;
110  ARMword junk;
111
112  va_start (ap, format);
113  vsprintf (buf, format, ap);
114
115  for (i = 0; buf[i]; i++);	/* The string is i chars long */
116
117  str = buf;
118  while (i >= 32)
119    {
120      MYwrite_char (kidmum[1], RDP_OSOp);
121      MYwrite_word (kidmum[1], SWI_Write0);
122      MYwrite_char (kidmum[1], OS_SendString);
123      MYwrite_char (kidmum[1], 32);	/* Send string 32bytes at a time */
124      for (j = 0; j < 32; j++, str++)
125	MYwrite_char (kidmum[1], *str);
126      wait_for_osreply (&junk);
127      i -= 32;
128    }
129
130  if (i > 0)
131    {
132      MYwrite_char (kidmum[1], RDP_OSOp);
133      MYwrite_word (kidmum[1], SWI_Write0);
134      MYwrite_char (kidmum[1], OS_SendString);
135      MYwrite_char (kidmum[1], (unsigned char) i);	/* Send remainder of string  */
136      for (j = 0; j < i; j++, str++)
137	MYwrite_char (kidmum[1], *str);
138      wait_for_osreply (&junk);
139    }
140
141  va_end (ap);
142  return;
143
144/*   str = buf; */
145/*   while ((ch=*str++) != 0) */
146/*     state->hostif->writec(state->hostif->hostosarg, ch); */
147}
148
149void
150ARMul_DebugPause (ARMul_State * state)
151{
152  if (!(rdi_log & 8))
153    state->hostif->dbgpause (state->hostif->dbgarg);
154}
155
156/***************************************************************************\
157*                                 RDI_open                                  *
158\***************************************************************************/
159
160static void
161InitFail (int exitcode, char const *which)
162{
163  ARMul_ConsolePrint (state, "%s interface failed to initialise. Exiting\n",
164		      which);
165  exit (exitcode);
166}
167
168static void
169RDIInit (unsigned type)
170{
171  if (type == 0)
172    {				/* cold start */
173      state->CallDebug = state->MemReadDebug = state->MemWriteDebug = 0;
174      BreaksSet = 0;
175    }
176}
177
178#define UNKNOWNPROC 0
179
180typedef struct
181{
182  char name[16];
183  unsigned properties;
184}
185Processor;
186
187Processor const p_arm2 =    { "ARM2",   ARM_Fix26_Prop };
188Processor const p_arm2as =  { "ARM2AS", ARM_Fix26_Prop };
189Processor const p_arm61 =   { "ARM61",  ARM_Fix26_Prop };
190Processor const p_arm3 =    { "ARM3",   ARM_Fix26_Prop };
191Processor const p_arm6 =    { "ARM6",   ARM_Lock_Prop };
192Processor const p_arm60 =   {  "ARM60", ARM_Lock_Prop };
193Processor const p_arm600 =  { "ARM600", ARM_Lock_Prop };
194Processor const p_arm610 =  { "ARM610", ARM_Lock_Prop };
195Processor const p_arm620 =  { "ARM620", ARM_Lock_Prop };
196Processor const p_unknown = { "",       0 };
197
198Processor const *const processors[] =
199{
200  &p_arm6,			/* default: must come first */
201  &p_arm2,
202  &p_arm2as,
203  &p_arm61,
204  &p_arm3,
205  &p_arm60,
206  &p_arm600,
207  &p_arm610,
208  &p_arm620,
209  &p_unknown
210};
211
212typedef struct ProcessorConfig ProcessorConfig;
213struct ProcessorConfig
214{
215  long id[2];
216  ProcessorConfig const *self;
217  long count;
218  Processor const *const *processors;
219};
220
221ProcessorConfig const processorconfig = {
222  {((((((long) 'x' << 8) | ' ') << 8) | 'c') << 8) | 'p',
223   ((((((long) 'u' << 8) | 's') << 8) | ' ') << 8) | 'x'},
224  &processorconfig,
225  16,
226  processors
227};
228
229static int
230RDI_open (unsigned type, const Dbg_ConfigBlock * config,
231	  const Dbg_HostosInterface * hostif, struct Dbg_MCState *dbg_state)
232/* Initialise everything */
233{
234  int virgin = (state == NULL);
235  IGNORE (dbg_state);
236
237#ifdef RDI_VERBOSE
238  if (rdi_log & 1)
239    {
240      if (virgin)
241	ARMul_DebugPrint_i (hostif, "RDI_open: type = %d\n", type);
242      else
243	ARMul_DebugPrint (state, "RDI_open: type = %d\n", type);
244    }
245#endif
246
247  if (type & 1)
248    {				/* Warm start */
249      ARMul_Reset (state);
250      RDIInit (1);
251    }
252  else
253    {
254      if (virgin)
255	{
256	  ARMul_EmulateInit ();
257	  state = ARMul_NewState ();
258	  state->hostif = hostif;
259	  {
260	    int req = config->processor;
261	    unsigned processor = processors[req]->val;
262	    ARMul_SelectProcessor (state, processor);
263	    ARMul_Reset (state);
264	    ARMul_ConsolePrint (state, "ARMulator V1.50, %s",
265				processors[req]->name);
266	  }
267	  if (ARMul_MemoryInit (state, config->memorysize) == FALSE)
268	    InitFail (1, "Memory");
269	  if (config->bytesex != RDISex_DontCare)
270	    state->bigendSig = config->bytesex;
271	  if (ARMul_CoProInit (state) == FALSE)
272	    InitFail (2, "Co-Processor");
273	  if (ARMul_OSInit (state) == FALSE)
274	    InitFail (3, "Operating System");
275	}
276      ARMul_Reset (state);
277      RDIInit (0);
278    }
279  if (type & 2)
280    {				/* Reset the comms link */
281      /* what comms link ? */
282    }
283  if (virgin && (type & 1) == 0)	/* Cold start */
284    ARMul_ConsolePrint (state, ", %s endian.\n",
285			state->bigendSig ? "Big" : "Little");
286
287  if (config->bytesex == RDISex_DontCare)
288    return (state->bigendSig ? RDIError_BigEndian : RDIError_LittleEndian);
289  else
290    return (RDIError_NoError);
291}
292
293/***************************************************************************\
294*                                RDI_close                                  *
295\***************************************************************************/
296
297static int
298RDI_close (void)
299{
300  TracePrint ((state, "RDI_close\n"));
301  ARMul_OSExit (state);
302  ARMul_CoProExit (state);
303  ARMul_MemoryExit (state);
304  return (RDIError_NoError);
305}
306
307/***************************************************************************\
308*                                 RDI_read                                  *
309\***************************************************************************/
310
311static int
312RDI_read (ARMword source, void *dest, unsigned *nbytes)
313{
314  unsigned i;
315  char *memptr = (char *) dest;
316
317  TracePrint ((state, "RDI_read: source=%.8lx dest=%p nbytes=%.8x\n",
318	       source, dest, *nbytes));
319
320  for (i = 0; i < *nbytes; i++)
321    *memptr++ = (char) ARMul_ReadByte (state, source++);
322  if (state->abortSig)
323    {
324      state->abortSig = LOW;
325      return (RDIError_DataAbort);
326    }
327  return (RDIError_NoError);
328}
329
330/***************************************************************************\
331*                                  RDI_write                                *
332\***************************************************************************/
333
334static int
335RDI_write (const void *source, ARMword dest, unsigned *nbytes)
336{
337  unsigned i;
338  char *memptr = (char *) source;
339
340  TracePrint ((state, "RDI_write: source=%p dest=%.8lx nbytes=%.8x\n",
341	       source, dest, *nbytes));
342
343  for (i = 0; i < *nbytes; i++)
344    ARMul_WriteByte (state, (ARMword) dest++, (ARMword) * memptr++);
345
346  if (state->abortSig)
347    {
348      state->abortSig = LOW;
349      return (RDIError_DataAbort);
350    }
351  return (RDIError_NoError);
352}
353
354/***************************************************************************\
355*                                RDI_CPUread                                *
356\***************************************************************************/
357
358static int
359RDI_CPUread (unsigned mode, unsigned long mask, ARMword buffer[])
360{
361  unsigned i, upto;
362
363  if (mode == RDIMode_Curr)
364    mode = (unsigned) (ARMul_GetCPSR (state) & MODEBITS);
365
366  for (upto = 0, i = 0; i < 15; i++)
367    if (mask & (1L << i))
368      {
369	buffer[upto++] = ARMul_GetReg (state, mode, i);
370      }
371
372  if (mask & RDIReg_R15)
373    {
374      buffer[upto++] = ARMul_GetR15 (state);
375    }
376
377  if (mask & RDIReg_PC)
378    {
379      buffer[upto++] = ARMul_GetPC (state);
380    }
381
382  if (mask & RDIReg_CPSR)
383    buffer[upto++] = ARMul_GetCPSR (state);
384
385  if (mask & RDIReg_SPSR)
386    buffer[upto++] = ARMul_GetSPSR (state, mode);
387
388  TracePrint ((state, "RDI_CPUread: mode=%.8x mask=%.8lx", mode, mask));
389#ifdef RDI_VERBOSE
390  if (rdi_log & 1)
391    {
392      for (upto = 0, i = 0; i <= 20; i++)
393	if (mask & (1L << i))
394	  {
395	    ARMul_DebugPrint (state, "%c%.8lx", upto % 4 == 0 ? '\n' : ' ',
396			      buffer[upto]);
397	    upto++;
398	  }
399      ARMul_DebugPrint (state, "\n");
400    }
401#endif
402
403  return (RDIError_NoError);
404}
405
406/***************************************************************************\
407*                               RDI_CPUwrite                                *
408\***************************************************************************/
409
410static int
411RDI_CPUwrite (unsigned mode, unsigned long mask, ARMword const buffer[])
412{
413  int i, upto;
414
415
416  TracePrint ((state, "RDI_CPUwrite: mode=%.8x mask=%.8lx", mode, mask));
417#ifdef RDI_VERBOSE
418  if (rdi_log & 1)
419    {
420      for (upto = 0, i = 0; i <= 20; i++)
421	if (mask & (1L << i))
422	  {
423	    ARMul_DebugPrint (state, "%c%.8lx", upto % 4 == 0 ? '\n' : ' ',
424			      buffer[upto]);
425	    upto++;
426	  }
427      ARMul_DebugPrint (state, "\n");
428    }
429#endif
430
431  if (mode == RDIMode_Curr)
432    mode = (unsigned) (ARMul_GetCPSR (state) & MODEBITS);
433
434  for (upto = 0, i = 0; i < 15; i++)
435    if (mask & (1L << i))
436      ARMul_SetReg (state, mode, i, buffer[upto++]);
437
438  if (mask & RDIReg_R15)
439    ARMul_SetR15 (state, buffer[upto++]);
440
441  if (mask & RDIReg_PC)
442    {
443
444      ARMul_SetPC (state, buffer[upto++]);
445    }
446  if (mask & RDIReg_CPSR)
447    ARMul_SetCPSR (state, buffer[upto++]);
448
449  if (mask & RDIReg_SPSR)
450    ARMul_SetSPSR (state, mode, buffer[upto++]);
451
452  return (RDIError_NoError);
453}
454
455/***************************************************************************\
456*                                RDI_CPread                                 *
457\***************************************************************************/
458
459static int
460RDI_CPread (unsigned CPnum, unsigned long mask, ARMword buffer[])
461{
462  ARMword fpregsaddr, word[4];
463
464  unsigned r, w;
465  unsigned upto;
466
467  if (CPnum != 1 && CPnum != 2)
468    {
469      unsigned char const *rmap = state->CPRegWords[CPnum];
470      if (rmap == NULL)
471	return (RDIError_UnknownCoPro);
472      for (upto = 0, r = 0; r < rmap[-1]; r++)
473	if (mask & (1L << r))
474	  {
475	    (void) state->CPRead[CPnum] (state, r, &buffer[upto]);
476	    upto += rmap[r];
477	  }
478      TracePrint ((state, "RDI_CPread: CPnum=%d mask=%.8lx", CPnum, mask));
479#ifdef RDI_VERBOSE
480      if (rdi_log & 1)
481	{
482	  w = 0;
483	  for (upto = 0, r = 0; r < rmap[-1]; r++)
484	    if (mask & (1L << r))
485	      {
486		int words = rmap[r];
487		ARMul_DebugPrint (state, "%c%2d",
488				  (w >= 4 ? (w = 0, '\n') : ' '), r);
489		while (--words >= 0)
490		  {
491		    ARMul_DebugPrint (state, " %.8lx", buffer[upto++]);
492		    w++;
493		  }
494	      }
495	  ARMul_DebugPrint (state, "\n");
496	}
497#endif
498      return RDIError_NoError;
499    }
500
501#ifdef NOFPE
502  return RDIError_UnknownCoPro;
503
504#else
505  if (FPRegsAddr == 0)
506    {
507      fpregsaddr = ARMul_ReadWord (state, 4L);
508      if ((fpregsaddr & 0xff800000) != 0xea000000)	/* Must be a forward branch */
509	return RDIError_UnknownCoPro;
510      fpregsaddr = ((fpregsaddr & 0xffffff) << 2) + 8;	/* address in __fp_decode - 4 */
511      if ((fpregsaddr < FPESTART) || (fpregsaddr >= FPEEND))
512	return RDIError_UnknownCoPro;
513      fpregsaddr = ARMul_ReadWord (state, fpregsaddr);	/* pointer to fp registers */
514      FPRegsAddr = fpregsaddr;
515    }
516  else
517    fpregsaddr = FPRegsAddr;
518
519  if (fpregsaddr == 0)
520    return RDIError_UnknownCoPro;
521  for (upto = 0, r = 0; r < 8; r++)
522    if (mask & (1L << r))
523      {
524	for (w = 0; w < 4; w++)
525	  word[w] =
526	    ARMul_ReadWord (state,
527			    fpregsaddr + (ARMword) r * 16 + (ARMword) w * 4);
528	switch ((int) (word[3] >> 29))
529	  {
530	  case 0:
531	  case 2:
532	  case 4:
533	  case 6:		/* its unpacked, convert to extended */
534	    buffer[upto++] = 2;	/* mark as extended */
535	    buffer[upto++] = (word[3] & 0x7fff) | (word[0] & 0x80000000);	/* exp and sign */
536	    buffer[upto++] = word[1];	/* mantissa 1 */
537	    buffer[upto++] = word[2];	/* mantissa 2 */
538	    break;
539	  case 1:		/* packed single */
540	    buffer[upto++] = 0;	/* mark as single */
541	    buffer[upto++] = word[0];	/* sign, exp and mantissa */
542	    buffer[upto++] = word[1];	/* padding */
543	    buffer[upto++] = word[2];	/* padding */
544	    break;
545	  case 3:		/* packed double */
546	    buffer[upto++] = 1;	/* mark as double */
547	    buffer[upto++] = word[0];	/* sign, exp and mantissa1 */
548	    buffer[upto++] = word[1];	/* mantissa 2 */
549	    buffer[upto++] = word[2];	/* padding */
550	    break;
551	  case 5:		/* packed extended */
552	    buffer[upto++] = 2;	/* mark as extended */
553	    buffer[upto++] = word[0];	/* sign and exp */
554	    buffer[upto++] = word[1];	/* mantissa 1 */
555	    buffer[upto++] = word[2];	/* mantissa 2 */
556	    break;
557	  case 7:		/* packed decimal */
558	    buffer[upto++] = 3;	/* mark as packed decimal */
559	    buffer[upto++] = word[0];	/* sign, exp and mantissa1 */
560	    buffer[upto++] = word[1];	/* mantissa 2 */
561	    buffer[upto++] = word[2];	/* mantissa 3 */
562	    break;
563	  }
564      }
565  if (mask & (1L << r))
566    buffer[upto++] = ARMul_ReadWord (state, fpregsaddr + 128);	/* fpsr */
567  if (mask & (1L << (r + 1)))
568    buffer[upto++] = 0;		/* fpcr */
569
570  TracePrint ((state, "RDI_CPread: CPnum=%d mask=%.8lx\n", CPnum, mask));
571#ifdef RDI_VERBOSE
572  if (rdi_log & 1)
573    {
574      for (upto = 0, r = 0; r < 9; r++)
575	if (mask & (1L << r))
576	  {
577	    if (r != 8)
578	      {
579		ARMul_DebugPrint (state, "%08lx ", buffer[upto++]);
580		ARMul_DebugPrint (state, "%08lx ", buffer[upto++]);
581		ARMul_DebugPrint (state, "%08lx ", buffer[upto++]);
582	      }
583	    ARMul_DebugPrint (state, "%08lx\n", buffer[upto++]);
584	  }
585      ARMul_DebugPrint (state, "\n");
586    }
587#endif
588  return (RDIError_NoError);
589#endif /* NOFPE */
590}
591
592/***************************************************************************\
593*                               RDI_CPwrite                                 *
594\***************************************************************************/
595
596static int
597RDI_CPwrite (unsigned CPnum, unsigned long mask, ARMword const buffer[])
598{
599  unsigned r;
600  unsigned upto;
601  ARMword fpregsaddr;
602
603  if (CPnum != 1 && CPnum != 2)
604    {
605      unsigned char const *rmap = state->CPRegWords[CPnum];
606      if (rmap == NULL)
607	return (RDIError_UnknownCoPro);
608      TracePrint ((state, "RDI_CPwrite: CPnum=%d mask=%.8lx", CPnum, mask));
609#ifdef RDI_VERBOSE
610      if (rdi_log & 1)
611	{
612	  int w = 0;
613	  for (upto = 0, r = 0; r < rmap[-1]; r++)
614	    if (mask & (1L << r))
615	      {
616		int words = rmap[r];
617		ARMul_DebugPrint (state, "%c%2d",
618				  (w >= 4 ? (w = 0, '\n') : ' '), r);
619		while (--words >= 0)
620		  {
621		    ARMul_DebugPrint (state, " %.8lx", buffer[upto++]);
622		    w++;
623		  }
624	      }
625	  ARMul_DebugPrint (state, "\n");
626	}
627#endif
628      for (upto = 0, r = 0; r < rmap[-1]; r++)
629	if (mask & (1L << r))
630	  {
631	    (void) state->CPWrite[CPnum] (state, r, &buffer[upto]);
632	    upto += rmap[r];
633	  }
634      return RDIError_NoError;
635    }
636
637#ifdef NOFPE
638  return RDIError_UnknownCoPro;
639
640#else
641  TracePrint ((state, "RDI_CPwrite: CPnum=%d mask=%.8lx", CPnum, mask));
642#ifdef RDI_VERBOSE
643  if (rdi_log & 1)
644    {
645      for (upto = 0, r = 0; r < 9; r++)
646	if (mask & (1L << r))
647	  {
648	    if (r != 8)
649	      {
650		ARMul_DebugPrint (state, "%08lx ", buffer[upto++]);
651		ARMul_DebugPrint (state, "%08lx ", buffer[upto++]);
652		ARMul_DebugPrint (state, "%08lx ", buffer[upto++]);
653	      }
654	    ARMul_DebugPrint (state, "%08lx\n", buffer[upto++]);
655	  }
656      ARMul_DebugPrint (state, "\n");
657    }
658#endif
659
660  if (FPRegsAddr == 0)
661    {
662      fpregsaddr = ARMul_ReadWord (state, 4L);
663      if ((fpregsaddr & 0xff800000) != 0xea000000)	/* Must be a forward branch */
664	return RDIError_UnknownCoPro;
665      fpregsaddr = ((fpregsaddr & 0xffffff) << 2) + 8;	/* address in __fp_decode - 4 */
666      if ((fpregsaddr < FPESTART) || (fpregsaddr >= FPEEND))
667	return RDIError_UnknownCoPro;
668      fpregsaddr = ARMul_ReadWord (state, fpregsaddr);	/* pointer to fp registers */
669      FPRegsAddr = fpregsaddr;
670    }
671  else
672    fpregsaddr = FPRegsAddr;
673
674  if (fpregsaddr == 0)
675    return RDIError_UnknownCoPro;
676  for (upto = 0, r = 0; r < 8; r++)
677    if (mask & (1L << r))
678      {
679	ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16,
680			 buffer[upto + 1]);
681	ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16 + 4,
682			 buffer[upto + 2]);
683	ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16 + 8,
684			 buffer[upto + 3]);
685	ARMul_WriteWord (state, fpregsaddr + (ARMword) r * 16 + 12,
686			 (buffer[upto] * 2 + 1) << 29);	/* mark type */
687	upto += 4;
688      }
689  if (mask & (1L << r))
690    ARMul_WriteWord (state, fpregsaddr + 128, buffer[upto++]);	/* fpsr */
691  return (RDIError_NoError);
692#endif /* NOFPE */
693}
694
695static void
696deletebreaknode (BreakNode ** prevp)
697{
698  BreakNode *p = *prevp;
699  *prevp = p->next;
700  ARMul_WriteWord (state, p->address, p->inst);
701  free ((char *) p);
702  BreaksSet--;
703  state->CallDebug--;
704}
705
706static int
707removebreak (ARMword address, unsigned type)
708{
709  BreakNode *p, **prevp = &BreakList;
710  for (; (p = *prevp) != NULL; prevp = &p->next)
711    if (p->address == address && p->type == type)
712      {
713	deletebreaknode (prevp);
714	return TRUE;
715      }
716  return FALSE;
717}
718
719/* This routine installs a breakpoint into the breakpoint table */
720
721static BreakNode *
722installbreak (ARMword address, unsigned type, ARMword bound)
723{
724  BreakNode *p = (BreakNode *) malloc (sizeof (BreakNode));
725  p->next = BreakList;
726  BreakList = p;
727  p->address = address;
728  p->type = type;
729  p->bound = bound;
730  p->inst = ARMul_ReadWord (state, address);
731  ARMul_WriteWord (state, address, 0xee000000L);
732  return p;
733}
734
735/***************************************************************************\
736*                               RDI_setbreak                                *
737\***************************************************************************/
738
739static int
740RDI_setbreak (ARMword address, unsigned type, ARMword bound,
741	      PointHandle * handle)
742{
743  BreakNode *p;
744  TracePrint ((state, "RDI_setbreak: address=%.8lx type=%d bound=%.8lx\n",
745	       address, type, bound));
746
747  removebreak (address, type);
748  p = installbreak (address, type, bound);
749  BreaksSet++;
750  state->CallDebug++;
751  *handle = (PointHandle) p;
752  TracePrint ((state, " returns %.8lx\n", *handle));
753  return RDIError_NoError;
754}
755
756/***************************************************************************\
757*                               RDI_clearbreak                              *
758\***************************************************************************/
759
760static int
761RDI_clearbreak (PointHandle handle)
762{
763  TracePrint ((state, "RDI_clearbreak: address=%.8lx\n", handle));
764  {
765    BreakNode *p, **prevp = &BreakList;
766    for (; (p = *prevp) != NULL; prevp = &p->next)
767      if (p == (BreakNode *) handle)
768	break;
769    if (p == NULL)
770      return RDIError_NoSuchPoint;
771    deletebreaknode (prevp);
772    return RDIError_NoError;
773  }
774}
775
776/***************************************************************************\
777*            Internal functions for breakpoint table manipulation           *
778\***************************************************************************/
779
780static void
781deletewatchnode (WatchNode ** prevp)
782{
783  WatchNode *p = *prevp;
784  if (p->datatype & Watch_AnyRead)
785    state->MemReadDebug--;
786  if (p->datatype & Watch_AnyWrite)
787    state->MemWriteDebug--;
788  *prevp = p->next;
789  free ((char *) p);
790}
791
792int
793removewatch (ARMword address, unsigned type)
794{
795  WatchNode *p, **prevp = &WatchList;
796  for (; (p = *prevp) != NULL; prevp = &p->next)
797    if (p->address == address && p->type == type)
798      {				/* found a match */
799	deletewatchnode (prevp);
800	return TRUE;
801      }
802  return FALSE;			/* never found a match */
803}
804
805static WatchNode *
806installwatch (ARMword address, unsigned type, unsigned datatype,
807	      ARMword bound)
808{
809  WatchNode *p = (WatchNode *) malloc (sizeof (WatchNode));
810  p->next = WatchList;
811  WatchList = p;
812  p->address = address;
813  p->type = type;
814  p->datatype = datatype;
815  p->bound = bound;
816  return p;
817}
818
819/***************************************************************************\
820*                               RDI_setwatch                                *
821\***************************************************************************/
822
823static int
824RDI_setwatch (ARMword address, unsigned type, unsigned datatype,
825	      ARMword bound, PointHandle * handle)
826{
827  WatchNode *p;
828  TracePrint (
829	      (state,
830	       "RDI_setwatch: address=%.8lx type=%d datatype=%d bound=%.8lx",
831	       address, type, datatype, bound));
832
833  if (!state->CanWatch)
834    return RDIError_UnimplementedMessage;
835
836  removewatch (address, type);
837  p = installwatch (address, type, datatype, bound);
838  if (datatype & Watch_AnyRead)
839    state->MemReadDebug++;
840  if (datatype & Watch_AnyWrite)
841    state->MemWriteDebug++;
842  *handle = (PointHandle) p;
843  TracePrint ((state, " returns %.8lx\n", *handle));
844  return RDIError_NoError;
845}
846
847/***************************************************************************\
848*                               RDI_clearwatch                              *
849\***************************************************************************/
850
851static int
852RDI_clearwatch (PointHandle handle)
853{
854  TracePrint ((state, "RDI_clearwatch: address=%.8lx\n", handle));
855  {
856    WatchNode *p, **prevp = &WatchList;
857    for (; (p = *prevp) != NULL; prevp = &p->next)
858      if (p == (WatchNode *) handle)
859	break;
860    if (p == NULL)
861      return RDIError_NoSuchPoint;
862    deletewatchnode (prevp);
863    return RDIError_NoError;
864  }
865}
866
867/***************************************************************************\
868*                               RDI_execute                                 *
869\***************************************************************************/
870
871static int
872RDI_execute (PointHandle * handle)
873{
874  TracePrint ((state, "RDI_execute\n"));
875  if (rdi_log & 4)
876    {
877      state->CallDebug++;
878      state->Debug = TRUE;
879    }
880  state->EndCondition = RDIError_NoError;
881  state->StopHandle = 0;
882
883  ARMul_DoProg (state);
884
885  *handle = state->StopHandle;
886  state->Reg[15] -= 8;		/* undo the pipeline */
887  if (rdi_log & 4)
888    {
889      state->CallDebug--;
890      state->Debug = FALSE;
891    }
892  return (state->EndCondition);
893}
894
895/***************************************************************************\
896*                                RDI_step                                   *
897\***************************************************************************/
898
899static int
900RDI_step (unsigned ninstr, PointHandle * handle)
901{
902
903  TracePrint ((state, "RDI_step\n"));
904  if (ninstr != 1)
905    return RDIError_UnimplementedMessage;
906  if (rdi_log & 4)
907    {
908      state->CallDebug++;
909      state->Debug = TRUE;
910    }
911  state->EndCondition = RDIError_NoError;
912  state->StopHandle = 0;
913  ARMul_DoInstr (state);
914  *handle = state->StopHandle;
915  state->Reg[15] -= 8;		/* undo the pipeline */
916  if (rdi_log & 4)
917    {
918      state->CallDebug--;
919      state->Debug = FALSE;
920    }
921  return (state->EndCondition);
922}
923
924/***************************************************************************\
925*                               RDI_info                                    *
926\***************************************************************************/
927
928static int
929RDI_info (unsigned type, ARMword * arg1, ARMword * arg2)
930{
931  switch (type)
932    {
933    case RDIInfo_Target:
934      TracePrint ((state, "RDI_Info_Target\n"));
935      /* Emulator, speed 10**5 IPS */
936      *arg1 = 5 | HIGHEST_RDI_LEVEL << 5 | LOWEST_RDI_LEVEL << 8;
937      *arg2 = 1298224434;
938      return RDIError_NoError;
939
940    case RDIInfo_Points:
941      {
942	ARMword n = RDIPointCapability_Comparison | RDIPointCapability_Range |
943	  RDIPointCapability_Mask | RDIPointCapability_Status;
944	TracePrint ((state, "RDI_Info_Points\n"));
945	if (state->CanWatch)
946	  n |= (Watch_AnyRead + Watch_AnyWrite) << 2;
947	*arg1 = n;
948	return RDIError_NoError;
949      }
950
951    case RDIInfo_Step:
952      TracePrint ((state, "RDI_Info_Step\n"));
953      *arg1 = RDIStep_Single;
954      return RDIError_NoError;
955
956    case RDIInfo_MMU:
957      TracePrint ((state, "RDI_Info_MMU\n"));
958      *arg1 = 1313820229;
959      return RDIError_NoError;
960
961    case RDISignal_Stop:
962      TracePrint ((state, "RDISignal_Stop\n"));
963      state->CallDebug++;
964      state->EndCondition = RDIError_UserInterrupt;
965      return RDIError_NoError;
966
967    case RDIVector_Catch:
968      TracePrint ((state, "RDIVector_Catch %.8lx\n", *arg1));
969      state->VectorCatch = (unsigned) *arg1;
970      return RDIError_NoError;
971
972    case RDISet_Cmdline:
973      TracePrint ((state, "RDI_Set_Cmdline %s\n", (char *) arg1));
974      state->CommandLine =
975	(char *) malloc ((unsigned) strlen ((char *) arg1) + 1);
976      (void) strcpy (state->CommandLine, (char *) arg1);
977      return RDIError_NoError;
978
979    case RDICycles:
980      TracePrint ((state, "RDI_Info_Cycles\n"));
981      arg1[0] = 0;
982      arg1[1] = state->NumInstrs;
983      arg1[2] = 0;
984      arg1[3] = state->NumScycles;
985      arg1[4] = 0;
986      arg1[5] = state->NumNcycles;
987      arg1[6] = 0;
988      arg1[7] = state->NumIcycles;
989      arg1[8] = 0;
990      arg1[9] = state->NumCcycles;
991      arg1[10] = 0;
992      arg1[11] = state->NumFcycles;
993      return RDIError_NoError;
994
995    case RDIErrorP:
996      *arg1 = ARMul_OSLastErrorP (state);
997      TracePrint ((state, "RDI_ErrorP returns %ld\n", *arg1));
998      return RDIError_NoError;
999
1000    case RDIInfo_DescribeCoPro:
1001      {
1002	int cpnum = *(int *) arg1;
1003	struct Dbg_CoProDesc *cpd = (struct Dbg_CoProDesc *) arg2;
1004	int i;
1005	unsigned char const *map = state->CPRegWords[cpnum];
1006	if (map == NULL)
1007	  return RDIError_UnknownCoPro;
1008	for (i = 0; i < cpd->entries; i++)
1009	  {
1010	    unsigned r, w = cpd->regdesc[i].nbytes / sizeof (ARMword);
1011	    for (r = cpd->regdesc[i].rmin; r <= cpd->regdesc[i].rmax; r++)
1012	      if (map[r] != w)
1013		return RDIError_BadCoProState;
1014	  }
1015	return RDIError_NoError;
1016      }
1017
1018    case RDIInfo_RequestCoProDesc:
1019      {
1020	int cpnum = *(int *) arg1;
1021	struct Dbg_CoProDesc *cpd = (struct Dbg_CoProDesc *) arg2;
1022	int i = -1, lastw = -1, r;
1023	unsigned char const *map;
1024	if ((unsigned) cpnum >= 16)
1025	  return RDIError_UnknownCoPro;
1026	map = state->CPRegWords[cpnum];
1027	if (map == NULL)
1028	  return RDIError_UnknownCoPro;
1029	for (r = 0; r < map[-1]; r++)
1030	  {
1031	    int words = map[r];
1032	    if (words == lastw)
1033	      cpd->regdesc[i].rmax = r;
1034	    else
1035	      {
1036		if (++i >= cpd->entries)
1037		  return RDIError_BufferFull;
1038		cpd->regdesc[i].rmax = cpd->regdesc[i].rmin = r;
1039		cpd->regdesc[i].nbytes = words * sizeof (ARMword);
1040		cpd->regdesc[i].access =
1041		  Dbg_Access_Readable + Dbg_Access_Writable;
1042	      }
1043	  }
1044	cpd->entries = i + 1;
1045	return RDIError_NoError;
1046      }
1047
1048    case RDIInfo_Log:
1049      *arg1 = (ARMword) rdi_log;
1050      return RDIError_NoError;
1051
1052    case RDIInfo_SetLog:
1053      rdi_log = (int) *arg1;
1054      return RDIError_NoError;
1055
1056    case RDIInfo_CoPro:
1057      return RDIError_NoError;
1058
1059    case RDIPointStatus_Watch:
1060      {
1061	WatchNode *p, *handle = (WatchNode *) * arg1;
1062	for (p = WatchList; p != NULL; p = p->next)
1063	  if (p == handle)
1064	    {
1065	      *arg1 = -1;
1066	      *arg2 = 1;
1067	      return RDIError_NoError;
1068	    }
1069	return RDIError_NoSuchPoint;
1070      }
1071
1072    case RDIPointStatus_Break:
1073      {
1074	BreakNode *p, *handle = (BreakNode *) * arg1;
1075	for (p = BreakList; p != NULL; p = p->next)
1076	  if (p == handle)
1077	    {
1078	      *arg1 = -1;
1079	      *arg2 = 1;
1080	      return RDIError_NoError;
1081	    }
1082	return RDIError_NoSuchPoint;
1083      }
1084
1085    case RDISet_RDILevel:
1086      if (*arg1 < LOWEST_RDI_LEVEL || *arg1 > HIGHEST_RDI_LEVEL)
1087	return RDIError_IncompatibleRDILevels;
1088      MYrdi_level = *arg1;
1089      return RDIError_NoError;
1090
1091    default:
1092      return RDIError_UnimplementedMessage;
1093
1094    }
1095}
1096
1097/***************************************************************************\
1098* The emulator calls this routine at the beginning of every cycle when the  *
1099* CallDebug flag is set.  The second parameter passed is the address of the *
1100* currently executing instruction (i.e Program Counter - 8), the third      *
1101* parameter is the instruction being executed.                              *
1102\***************************************************************************/
1103
1104ARMword
1105ARMul_Debug (ARMul_State * state, ARMword pc, ARMword instr)
1106{
1107
1108  if (state->EndCondition == RDIError_UserInterrupt)
1109    {
1110      TracePrint ((state, "User interrupt at %.8lx\n", pc));
1111      state->CallDebug--;
1112      state->Emulate = STOP;
1113    }
1114  else
1115    {
1116      BreakNode *p = BreakList;
1117      for (; p != NULL; p = p->next)
1118	{
1119	  switch (p->type)
1120	    {
1121	    case RDIPoint_EQ:
1122	      if (pc == p->address)
1123		break;
1124	      continue;
1125	    case RDIPoint_GT:
1126	      if (pc > p->address)
1127		break;
1128	      continue;
1129	    case RDIPoint_GE:
1130	      if (pc >= p->address)
1131		break;
1132	      continue;
1133	    case RDIPoint_LT:
1134	      if (pc < p->address)
1135		break;
1136	      continue;
1137	    case RDIPoint_LE:
1138	      if (pc <= p->address)
1139		break;
1140	      continue;
1141	    case RDIPoint_IN:
1142	      if (p->address <= pc && pc < p->address + p->bound)
1143		break;
1144	      continue;
1145	    case RDIPoint_OUT:
1146	      if (p->address > pc || pc >= p->address + p->bound)
1147		break;
1148	      continue;
1149	    case RDIPoint_MASK:
1150	      if ((pc & p->bound) == p->address)
1151		break;
1152	      continue;
1153	    }
1154	  /* found a match */
1155	  TracePrint ((state, "Breakpoint reached at %.8lx\n", pc));
1156	  state->EndCondition = RDIError_BreakpointReached;
1157	  state->Emulate = STOP;
1158	  state->StopHandle = (ARMword) p;
1159	  break;
1160	}
1161    }
1162  return instr;
1163}
1164
1165void
1166ARMul_CheckWatch (ARMul_State * state, ARMword addr, int access)
1167{
1168  WatchNode *p;
1169  for (p = WatchList; p != NULL; p = p->next)
1170    if (p->datatype & access)
1171      {
1172	switch (p->type)
1173	  {
1174	  case RDIPoint_EQ:
1175	    if (addr == p->address)
1176	      break;
1177	    continue;
1178	  case RDIPoint_GT:
1179	    if (addr > p->address)
1180	      break;
1181	    continue;
1182	  case RDIPoint_GE:
1183	    if (addr >= p->address)
1184	      break;
1185	    continue;
1186	  case RDIPoint_LT:
1187	    if (addr < p->address)
1188	      break;
1189	    continue;
1190	  case RDIPoint_LE:
1191	    if (addr <= p->address)
1192	      break;
1193	    continue;
1194	  case RDIPoint_IN:
1195	    if (p->address <= addr && addr < p->address + p->bound)
1196	      break;
1197	    continue;
1198	  case RDIPoint_OUT:
1199	    if (p->address > addr || addr >= p->address + p->bound)
1200	      break;
1201	    continue;
1202	  case RDIPoint_MASK:
1203	    if ((addr & p->bound) == p->address)
1204	      break;
1205	    continue;
1206	  }
1207	/* found a match */
1208	TracePrint ((state, "Watchpoint at %.8lx accessed\n", addr));
1209	state->EndCondition = RDIError_WatchpointAccessed;
1210	state->Emulate = STOP;
1211	state->StopHandle = (ARMword) p;
1212	return;
1213      }
1214}
1215
1216static RDI_NameList const *
1217RDI_cpunames ()
1218{
1219  return (RDI_NameList const *) &processorconfig.count;
1220}
1221
1222const struct RDIProcVec armul_rdi = {
1223  "ARMUL",
1224  RDI_open,
1225  RDI_close,
1226  RDI_read,
1227  RDI_write,
1228  RDI_CPUread,
1229  RDI_CPUwrite,
1230  RDI_CPread,
1231  RDI_CPwrite,
1232  RDI_setbreak,
1233  RDI_clearbreak,
1234  RDI_setwatch,
1235  RDI_clearwatch,
1236  RDI_execute,
1237  RDI_step,
1238  RDI_info,
1239
1240  0,				/*pointinq */
1241  0,				/*addconfig */
1242  0,				/*loadconfigdata */
1243  0,				/*selectconfig */
1244  0,				/*drivernames */
1245
1246  RDI_cpunames
1247};
1248