gm4 -> m4
[deliverable/binutils-gdb.git] / gdb / remote-udi.c
CommitLineData
9bddba9a
SG
1/*
2 - Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
3 This is like remote.c but expects MiniMON to be running on the Am29000
4 target hardware.
5 - Originally written by Daniel Mann at AMD for gdb 3.91.6.
6 - David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
7 file to gdb 3.95. I was unable to get this working on sun3os4
8 with termio, only with sgtty. Because we are only attempting to
9 use this module to debug our kernel, which is already loaded when
10 gdb is started up, I did not code up the file downloading facilities.
11 As a result this module has only the stubs to download files.
12 You should get tagged at compile time if you need to make any
13 changes/additions.
14*- Daniel Mann at AMD took the 3.95 adaptions above and replaced
15 MiniMON interface with UDI-p interface.
16
17 Copyright (C) 1990 Free Software Foundation, Inc.
18
19This file is part of GDB.
20
21This program is free software; you can redistribute it and/or modify
22it under the terms of the GNU General Public License as published by
23the Free Software Foundation; either version 1, or (at your option)
24any later version.
25
26This program is distributed in the hope that it will be useful,
27but WITHOUT ANY WARRANTY; without even the implied warranty of
28MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29GNU General Public License for more details.
30
31You should have received a copy of the GNU General Public License
32along with this program; see the file COPYING. If not, write to
33the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
34
35
36#include <stdio.h>
37#include "defs.h"
38#include "inferior.h"
39#include "wait.h"
40#include "value.h"
41#include <ctype.h>
42#include <fcntl.h>
43#include <signal.h>
44#include <errno.h>
45#include <string.h>
46#include "terminal.h"
47#include "target.h"
48#include "udiproc.h"
49
50/* access the register store directly, without going through
51 the normal handler functions. This avoids an extra data copy
52*/
53
54/* #define DEBUG 1 /* */
55#ifdef DEBUG
56# define DENTER(NAME) (printf("Entering %s\n",NAME), fflush(stdout))
57# define DEXIT(NAME) (printf("Exiting %s\n",NAME), fflush(stdout))
58#else
59# define DENTER(NAME)
60# define DEXIT(NAME)
61#endif
62
63
64extern char register_valid[];
65extern int stop_soon_quietly; /* for wait_for_inferior */
66extern struct value *call_function_by_hand();
67static void udi_resume();
68static void udi_fetch_registers ();
69static void udi_load();
70static int fetch_register ();
71static void udi_store_registers ();
72static int store_register ();
73static int regnum_to_srnum();
74static void udi_close ();
75static CPUSpace udi_memory_space();
76static int udi_write_inferior_memory();
77static int udi_read_inferior_memory();
78char CoffFileName[100] = "";
79/*
80 * Processor types.
81 */
82#define TYPE_UNKNOWN 0
83#define TYPE_A29000 1
84#define TYPE_A29030 2
85#define TYPE_A29050 3
86static char *processor_name[] = { "Unknown", "Am29000", "Am29030", "Am29050" };
87static int processor_type=TYPE_UNKNOWN;
88#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
89#define USE_SHADOW_PC ((processor_type == TYPE_A29050) && FREEZE_MODE)
90
91#define LLOG_FILE "udi.log"
92#if defined (LOG_FILE)
93FILE *log_file;
94#endif
95
96static int timeout = 5;
97extern struct target_ops udi_ops; /* Forward declaration */
98
99/* Special register enumeration.
100*/
101
102/******************************************************************* UDI DATA*/
103#define MAXDATA 2*1024 /* max UDI[read/write] byte size */
104/* Descriptor for I/O to remote machine. Initialize it to -1 so that
105 udi_open knows that we don't have a file open when the program
106 starts. */
107 UDISessionId udi_session_id = -1;
108
109 CPUOffset IMemStart = 0;
110 CPUSizeT IMemSize = 0;
111 CPUOffset DMemStart = 0;
112 CPUSizeT DMemSize = 0;
113 CPUOffset RMemStart = 0;
114 CPUSizeT RMemSize = 0;
115 UDIUInt32 CPUPRL;
116 UDIUInt32 CoProcPRL;
117
118#define SBUF_MAX 1024 /* maximum size of string handling buffer */
119char sbuf[SBUF_MAX];
120
121typedef struct bkpt_entry_str
122{
123 UDIResource Addr;
124 UDIUInt32 PassCount;
125 UDIBreakType Type;
126 unsigned int BreakId;
127} bkpt_entry_t;
54847287
SG
128#define BKPT_TABLE_SIZE 40
129static bkpt_entry_t bkpt_table[BKPT_TABLE_SIZE];
9bddba9a
SG
130extern char dfe_errmsg[]; /* error string */
131
132/*********************************************************** SIGNAL SUPPORT */
133/* Called when SIGALRM signal sent due to alarm() timeout. */
134#ifndef HAVE_TERMIO
135
136#ifndef __STDC__
137# ifndef volatile
138# define volatile /**/
139# endif
140#endif
141volatile int n_alarms;
142
143static void
144udi_timer ()
145{
146#if 0
147 if (kiodebug)
148 printf ("udi_timer called\n");
149#endif
150 n_alarms++;
151}
152#endif /* HAVE_TERMIO */
153
154/* malloc'd name of the program on the remote system. */
155static char *prog_name = NULL;
156
157
158/* Number of SIGTRAPs we need to simulate. That is, the next
159 NEED_ARTIFICIAL_TRAP calls to udi_wait should just return
160 SIGTRAP without actually waiting for anything. */
161
162/******************************************************* UDI_CREATE_INFERIOR */
163/* This is called not only when we first attach, but also when the
164 user types "run" after having attached. */
165static void
166udi_create_inferior (execfile, args, env)
167 char *execfile;
168 char *args;
169 char **env;
170{
171 DENTER("udi_create_inferior()");
172
173 if (execfile)
174 { if (prog_name != NULL)
175 free (prog_name);
176 prog_name = savestring (execfile, strlen (execfile));
177 }
178
179 if (prog_name == 0 /* || exec_bfd == 0 */ )
180 error ("No exec file specified");
181
182 if (udi_session_id < 0){
183 printf("UDI connection not open yet.\n");
184 return;
185 }
186
187#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
188 /* On ultra3 (NYU) we assume the kernel is already running so there is
189 * no file to download
190 */
191#else
192 if(*args == '\0') args = prog_name;
193 udi_load(args, 0);
194#endif /* !ULTRA3 */
195
196 /* We will get a task spawn event immediately. */
197#ifdef NOTDEF /* start_remote() now does a wait without a resume
198 so don't use it*/
199 start_remote ();
200#else
201 init_wait_for_inferior ();
202 clear_proceed_status ();
203 proceed(-1,-1,0);
204#endif
205 DEXIT("udi_create_inferior()");
206}
207/******************************************************* UDI_MOURN_INFERIOR */
208static void
209udi_mourn()
210{
211 DENTER("udi_mourn()");
212 pop_target (); /* Pop back to no-child state */
213 generic_mourn_inferior ();
214 DEXIT("udi_mourn()");
215}
216
217/******************************************************************** UDI_OPEN
218** Open a connection to remote TIP.
219 NAME is the socket domain used for communication with the TIP,
220 then a space and the socket name or TIP-host name.
221 '<udi_udi_config_id> [progname]' for example.
222 */
223
224static char *udi_config_id;
225static void
226udi_open (name, from_tty)
227 char *name;
228 int from_tty;
229{
230 unsigned int prl;
231 char *p;
232 int cnt;
233 UDIMemoryRange KnownMemory[10];
234 UDIUInt32 ChipVersions[10];
235 UDIInt NumberOfRanges = 10;
236 UDIInt NumberOfChips = 10;
237 UDIPId PId;
238 UDIUInt32 TIPId, TargetId, DFEId, DFE, TIP, DFEIPCId, TIPIPCId;
239
240 DENTER("udi_open()");
241
242 /* Find the first whitespace character, it separates udi_config_id
243 from prog_name. */
244 if(!name) goto erroid;
245 for (p = name;
246 *p != '\0' && !isspace (*p); p++)
247 ;
248 if (*p == '\0')
249erroid:
250 error("Usage: target udi config_id progname, where config_id appears in udi_soc file");
251 udi_config_id = (char*)malloc (p - name + 1);
252 strncpy (udi_config_id, name, p - name);
253 udi_config_id[p - name] = '\0';
254
255 /* Skip over the whitespace after udi_config_id */
256 for (; isspace (*p); p++)
257 /*EMPTY*/;
258
259 if (prog_name != NULL)
260 free (prog_name);
261 prog_name = savestring (p, strlen (p));
262
263 if (udi_session_id >= 0)
264 close (udi_session_id);
265
266 if(UDIConnect(udi_config_id, &udi_session_id))
267 fprintf(stderr, "UDIConnect() failed: %s\n", dfe_errmsg);
268 push_target (&udi_ops);
269
270#ifndef HAVE_TERMIO
271#ifndef NO_SIGINTERRUPT
272 /* Cause SIGALRM's to make reads fail with EINTR instead of resuming
273 the read. */
274 if (siginterrupt (SIGALRM, 1) != 0)
275 perror ("udi_open: error in siginterrupt");
276#endif
277
278 /* Set up read timeout timer. */
279 if ((void (*)) signal (SIGALRM, udi_timer) == (void (*)) -1)
280 perror ("udi_open: error in signal");
281#endif
282
283#if defined (LOG_FILE)
284 log_file = fopen (LOG_FILE, "w");
285 if (log_file == NULL)
286 perror (LOG_FILE);
287#endif
288 /*
289 ** Initialize target configuration structure (global)
290 */
291 if(UDIGetTargetConfig( KnownMemory, &NumberOfRanges,
292 ChipVersions, &NumberOfChips))
293 error ("UDIGetTargetConfig() failed");
294 if(NumberOfChips > 2)
295 fprintf(stderr,"Taret has more than one processor\n");
296 for(cnt=0; cnt<NumberOfRanges; cnt++)
297 { switch(KnownMemory[cnt].Space)
298 {
299 default: fprintf(stderr, "UDIGetTargetConfig() unknown memory space\n");
300 break;
301 case UDI29KCP_S:
302 break;
303 case UDI29KIROMSpace:
304 RMemStart = KnownMemory[cnt].Offset;
305 RMemSize = KnownMemory[cnt].Size;
306 break;
307 case UDI29KIRAMSpace:
308 IMemStart = KnownMemory[cnt].Offset;
309 IMemSize = KnownMemory[cnt].Size;
310 break;
311 case UDI29KDRAMSpace:
312 DMemStart = KnownMemory[cnt].Offset;
313 DMemSize = KnownMemory[cnt].Size;
314 break;
315 }
316 }
317
318 /* Determine the processor revision level */
319 prl = (unsigned int)read_register(CFG_REGNUM) >> 24;
320 if ((prl&0xe0) == 0)
321 { fprintf_filtered(stderr,
322 "Remote debugging Am29000 rev %c\n",'A'+(prl&0x1f));
323 processor_type = TYPE_A29000;
324 } else if ((prl&0xe0) == 0x40) /* 29030 = 0x4* */
325 { fprintf_filtered(stderr,
326 "Remote debugging Am2903* rev %c\n",'A'+(prl&0x1f));
327 processor_type = TYPE_A29030;
328 } else if ((prl&0xe0) == 0x20) /* 29050 = 0x2* */
329 { fprintf_filtered(stderr,
330 "Remote debugging Am29050 rev %c\n",'A'+(prl&0x1f));
331 processor_type = TYPE_A29050;
332 } else {
333 processor_type = TYPE_UNKNOWN;
334 fprintf_filtered(stderr,"WARNING: processor type unknown.\n");
335 }
336 if(UDICreateProcess(&PId))
337 fprintf(stderr, "UDICreateProcess() failed\n");
338
339 /* Print out some stuff, letting the user now what's going on */
340 if(UDICapabilities( &TIPId, &TargetId, DFEId, DFE, &TIP, &DFEIPCId,
341 &TIPIPCId, sbuf))
342 error ("UDICapabilities() failed");
343 if (from_tty) {
344 printf_filtered("Remote debugging an %s connected via UDI socket,\n\
345 DFE-IPC version %x.%x.%x TIP-IPC version %x.%x.%x TIP version %x.%x.%x\n %s\n",
346 processor_name[processor_type],
347 (DFEIPCId>>8)&0xf, (DFEIPCId>>4)&0xf, DFEIPCId&0xf,
348 (TIPIPCId>>8)&0xf, (TIPIPCId>>4)&0xf, TIPIPCId&0xf,
349 (TargetId>>8)&0xf, (TargetId>>4)&0xf, TargetId&0xf,
350 sbuf);
351#ifdef ULTRA3
352 /* FIXME: can this restriction be removed? */
353 printf_filtered("Remote debugging using virtual addresses works only\n");
354 printf_filtered(" when virtual addresses map 1:1 to physical addresses.\n");
355#endif
356 }
357#ifdef ULTRA3
358 if (processor_type != TYPE_A29050) {
359 fprintf_filtered(stderr,
360 "Freeze-mode debugging can only be done on an Am29050,\n");
361 fprintf_filtered(stderr,
362 " unless GDB is being used with a 29K simulator.\n");
363 }
364#endif
365}
366
367/******************************************************************* UDI_CLOSE
368 Close the open connection to the TIP process.
369 Use this when you want to detach and do something else
370 with your gdb. */
371static void
372udi_close (quitting) /*FIXME: how is quitting used */
373 int quitting;
374{
375 int Terminate = -1;
376 DENTER("udi_close()");
377
378 if (udi_session_id < 0)
379 error ("Can't close udi connection: not debugging remotely.");
380
381 /* We should never get here if there isn't something valid in
382 udi_session_id.
383
384 if(UDIDisconnect(udi_stream, Terminate);)
385 error ("UDIDisconnect() failed in udi_close");
386
387 /* Do not try to close udi_session_id again, later in the program. */
388 udi_session_id = -1;
389
390#if defined (LOG_FILE)
391 if (ferror (log_file))
392 printf ("Error writing log file.\n");
393 if (fclose (log_file) != 0)
394 printf ("Error closing log file.\n");
395#endif
396
397 printf ("Ending remote debugging\n");
398
399 DEXIT("udi_close()");
400}
401
402/**************************************************************** UDI_ATACH */
403/* Attach to a program that is already loaded and running
404 * Upon exiting the process's execution is stopped.
405 */
406static void
407udi_attach (args, from_tty)
408 char *args;
409 int from_tty;
410{
411 UDIResource From;
412 UDIInt32 PC_adds;
413 UDICount Count = 1;
414 UDISizeT Size = 4;
415 UDICount CountDone;
416 UDIBool HostEndian = 0;
417 DENTER("udi_attach()");
418
419 if (udi_session_id < 0)
420 printf ("UDI connection not opened yet, use the 'target udi' command.\n");
421
422 if (from_tty)
423 printf ("Attaching to remote program %s...\n", prog_name);
424
425 mark_breakpoints_out ();
426 UDIStop();
427 From.Space = 11;
428 From.Offset = UDI29KSpecialRegs;
429 if(UDIRead(From, &PC_adds, Count, Size, &CountDone, HostEndian))
430 error ("UDIRead failed in udi_attach");
431 printf ("Remote process is now halted, pc1 = 0x%x.\n", PC_adds);
432
433 DEXIT("udi_attach()");
434}
435/************************************************************* UDI_DETACH */
436/* Terminate the open connection to the TIP process.
437 Use this when you want to detach and do something else
438 with your gdb. Leave remote process running (with no breakpoints set). */
439static void
440udi_detach (args,from_tty)
441 char *args;
442 int from_tty;
443{
444 DENTER("udi_dettach()");
445 remove_breakpoints(); /* Just in case there were any left in */
446 if(UDIDisconnect(udi_session_id))
447 error ("UDIDisconnect() failed in udi_detach");
448 pop_target(); /* calls udi_close to do the real work */
449 if (from_tty)
450 printf ("Ending remote debugging\n");
451 DEXIT("udi_dettach()");
452}
453
454
455/****************************************************************** UDI_RESUME
456** Tell the remote machine to resume. */
457
458static void
459udi_resume (step, sig)
460 int step, sig;
461{
462 UDIError tip_error;
463 UDIUInt32 Steps = 1;
464 UDIStepType StepType = UDIStepNatural;
465 UDIRange Range;
466 DENTER("udi_resume()");
467 if (step) /* step 1 instruction */
468 { tip_error = tip_error = UDIStep(Steps, StepType, Range);
469 if(tip_error)fprintf(stderr, "UDIStep() error = %d\n", tip_error);
470 if(tip_error)error ("failed in udi_resume");
471
472 }
473 else
474 { if(UDIExecute())
475 error ("UDIExecute() failed in udi_resume");
476 }
477
478 DEXIT("udi_resume()");
479}
480
481/******************************************************************** UDI_WAIT
482** Wait until the remote machine stops, then return,
483 storing status in STATUS just as `wait' would. */
484
485static int
486udi_wait (status)
487 WAITTYPE *status;
488{
489 UDIInt32 MaxTime;
490 UDIPId PId;
491 UDIInt32 StopReason;
492 UDISizeT CountDone;
493 int old_timeout = timeout;
494 int old_immediate_quit = immediate_quit;
495 int i;
496
497 DENTER("udi_wait()");
498 WSETEXIT ((*status), 0);
499
500/* wait for message to arrive. It should be:
501 If the target stops executing, udi_wait() should return.
502*/
503 timeout = 0; /* Wait indefinetly for a message */
504 immediate_quit = 1; /* Helps ability to QUIT */
505 while(1)
506 {
507 i = 0;
508 MaxTime = UDIWaitForever;
509 UDIWait(MaxTime, &PId, &StopReason);
510 QUIT; /* Let user quit if they want */
511 switch (StopReason & 0xff)
512 {
513 default:
514 goto halted;
515 case UDIStdoutReady:
516 if(UDIGetStdout(sbuf, (UDISizeT)SBUF_MAX, &CountDone))
517 error("UDIGetStdin() failed in udi_wait");
518 while(CountDone--)putc(sbuf[i++], stdout);
519 fflush(stdout);
520 break;
521 case UDIStderrReady:
522 UDIGetStderr(sbuf, (UDISizeT)SBUF_MAX, &CountDone);
523 while(CountDone--)putc(sbuf[i++], stderr);
524 fflush(stderr);
525 fflush(stderr);
526 break;
527 case UDIStdinNeeded:
528 printf("DEBUG: stdin requested ... continue\n");
529/* UDIPutStdin(sbuf, (UDISizeT)i, &CountDone); */
530 break;
531 case UDIStdinModeX:
532 break;
533 }
534 continue;
535 }
536halted:
537 if (StopReason & 0xff == UDITrapped ) /* lower 8-bits == 0 */
538 {
539 if (StopReason >> 24 == 0)
540 { printf("Am290*0 received vector number 0 (break point)\n");
541 WSETSTOP ((*status), SIGTRAP);
542 }
543 else if (StopReason >> 24 == 1)
544 { printf("Am290*0 received vector 1\n");
545 WSETSTOP ((*status), SIGBUS);
546 }
547 else if (StopReason >> 24 == 3
548 || StopReason >> 24 == 4)
549 { printf("Am290*0 received vector number %d\n",
550 StopReason >> 24);
551 WSETSTOP ((*status), SIGFPE);
552 }
553 else if (StopReason >> 24 == 5)
554 { printf("Am290*0 received vector number %d\n",
555 StopReason >> 24);
556 WSETSTOP ((*status), SIGILL);
557 }
558 else if (StopReason >> 24 >= 6
559 && StopReason >> 24 <= 11)
560 { printf("Am290*0 received vector number %d\n",
561 StopReason >> 24);
562 WSETSTOP ((*status), SIGSEGV);
563 }
564 else if (StopReason >> 24 == 12
565 || StopReason >> 24 == 13)
566 { printf("Am290*0 received vector number %d\n",
567 StopReason >> 24);
568 WSETSTOP ((*status), SIGILL);
569 }
570 else if ((StopReason & 0xff) == 14)
571 { printf("Am290*0 received vector number %d\n",
572 StopReason >> 24);
573 WSETSTOP ((*status), SIGALRM);
574 }
575 else if ((StopReason & 0xff) == 15)
576 WSETSTOP ((*status), SIGTRAP);
577 else if ((StopReason >> 24) >= 16
578 && (StopReason >> 24) <= 21)
579 { printf("Am290*0 received vector number %d\n",
580 StopReason >> 24);
581 WSETSTOP ((*status), SIGINT);
582 }
583 else if ((StopReason & 0xff) == 22)
584 { printf("Am290*0 received vector number %d\n",
585 StopReason >> 24);
586 WSETSTOP ((*status), SIGILL);
587 }
588 else if ((StopReason & 0xff) == 77)
589 WSETSTOP ((*status), SIGTRAP);
590 else
591exit:
592 WSETEXIT ((*status), 0);
593 }
594 else if ((StopReason & 0xff) == UDIBreak)
595 WSETSTOP ((*status), SIGTRAP);
596 else if ((StopReason & 0xff) == UDINotExecuting)
597 WSETSTOP ((*status), SIGTERM);
598 else if ((StopReason & 0xff) == UDIRunning)
599 WSETSTOP ((*status), SIGILL);
600 else if ((StopReason & 0xff) == UDIStopped)
601 WSETSTOP ((*status), SIGTSTP);
602 else if ((StopReason & 0xff) == UDIWarned)
603 WSETSTOP ((*status), SIGLOST);
604 else if ((StopReason & 0xff) == UDIStepped)
605 WSETSTOP ((*status), SIGTRAP);
606 else if ((StopReason & 0xff) == UDIWaiting)
607 WSETSTOP ((*status), SIGSTOP);
608 else if ((StopReason & 0xff) == UDIHalted)
609 WSETSTOP ((*status), SIGKILL);
610 else
611 WSETEXIT ((*status), 0);
612
613 timeout = old_timeout; /* Restore original timeout value */
614 immediate_quit = old_immediate_quit;
615 DEXIT("udi_wait()");
616 return 0;
617}
618
619/********************************************************** UDI_FETCH_REGISTERS
620 * Read a remote register 'regno'.
621 * If regno==-1 then read all the registers.
622 */
623static void
624udi_fetch_registers (regno)
625int regno;
626{
627 UDIResource From;
628 UDIUInt32 *To;
629 UDICount Count;
630 UDISizeT Size = 4;
631 UDICount CountDone;
632 UDIBool HostEndian = 0;
633 int i;
634
635 if (regno >= 0) {
636 fetch_register(regno);
637 return;
638 }
639 DENTER("udi_fetch_registers()");
640
641/* Gr1/rsp */
642 From.Space = UDI29KGlobalRegs;
643 From.Offset = 1;
644 To = (UDIUInt32*)&registers[4 * GR1_REGNUM];
645 Count = 1;
646 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
647 error("UDIRead() failed in udi_fetch_registers");
648 else register_valid[4 * GR1_REGNUM] = 1;
649
650#if defined(GR64_REGNUM) /* Read gr64-127 */
651/* Global Registers gr64-gr95 */
652 From.Space = UDI29KGlobalRegs;
653 From.Offset = 64;
654 To = &registers[4 * GR64_REGNUM];
655 Count = 32;
656 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
657 error("UDIRead() failed in udi_fetch_registers");
658 else for(i = 4 * GR64_REGNUM; i < 4*GR64_REGNUM + 32; i++)
659#endif /* GR64_REGNUM */
660
661/* Global Registers gr96-gr127 */
662 From.Space = UDI29KGlobalRegs;
663 From.Offset = 64;
664 To = (UDIUInt32*)&registers[4 * GR96_REGNUM];
665 Count = 32;
666 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
667 error("UDIRead() failed in udi_fetch_registers");
668 else for(i = 4 * GR96_REGNUM; i < 4*GR96_REGNUM + 32; i++)
669 register_valid[i] = 1;
670
671/* Local Registers */
672 From.Space = UDI29KLocalRegs;
673 From.Offset = 0;
674 To = (UDIUInt32*)&registers[4 * LR0_REGNUM];
675 Count = 128;
676 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
677 error("UDIRead() failed in udi_fetch_registers");
678 else for(i = 4 * LR0_REGNUM; i < 4*LR0_REGNUM + 128; i++)
679 register_valid[i] = 1;
680
681/* Protected Special Registers */
682 From.Space = UDI29KSpecialRegs;
683 From.Offset = 0;
684 To = (UDIUInt32*)&registers[4 * SR_REGNUM(0)];
685 Count = 15;
686 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
687 error("UDIRead() failed in udi_fetch_registers");
688 else for(i = 4 * SR_REGNUM(0); i < 4*SR_REGNUM(0) + 15; i++)
689 register_valid[i] = 1;
690
691 if (USE_SHADOW_PC) { /* Let regno_to_srnum() handle the register number */
692 fetch_register(NPC_REGNUM);
693 fetch_register(PC_REGNUM);
694 fetch_register(PC2_REGNUM);
695 }
696
697/* Unprotected Special Registers sr128-sr135*/
698 if (USE_SHADOW_PC) /* Let regno_to_srnum() handle the register number */
699 { From.Space = UDI29KSpecialRegs;
700 From.Offset = 128;
701 To = (UDIUInt32*)&registers[4 * SR_REGNUM(128)];
702 Count = 135-128 +1;
703 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
704 error("UDIRead() failed in udi_fetch_registers");
705 else for(i = 4 * SR_REGNUM(128); i < 4*SR_REGNUM(128) + 135-128+1; i++)
706 register_valid[i] = 1;
707 }
708
709 /* There doesn't seem to be any way to get these. */
710 {
711 int val = -1;
712 supply_register (FPE_REGNUM, (char *) &val);
713 supply_register (INT_REGNUM, (char *) &val);
714 supply_register (FPS_REGNUM, (char *) &val);
715 supply_register (EXO_REGNUM, (char *) &val);
716 }
717
718 DEXIT("udi_fetch_registerS()");
719}
720
721
722/********************************************************* UDI_STORE_REGISTERS
723** Store register regno into the target.
724 * If regno==-1 then store all the registers.
725 */
726
727static void
728udi_store_registers (regno)
729int regno;
730{
731 UDIUInt32 *From;
732 UDIResource To;
733 UDICount Count;
734 UDISizeT Size = 4;
735 UDICount CountDone;
736 UDIBool HostEndian = 0;
737
738 if (regno >= 0)
739 {
740 store_register(regno);
741 return;
742 }
743
744 DENTER("udi_store_registers()");
745
746/* Gr1/rsp */
747 From = (UDIUInt32*)&registers[4 * GR1_REGNUM];
748 To.Space = UDI29KGlobalRegs;
749 To.Offset = 1;
750 Count = 1;
751 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
752 error("UDIWrite() failed in udi_store_regisetrs");
753
754#if defined(GR64_REGNUM)
755/* Global registers gr64-gr95 */
756 From = (UDIUInt32*)&registers[4 * GR64_REGNUM];
757 To.Space = UDI29KGlobalRegs;
758 To.Offset = 64;
759 Count = 32;
760 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
761 error("UDIWrite() failed in udi_store_regisetrs");
762#endif /* GR64_REGNUM */
763
764/* Global registers gr96-gr127 */
765 From = (UDIUInt32*)&registers[4 * GR96_REGNUM];
766 To.Space = UDI29KGlobalRegs;
767 To.Offset = 96;
768 Count = 32;
769 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
770 error("UDIWrite() failed in udi_store_regisetrs");
771
772/* Local Registers */
773 From = (UDIUInt32*)&registers[4 * LR0_REGNUM];
774 To.Space = UDI29KLocalRegs;
775 To.Offset = 0;
776 Count = 128;
777 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
778 error("UDIWrite() failed in udi_store_regisetrs");
779
780
781/* Protected Special Registers */ /* VAB through TMR */
782 From = (UDIUInt32*)&registers[4 * SR_REGNUM(0)];
783 To.Space = UDI29KSpecialRegs;
784 To.Offset = 0;
785 Count = 10;
786 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
787 error("UDIWrite() failed in udi_store_regisetrs");
788
789 /* PC0, PC1, PC2 possibly as shadow registers */
790 From = (UDIUInt32*)&registers[4 * SR_REGNUM(10)];
791 To.Space = UDI29KSpecialRegs;
792 Count = 3;
793 if (USE_SHADOW_PC)
794 To.Offset = 20; /* SPC0 */
795 else
796 To.Offset = 10; /* PC0 */
797 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
798 error("UDIWrite() failed in udi_store_regisetrs");
799
800 /* LRU and MMU */
801 From = (UDIUInt32*)&registers[4 * SR_REGNUM(13)];
802 To.Space = UDI29KSpecialRegs;
803 To.Offset = 13;
804 Count = 2;
805 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
806 error("UDIWrite() failed in udi_store_regisetrs");
807
808/* Unprotected Special Registers */
809 From = (UDIUInt32*)&registers[4 * SR_REGNUM(128)];
810 To.Space = UDI29KSpecialRegs;
811 To.Offset = 128;
812 Count = 135-128 +1;
813 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
814 error("UDIWrite() failed in udi_store_regisetrs");
815
816 registers_changed ();
817 DEXIT("udi_store_registers() failed in udi_store_regisetrs");
818}
819
820/****************************************************** UDI_PREPARE_TO_STORE */
821/* Get ready to modify the registers array. On machines which store
822 individual registers, this doesn't need to do anything. On machines
823 which store all the registers in one fell swoop, this makes sure
824 that registers contains all the registers from the program being
825 debugged. */
826
827static void
828udi_prepare_to_store ()
829{
830 /* Do nothing, since we can store individual regs */
831}
832
833/********************************************************** TRANSLATE_ADDR */
834static CORE_ADDR
835translate_addr(addr)
836CORE_ADDR addr;
837{
838#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
839 /* Check for a virtual address in the kernel */
840 /* Assume physical address of ublock is in paddr_u register */
841 /* FIXME: doesn't work for user virtual addresses */
842 if (addr >= UVADDR) {
843 /* PADDR_U register holds the physical address of the ublock */
844 CORE_ADDR i = (CORE_ADDR)read_register(PADDR_U_REGNUM);
845 return(i + addr - (CORE_ADDR)UVADDR);
846 } else {
847 return(addr);
848 }
849#else
850 return(addr);
851#endif
852}
853/************************************************* UDI_XFER_INFERIOR_MEMORY */
854/* FIXME! Merge these two. */
855static int
856udi_xfer_inferior_memory (memaddr, myaddr, len, write)
857 CORE_ADDR memaddr;
858 char *myaddr;
859 int len;
860 int write;
861{
862
863 memaddr = translate_addr(memaddr);
864
865 if (write)
866 return udi_write_inferior_memory (memaddr, myaddr, len);
867 else
868 return udi_read_inferior_memory (memaddr, myaddr, len);
869}
870
871/********************************************************** UDI_FILES_INFO */
872static void
873udi_files_info ()
874{
875 printf ("\tAttached to UDI socket to %s and running program %s.\n",
876 udi_config_id, prog_name);
877}
878
879/**************************************************** UDI_INSERT_BREAKPOINT */
880static int
881udi_insert_breakpoint (addr, contents_cache)
882 CORE_ADDR addr;
883 char *contents_cache;
884{
54847287
SG
885 int cnt;
886 UDIError err;
887
888 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
889 if (bkpt_table[cnt].Type == 0) /* Find first free slot */
890 break;
891
892 if(cnt >= BKPT_TABLE_SIZE)
893 error("Too many breakpoints set");
9bddba9a 894
9bddba9a
SG
895 bkpt_table[cnt].Addr.Offset = addr;
896 bkpt_table[cnt].Addr.Space = UDI29KIRAMSpace;
897 bkpt_table[cnt].PassCount = 1;
898 bkpt_table[cnt].Type = UDIBreakFlagExecute;
899
54847287
SG
900 err = UDISetBreakpoint(bkpt_table[cnt].Addr,
901 bkpt_table[cnt].PassCount,
902 bkpt_table[cnt].Type,
903 &bkpt_table[cnt].BreakId);
904
905 if (err == 0) return 0; /* Success */
906
907 bkpt_table[cnt].Type = 0;
908 error("UDISetBreakpoint returned error code %d\n", err);
9bddba9a
SG
909}
910
911/**************************************************** UDI_REMOVE_BREAKPOINT */
912static int
913udi_remove_breakpoint (addr, contents_cache)
914 CORE_ADDR addr;
915 char *contents_cache;
916{
54847287
SG
917 int cnt;
918 UDIError err;
919
920 for (cnt = 0; cnt < BKPT_TABLE_SIZE; cnt++)
921 if (bkpt_table[cnt].Addr.Offset == addr) /* Find matching breakpoint */
922 break;
923
924 if(cnt >= BKPT_TABLE_SIZE)
925 error("Can't find breakpoint in table");
926
9bddba9a
SG
927 bkpt_table[cnt].Type = 0;
928
54847287
SG
929 err = UDIClearBreakpoint(bkpt_table[cnt].BreakId);
930 if (err == 0) return 0; /* Success */
9bddba9a 931
54847287
SG
932 error("UDIClearBreakpoint returned error code %d\n", err);
933}
9bddba9a
SG
934
935/***************************************************************** UDI_KILL */
936static void
937udi_kill(arg,from_tty)
938char *arg;
939int from_tty;
940{
941 char buf[4];
942
943 DENTER("udi_kill()");
944#if defined(ULTRA3) && defined(KERNEL_DEBUGGING)
945 /* We don't ever kill the kernel */
946 if (from_tty) {
947 printf("Kernel not killed, but left in current state.\n");
948 printf("Use detach to leave kernel running.\n");
949 }
950#else
951 UDIStop();
952 if (from_tty) {
953 printf("Target has been stopped.");
954 }
955 pop_target();
956#endif
957 DEXIT("udi_kill()");
958}
959
960
961
962/***************************************************************** UDI_LOAD */
963/*
964 * Load a program into the target.
965 */
966static void
967udi_load(arg_string,from_tty)
968char *arg_string;
969int from_tty;
970{
971#define MAX_TOKENS 25
972#define BUFFER_SIZE 256
973 int token_count;
974 char *token[MAX_TOKENS];
975 char cmd_line[BUFFER_SIZE];
976
977 dont_repeat ();
978
979#if defined(KERNEL_DEBUGGING) && defined(ULTRA3)
980 printf("The kernel had better be loaded already! Loading not done.\n");
981#else
982 if (arg_string == 0)
983 error ("The load command takes a file name");
984 arg_string = tilde_expand (arg_string);
985 sprintf(cmd_line,"y %s %s", prog_name, arg_string);
986
987 token_count = 0;
988 token[0] = cmd_line;
989
990 if (cmd_line[0] != '\0')
991 { token[token_count] = strtok(cmd_line, " \t,;\n\r");
992
993 if (token[token_count] != NULL)
994 { do {
995 token_count = token_count + 1;
996 token[token_count] = strtok((char *) NULL, " \t,;\n\r");
997 } while ((token[token_count] != NULL) &&
998 (token_count < MAX_TOKENS));
999 }
1000 else
1001 *token[0] = '\0';
1002 }
1003 make_cleanup (free, arg_string);
1004 QUIT;
1005 immediate_quit++;
1006 if(yank_cmd(token, token_count))
1007 error("Failure when tring to load program");
1008 immediate_quit--;
1009 symbol_file_add (arg_string, from_tty, 0, 0, 0, 0);/*DEBUG need to add text_addr */
1010#endif
1011
1012}
1013
1014/*************************************************** UDI_WRITE_INFERIOR_MEMORY
1015** Copy LEN bytes of data from debugger memory at MYADDR
1016 to inferior's memory at MEMADDR. Returns number of bytes written. */
1017static int
1018udi_write_inferior_memory (memaddr, myaddr, len)
1019 CORE_ADDR memaddr;
1020 char *myaddr;
1021 int len;
1022{
1023 int nwritten = 0;
1024 UDIUInt32 *From;
1025 UDIResource To;
1026 UDICount Count;
1027 UDISizeT Size = 1;
1028 UDICount CountDone = 0;
1029 UDIBool HostEndian = 0;
1030
1031
1032 /* DENTER("udi_write_inferior_memory()"); */
1033 To.Space = udi_memory_space(memaddr);
1034 From = (UDIUInt32*)myaddr;
1035
1036 while (nwritten < len)
1037 { Count = len - nwritten;
1038 if (Count > MAXDATA) Count = MAXDATA;
1039 To.Offset = memaddr + nwritten;
1040 if(UDIWrite(From, To, Count, Size, &CountDone, HostEndian))
1041 { error("UDIWrite() failed in udi_write_inferrior_memory");
1042 break;
1043 }
1044 else
1045 { nwritten += CountDone;
1046 From += CountDone;
1047 }
1048 }
1049 /* DEXIT("udi_write_inferior_memory()"); */
1050 return(nwritten);
1051}
1052
1053/**************************************************** UDI_READ_INFERIOR_MEMORY
1054** Read LEN bytes from inferior memory at MEMADDR. Put the result
1055 at debugger address MYADDR. Returns number of bytes read. */
1056static int
1057udi_read_inferior_memory(memaddr, myaddr, len)
1058 CORE_ADDR memaddr;
1059 char *myaddr;
1060 int len;
1061{
1062 int nread = 0;
1063 UDIResource From;
1064 UDIUInt32 *To;
1065 UDICount Count;
1066 UDISizeT Size = 1;
1067 UDICount CountDone = 0;
1068 UDIBool HostEndian = 0;
1069
1070
1071 /* DENTER("udi_read_inferior_memory()"); */
1072 From.Space = udi_memory_space(memaddr);
1073 To = (UDIUInt32*)myaddr;
1074
1075 while (nread < len)
1076 { Count = len - nread;
1077 if (Count > MAXDATA) Count = MAXDATA;
1078 From.Offset = memaddr + nread;
1079 if(UDIRead(From, To, Count, Size, &CountDone, HostEndian))
1080 { error("UDIWrite() failed in udi_read_inferrior_memory");
1081 break;
1082 }
1083 else
1084 { nread += CountDone;
1085 To += CountDone;
1086 }
1087 }
1088 return(nread);
1089}
1090
1091/********************************************************************* WARNING
1092*/
1093udi_warning(num)
1094int num;
1095{
1096 error ("ERROR while loading program into remote TIP: $d\n", num);
1097}
1098
1099
1100/*****************************************************************************/
1101/* Fetch a single register indicatated by 'regno'.
1102 * Returns 0/-1 on success/failure.
1103 */
1104static int
1105fetch_register (regno)
1106 int regno;
1107{
1108 UDIResource From;
1109 UDIUInt32 To;
1110 UDICount Count = 1;
1111 UDISizeT Size = 4;
1112 UDICount CountDone;
1113 UDIBool HostEndian = 0;
1114 int result;
1115
1116 DENTER("udi_fetch_register()");
1117
1118 if (regno == GR1_REGNUM)
1119 { From.Space = UDI29KGlobalRegs;
1120 From.Offset = 1;
1121 result = UDIRead(From, &To, Count, Size, &CountDone, HostEndian);
1122 }
1123 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1124 { From.Space = UDI29KGlobalRegs;
1125 From.Offset = (regno - GR96_REGNUM) + 96;;
1126 result = UDIRead(From, &To, Count, Size, &CountDone, HostEndian);
1127 }
1128#if defined(GR64_REGNUM)
1129 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1130 { From.Space = UDI29KGlobalRegs;
1131 From.Offset = (regno - GR64_REGNUM) + 64;
1132 result = UDIRead(From, &To, Count, Size, &CountDone, HostEndian);
1133 }
1134#endif /* GR64_REGNUM */
1135 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1136 { From.Space = UDI29KLocalRegs;
1137 From.Offset = (regno - LR0_REGNUM);
1138 result = UDIRead(From, &To, Count, Size, &CountDone, HostEndian);
1139 }
1140 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1141 { int val = -1;
1142 supply_register(160 + (regno - FPE_REGNUM),(char *) &val);
1143 return 0; /* Pretend Success */
1144 }
1145 else
1146 { From.Space = UDI29KSpecialRegs;
1147 From.Offset = regnum_to_srnum(regno);
1148 result = UDIRead(From, &To, Count, Size, &CountDone, HostEndian);
1149 }
1150 DEXIT("udi_fetch_register()");
1151 if(result)
1152 { result = -1;
1153 error("UDIRead() failed in udi_fetch_registers");
1154 }
1155 supply_register(regno, (char *) &To);
1156 return result;
1157}
1158/*****************************************************************************/
1159/* Store a single register indicated by 'regno'.
1160 * Returns 0/-1 on success/failure.
1161 */
1162static int
1163store_register (regno)
1164 int regno;
1165{
1166 int result;
1167 UDIUInt32 From;
1168 UDIResource To;
1169 UDICount Count = 1;
1170 UDISizeT Size = 4;
1171 UDICount CountDone;
1172 UDIBool HostEndian = 0;
1173
1174 DENTER("store_register()");
1175 From = read_register (regno); /* get data value */
1176
1177 if (regno == GR1_REGNUM)
1178 { To.Space = UDI29KGlobalRegs;
1179 To.Offset = 1;
1180 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1181 /* Setting GR1 changes the numbers of all the locals, so invalidate the
1182 * register cache. Do this *after* calling read_register, because we want
1183 * read_register to return the value that write_register has just stuffed
1184 * into the registers array, not the value of the register fetched from
1185 * the inferior.
1186 */
1187 registers_changed ();
1188 }
1189#if defined(GR64_REGNUM)
1190 else if (regno >= GR64_REGNUM && regno < GR64_REGNUM + 32 )
1191 { To.Space = UDI29KGlobalRegs;
1192 To.Offset = (regno - GR64_REGNUM) + 64;
1193 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1194 }
1195#endif /* GR64_REGNUM */
1196 else if (regno >= GR96_REGNUM && regno < GR96_REGNUM + 32)
1197 { To.Space = UDI29KGlobalRegs;
1198 To.Offset = (regno - GR96_REGNUM) + 96;
1199 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1200 }
1201 else if (regno >= LR0_REGNUM && regno < LR0_REGNUM + 128)
1202 { To.Space = UDI29KLocalRegs;
1203 To.Offset = (regno - LR0_REGNUM);
1204 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1205 }
1206 else if (regno>=FPE_REGNUM && regno<=EXO_REGNUM)
1207 {
1208 return 0; /* Pretend Success */
1209 }
1210 else /* An unprotected or protected special register */
1211 { To.Space = UDI29KSpecialRegs;
1212 To.Offset = regnum_to_srnum(regno);
1213 result = UDIWrite(&From, To, Count, Size, &CountDone, HostEndian);
1214 }
1215
1216 DEXIT("store_register()");
1217 if(result)
1218 { result = -1;
1219 error("UDIWrite() failed in store_registers");
1220 }
1221 return result;
1222}
1223/********************************************************** REGNUM_TO_SRNUM */
1224/*
1225 * Convert a gdb special register number to a 29000 special register number.
1226 */
1227static int
1228regnum_to_srnum(regno)
1229int regno;
1230{
1231 switch(regno) {
1232 case VAB_REGNUM: return(0);
1233 case OPS_REGNUM: return(1);
1234 case CPS_REGNUM: return(2);
1235 case CFG_REGNUM: return(3);
1236 case CHA_REGNUM: return(4);
1237 case CHD_REGNUM: return(5);
1238 case CHC_REGNUM: return(6);
1239 case RBP_REGNUM: return(7);
1240 case TMC_REGNUM: return(8);
1241 case TMR_REGNUM: return(9);
1242 case NPC_REGNUM: return(USE_SHADOW_PC ? (20) : (10));
1243 case PC_REGNUM: return(USE_SHADOW_PC ? (21) : (11));
1244 case PC2_REGNUM: return(USE_SHADOW_PC ? (22) : (12));
1245 case MMU_REGNUM: return(13);
1246 case LRU_REGNUM: return(14);
1247 case IPC_REGNUM: return(128);
1248 case IPA_REGNUM: return(129);
1249 case IPB_REGNUM: return(130);
1250 case Q_REGNUM: return(131);
1251 case ALU_REGNUM: return(132);
1252 case BP_REGNUM: return(133);
1253 case FC_REGNUM: return(134);
1254 case CR_REGNUM: return(135);
1255 case FPE_REGNUM: return(160);
1256 case INT_REGNUM: return(161);
1257 case FPS_REGNUM: return(162);
1258 case EXO_REGNUM:return(164);
1259 default:
1260 return(255); /* Failure ? */
1261 }
1262}
1263/****************************************************************************/
1264/*
1265 * Determine the Target memory space qualifier based on the addr.
1266 * FIXME: Can't distinguis I_ROM/D_ROM.
1267 * FIXME: Doesn't know anything about I_CACHE/D_CACHE.
1268 */
1269static CPUSpace
1270udi_memory_space(addr)
1271CORE_ADDR *addr;
1272{
1273 UDIUInt32 tstart = IMemStart;
1274 UDIUInt32 tend = tstart + IMemSize;
1275 UDIUInt32 dstart = DMemStart;
1276 UDIUInt32 dend = tstart + DMemSize;
1277 UDIUInt32 rstart = RMemStart;
1278 UDIUInt32 rend = tstart + RMemSize;
1279
1280 if (((UDIUInt32)addr >= tstart) && ((UDIUInt32)addr < tend)) {
1281 return UDI29KIRAMSpace;
1282 } else if (((UDIUInt32)addr >= dstart) && ((UDIUInt32)addr < dend)) {
1283 return UDI29KDRAMSpace;
1284 } else if (((UDIUInt32)addr >= rstart) && ((UDIUInt32)addr < rend)) {
1285 /* FIXME: how do we determine between D_ROM and I_ROM */
1286 return UDI29KIROMSpace;
1287 } else /* FIXME: what do me do now? */
1288 return UDI29KDRAMSpace; /* Hmmm! */
1289}
1290/*********************************************************************** STUBS
1291*/
1292
1293void convert16() {;}
1294void convert32() {;}
1295FILE* EchoFile = 0; /* used for debugging */
1296int QuietMode = 0; /* used for debugging */
1297
1298/****************************************************************************/
1299/*
1300 * Define the target subroutine names
1301 */
1302static struct target_ops udi_ops = {
1303 "udi", "Remote UDI connected TIP",
1304 "Remote debug an Am290*0 using socket connection to TIP process ",
1305 udi_open, udi_close,
1306 udi_attach, udi_detach, udi_resume, udi_wait,
1307 udi_fetch_registers, udi_store_registers,
1308 udi_prepare_to_store, 0, 0, /* conv_to, conv_from */
1309 udi_xfer_inferior_memory,
1310 udi_files_info,
1311 udi_insert_breakpoint, udi_remove_breakpoint, /* Breakpoints */
1312 0, 0, 0, 0, 0, /* Terminal handling */
1313 udi_kill, /* FIXME, kill */
1314 udi_load,
1315 0, /* lookup_symbol */
1316 udi_create_inferior, /* create_inferior */
1317 udi_mourn, /* mourn_inferior FIXME */
1318 process_stratum, 0, /* next */
1319 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1320 0, 0, /* Section pointers */
1321 OPS_MAGIC, /* Always the last thing */
1322};
1323
1324void _initialize_remote_udi()
1325{
1326 add_target (&udi_ops);
1327}
1328
1329#ifdef NO_HIF_SUPPORT
1330service_HIF(msg)
1331union msg_t *msg;
1332{
1333 return(0); /* Emulate a failure */
1334}
1335#endif
This page took 0.070595 seconds and 4 git commands to generate.