* Makefile.in configure configure.in: Remove ENABLE_CLIBS,
[external/binutils.git] / gdb / v850ice.c
1 /* ICE interface for the NEC V850 for GDB, the GNU debugger.
2    Copyright 1996, Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #include "defs.h"
21 #include "gdb_string.h"
22 #if 0
23 #include "frame.h"
24 #endif
25 #include "inferior.h"
26 #if 0
27 #include "bfd.h"
28 #endif
29 #include "symfile.h"
30 #include "target.h"
31 #if 0
32 #include "wait.h"
33 #include "gdbcmd.h"
34 #include "objfiles.h"
35 #include "gdb-stabs.h"
36 #include "gdbthread.h"
37 #endif
38
39 /* Prototypes for local functions */
40
41 static void v850ice_files_info PARAMS ((struct target_ops *ignore));
42
43 static int v850ice_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
44                                         int len, int should_write,
45                                         struct target_ops *target));
46
47 static void v850ice_prepare_to_store PARAMS ((void));
48
49 static void v850ice_fetch_registers PARAMS ((int regno));
50
51 static void v850ice_resume PARAMS ((int pid, int step,
52                                    enum target_signal siggnal));
53
54 static void v850ice_open PARAMS ((char *name, int from_tty));
55
56 static void v850ice_close PARAMS ((int quitting));
57
58 static void v850ice_store_registers PARAMS ((int regno));
59
60 static void v850ice_mourn PARAMS ((void));
61
62 static int v850ice_wait PARAMS ((int pid, struct target_waitstatus *status));
63
64 static void v850ice_kill PARAMS ((void));
65
66 static void v850ice_detach PARAMS ((char *args, int from_tty));
67
68 static int v850ice_insert_breakpoint PARAMS ((CORE_ADDR, char *));
69
70 static int v850ice_remove_breakpoint PARAMS ((CORE_ADDR, char *));
71
72 static int ice_open = 0;
73
74 #ifndef EXPORT
75 #define EXPORT __declspec(dllexport)
76 #endif
77
78 EXPORT long __stdcall ExeAppReq (char *, long, char *, char *);
79
80 #define MREADREG          0x0001
81 #define MWRITEREG         0x0002
82 #define MREADMEM          0x0003
83 #define MWRITEMEM         0x0004
84 #define MSINGLESTEP       0x0005
85 #define MRESUME           0x0006
86 #define MLOADPROGRAM      0x0007
87 #define MSETBREAK         0x0008
88 #define MREMOVEBREAK      0x0009
89 #define MQUIT             0x000A
90 #define MTERMINATE        0x000B
91 #define MATTACH           0x000C
92 #define MCHECKSTATUS      0x000D
93 #define MHALT             0x000E
94 #define MDIRECTCMD        0x000F
95 #define MSYMADR           0x0010
96 #define MGETTASKLIST      0x0011
97 #define MREADVECREG       0x0012
98 #define MWRITEVECREG      0x0013
99 #define MGETCHANGEDREGS   0x0014
100 #define MGETSERVERINFO    0x0015
101 #define MREADBLOCK        0x0016
102 #define MSETHARDBRK       0x0017
103 #define MREMOVEHARDBRK    0x0018
104 #define MCOPYBLOCK        0x0019
105 #define MBLOCKFILL        0x001A
106 #define MFINDBLOCK        0x001B
107 #define MCOMPAREBLOCK     0x001C
108 #define MREFRESH          0x001D
109 #define MSPECIAL          0x001E
110 #define MGETCMDLIST       0x001F
111 #define MEXPVAL           0x0020
112 #define MEXPFAILED        0x0021
113 #define MSAVESTATE        0x0022
114 #define MWRITEBLOCK       0x0023
115 #define MDETACH           0x0024
116 #define MGETMODULES       0x0025
117 #define MREMOTESYMBOL     0x0026
118 #define MREADCSTRING      0x0027
119 #define MLOADMODULE       0x0028
120 #define MDIDSYSCALL       0x0029
121 #define MDBPWRITEBUFFERS  0x002A
122 #define MBPID             0x002B
123 #define MINITEXEC         0x002C
124 #define MEXITEXEC         0x002D
125 #define MRCCMD            0x002E
126 #define MDOWNLOAD         0x0050
127
128 extern struct target_ops v850ice_ops;   /* Forward decl */
129
130 /*   "pir", "tkcw", "chcw", "adtre" */
131
132 /* Code for opening a connection to the ICE.  */
133
134 static void
135 v850ice_open (name, from_tty)
136      char *name;
137      int from_tty;
138 {
139   long retval;
140   char retmsg[1000];
141
142   if (name)
143     error ("Too many arguments.");
144
145   target_preopen (from_tty);
146
147   unpush_target (&v850ice_ops);
148
149   if (from_tty)
150     puts_filtered ("V850ice debugging\n");
151
152   push_target (&v850ice_ops);   /* Switch to using v850ice target now */
153
154   target_terminal_init ();
155
156   /* Without this, some commands which require an active target (such as kill)
157      won't work.  This variable serves (at least) double duty as both the pid
158      of the target process (if it has such), and as a flag indicating that a
159      target is active.  These functions should be split out into seperate
160      variables, especially since GDB will someday have a notion of debugging
161      several processes.  */
162
163   inferior_pid = 42000;
164
165   /* Start the v850ice connection; if error (0), discard this target.
166      In particular, if the user quits, be sure to discard it
167      (we'd be in an inconsistent state otherwise).  */
168
169   retval = ExeAppReq ("GDB", MINITEXEC, "0", retmsg);
170   ice_open = 1;
171
172   start_remote ();
173
174 /*  pop_target();*/
175 }
176
177 /* Clean up connection to a remote debugger.  */
178
179 /* ARGSUSED */
180 static void
181 v850ice_close (quitting)
182      int quitting;
183 {
184   long retval;
185
186   if (ice_open)
187     {
188       retval = ExeAppReq ("GDB", MEXITEXEC, NULL, NULL);
189       if (retval)
190         error ("ExeAppReq (MEXITEXEC) returned %d", retval);
191       ice_open = 0;
192     }
193 }
194
195 static void
196 v850ice_detach (args, from_tty)
197      char *args;
198      int from_tty;
199 {
200   if (args)
201     error ("Argument given to \"detach\" when remotely debugging.");
202
203   pop_target ();
204   if (from_tty)
205     puts_filtered ("Ending v850ice debugging.\n");
206 }
207
208 /* Tell the remote machine to resume.  */
209
210 static void
211 v850ice_resume (pid, step, siggnal)
212      int pid, step;
213      enum target_signal siggnal;
214 {
215   long retval;
216   char cmd[100];
217   char val[100];
218
219   if (step)
220     retval = ExeAppReq ("GDB", MSINGLESTEP, "step", val);
221   else
222     retval = ExeAppReq ("GDB", MRESUME, "run", val);
223
224   if (retval)
225     error ("ExeAppReq (step = %d) returned %d: cmd = %s", step, retval, cmd);
226 }
227
228 /* Wait until the remote machine stops, then return,
229    storing status in STATUS just as `wait' would.
230    Returns "pid" (though it's not clear what, if anything, that
231    means in the case of this target).  */
232
233 static int
234 v850ice_wait (pid, status)
235      int pid;
236      struct target_waitstatus *status;
237 {
238   status->kind = TARGET_WAITKIND_STOPPED;
239   status->value.sig = TARGET_SIGNAL_TRAP;
240
241   return inferior_pid;
242 }
243
244 static int
245 convert_register (regno, buf)
246      int regno;
247      char *buf;
248 {
249   if (regno <= 31)
250     sprintf (buf, "r%d", regno);
251   else if (reg_names[regno][0] == 's'
252            && reg_names[regno][1] == 'r')
253     return 0;
254   else
255     sprintf (buf, "%s", reg_names[regno]);
256
257   return 1;
258 }
259
260 /* Read the remote registers into the block REGS.  */
261 /* Note that the ICE returns register contents as ascii hex strings.  We have
262    to convert that to an unsigned long, and then call store_unsigned_integer to
263    convert it to target byte-order if necessary.  */
264
265 static void
266 v850ice_fetch_registers (regno)
267      int regno;
268 {
269   long retval;
270   char cmd[100];
271   char val[100];
272   unsigned long regval;
273   char *p;
274
275   if (regno == -1)
276     {
277       for (regno = 0; regno < NUM_REGS; regno++)
278         v850ice_fetch_registers (regno);
279       return;
280     }
281
282   strcpy (cmd, "reg ");
283   if (!convert_register (regno, &cmd[4]))
284     return;
285
286   retval = ExeAppReq ("GDB", MREADREG, cmd, val);
287   if (retval)
288     error ("ExeAppReq returned %d: cmd = %s", retval, cmd);
289
290   regval = strtoul (val, &p, 16);
291   if (regval == 0 && p == val)
292     error ("v850ice_fetch_registers (%d):  bad value from ICE: %s.",
293            regno, val);
294
295   store_unsigned_integer (val, REGISTER_RAW_SIZE (regno), regval);
296   supply_register (regno, val);
297 }
298
299 /* Store register REGNO, or all registers if REGNO == -1, from the contents
300    of REGISTERS.  */
301
302 static void
303 v850ice_store_registers (regno)
304      int regno;
305 {
306   long retval;
307   char cmd[100];
308   char val[100];
309   unsigned long regval;
310
311   if (regno == -1)
312     {
313       for (regno = 0; regno < NUM_REGS; regno++)
314         v850ice_store_registers (regno);
315       return;
316     }
317
318   regval = extract_unsigned_integer (&registers[REGISTER_BYTE (regno)],
319                                      REGISTER_RAW_SIZE (regno));
320   strcpy (cmd, "reg ");
321   if (!convert_register (regno, &cmd[4]))
322     return;
323   sprintf (cmd + strlen (cmd), "=0x%x", regval);
324
325   retval = ExeAppReq ("GDB", MWRITEREG, cmd, val);
326   if (retval)
327     error ("ExeAppReq returned %d: cmd = %s", retval, cmd);
328 }
329
330 /* Prepare to store registers.  Nothing to do here, since the ICE can write one
331    register at a time.  */
332
333 static void 
334 v850ice_prepare_to_store ()
335 {
336 }
337
338 /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
339    to or from debugger address MYADDR.  Write to inferior if SHOULD_WRITE is
340    nonzero.  Returns length of data written or read; 0 for error.  */
341
342 /* ARGSUSED */
343 static int
344 v850ice_xfer_memory (memaddr, myaddr, len, should_write, target)
345      CORE_ADDR memaddr;
346      char *myaddr;
347      int len;
348      int should_write;
349      struct target_ops *target;                 /* ignored */
350 {
351   long retval;
352   char cmd[100];
353
354   if (should_write)
355     {
356 #if 1
357       sprintf (cmd, "memory b c 0x%x=0x00 l=%d", (int)memaddr, len);
358       retval = ExeAppReq ("GDB", MWRITEBLOCK, cmd, myaddr);
359 #else
360       sprintf (cmd, "memory b c 0x%x=0x%x", (int)memaddr, *myaddr & 0xff);
361       retval = ExeAppReq ("GDB", MWRITEBLOCK, cmd, myaddr);
362       return 1;
363 #endif
364     }
365   else
366     {
367       unsigned char *tmp;
368       int i;
369
370       tmp = alloca (len + 100);
371       memset (tmp + len, 0xff, 100);
372       
373       sprintf (cmd, "memory b 0x%x l=%d", (int)memaddr, len);
374       retval = ExeAppReq ("GDB", MREADBLOCK, cmd, tmp);
375
376       for (i = 0; i <  100; i++)
377         {
378           if (tmp[len + i] != 0xff)
379             {
380               warning ("MREADBLOCK trashed bytes after transfer area.");
381               break;
382             }
383         }
384       memcpy (myaddr, tmp, len);
385     }
386
387   if (retval)
388     error ("ExeAppReq returned %d: cmd = %s", retval, cmd);
389
390   return len;
391 }
392
393 static void
394 v850ice_files_info (ignore)
395      struct target_ops *ignore;
396 {
397   puts_filtered ("Debugging a target via the NEC V850 ICE.\n");
398 }
399
400 static int
401 v850ice_insert_breakpoint (addr, contents_cache)
402      CORE_ADDR addr;
403      char *contents_cache;
404 {
405   long retval;
406   char cmd[100];
407   char val[100];
408
409   sprintf (cmd, "%d, ", addr);
410
411 #if 1
412   retval = ExeAppReq ("GDB", MSETBREAK, cmd, val);
413 #else
414   retval = ExeAppReq ("GDB", MSETHARDBRK, cmd, val);
415 #endif
416   if (retval)
417     error ("ExeAppReq (MSETBREAK) returned %d: cmd = %s", retval, cmd);
418
419   return 0;
420 }
421
422 static int
423 v850ice_remove_breakpoint (addr, contents_cache)
424      CORE_ADDR addr;
425      char *contents_cache;
426 {
427   long retval;
428   char cmd[100];
429   char val[100];
430
431   sprintf (cmd, "%d, ", addr);
432
433 #if 1
434   retval = ExeAppReq ("GDB", MREMOVEBREAK, cmd, val);
435 #else
436   retval = ExeAppReq ("GDB", MREMOVEHARDBRK, cmd, val);
437 #endif
438   if (retval)
439     error ("ExeAppReq (MREMOVEBREAK) returned %d: cmd = %s", retval, cmd);
440
441   return 0;
442 }
443
444 static void
445 v850ice_kill ()
446 {
447   target_mourn_inferior ();
448 }
449
450 static void
451 v850ice_mourn ()
452 {
453 }
454
455 /* Define the target subroutine names */
456
457 struct target_ops v850ice_ops = {
458   "ice",                        /* to_shortname */
459   "NEC V850 ICE interface",     /* to_longname */
460   "Debug a system controlled by a NEC 850 ICE.", /* to_doc */
461   v850ice_open,                 /* to_open */
462   v850ice_close,                /* to_close */
463   NULL,                         /* to_attach */
464   v850ice_detach,               /* to_detach */
465   v850ice_resume,               /* to_resume */
466   v850ice_wait,                 /* to_wait */
467   v850ice_fetch_registers,      /* to_fetch_registers */
468   v850ice_store_registers,      /* to_store_registers */
469   v850ice_prepare_to_store,     /* to_prepare_to_store */
470   v850ice_xfer_memory,          /* to_xfer_memory */
471   v850ice_files_info,           /* to_files_info */
472   v850ice_insert_breakpoint,    /* to_insert_breakpoint */
473   v850ice_remove_breakpoint,    /* to_remove_breakpoint */
474   NULL,                         /* to_terminal_init */
475   NULL,                         /* to_terminal_inferior */
476   NULL,                         /* to_terminal_ours_for_output */
477   NULL,                         /* to_terminal_ours */
478   NULL,                         /* to_terminal_info */
479   v850ice_kill,                 /* to_kill */
480   generic_load,                 /* to_load */
481   NULL,                         /* to_lookup_symbol */
482   NULL,                         /* to_create_inferior */
483   v850ice_mourn,                /* to_mourn_inferior */
484   0,                            /* to_can_run */
485   0,                            /* to_notice_signals */
486   NULL,                         /* to_thread_alive */
487   0,                            /* to_stop */
488   process_stratum,              /* to_stratum */
489   NULL,                         /* to_next */
490   1,                            /* to_has_all_memory */
491   1,                            /* to_has_memory */
492   1,                            /* to_has_stack */
493   1,                            /* to_has_registers */
494   1,                            /* to_has_execution */
495   NULL,                         /* sections */
496   NULL,                         /* sections_end */
497   OPS_MAGIC                     /* to_magic */
498 };
499
500 void
501 _initialize_v850ice ()
502 {
503   add_target (&v850ice_ops);
504 }