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