1 /* ICE interface for the NEC V850 for GDB, the GNU debugger.
2 Copyright 1996, Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
21 #include "gdb_string.h"
35 #include "gdb-stabs.h"
36 #include "gdbthread.h"
38 #define WIN32_LEAN_AND_MEAN
41 /* Prototypes for local functions */
43 static void v850ice_files_info
PARAMS ((struct target_ops
*ignore
));
45 static int v850ice_xfer_memory
PARAMS ((CORE_ADDR memaddr
, char *myaddr
,
46 int len
, int should_write
,
47 struct target_ops
*target
));
49 static void v850ice_prepare_to_store
PARAMS ((void));
51 static void v850ice_fetch_registers
PARAMS ((int regno
));
53 static void v850ice_resume
PARAMS ((int pid
, int step
,
54 enum target_signal siggnal
));
56 static void v850ice_open
PARAMS ((char *name
, int from_tty
));
58 static void v850ice_close
PARAMS ((int quitting
));
60 static void v850ice_store_registers
PARAMS ((int regno
));
62 static void v850ice_mourn
PARAMS ((void));
64 static int v850ice_wait
PARAMS ((int pid
, struct target_waitstatus
*status
));
66 static void v850ice_kill
PARAMS ((void));
68 static void v850ice_detach
PARAMS ((char *args
, int from_tty
));
70 static int v850ice_insert_breakpoint
PARAMS ((CORE_ADDR
, char *));
72 static int v850ice_remove_breakpoint
PARAMS ((CORE_ADDR
, char *));
74 static int ice_open
= 0;
77 #define EXPORT __declspec(dllexport)
82 int size
; /* length of input or output in bytes */
83 char *buf
; /* buffer having the input/output information */
86 struct MessageIO null_iob
= { 0, NULL
};
88 EXPORT
long __stdcall
ExeAppReq (char *, long, char *, struct MessageIO
*);
89 EXPORT
long __stdcall
RegisterClient (HWND
);
90 EXPORT
long __stdcall
UnregisterClient (void);
91 EXPORT
long __stdcall
GdbCallBack (void);
93 #define MREADREG 0x0001
94 #define MWRITEREG 0x0002
95 #define MREADMEM 0x0003
96 #define MWRITEMEM 0x0004
97 #define MSINGLESTEP 0x0005
98 #define MRESUME 0x0006
99 #define MLOADPROGRAM 0x0007
100 #define MSETBREAK 0x0008
101 #define MREMOVEBREAK 0x0009
103 #define MTERMINATE 0x000B
104 #define MATTACH 0x000C
105 #define MCHECKSTATUS 0x000D
107 #define MDIRECTCMD 0x000F
108 #define MSYMADR 0x0010
109 #define MGETTASKLIST 0x0011
110 #define MREADVECREG 0x0012
111 #define MWRITEVECREG 0x0013
112 #define MGETCHANGEDREGS 0x0014
113 #define MGETSERVERINFO 0x0015
114 #define MREADBLOCK 0x0016
115 #define MSETHARDBRK 0x0017
116 #define MREMOVEHARDBRK 0x0018
117 #define MCOPYBLOCK 0x0019
118 #define MBLOCKFILL 0x001A
119 #define MFINDBLOCK 0x001B
120 #define MCOMPAREBLOCK 0x001C
121 #define MREFRESH 0x001D
122 #define MSPECIAL 0x001E
123 #define MGETCMDLIST 0x001F
124 #define MEXPVAL 0x0020
125 #define MEXPFAILED 0x0021
126 #define MSAVESTATE 0x0022
127 #define MWRITEBLOCK 0x0023
128 #define MDETACH 0x0024
129 #define MGETMODULES 0x0025
130 #define MREMOTESYMBOL 0x0026
131 #define MREADCSTRING 0x0027
132 #define MLOADMODULE 0x0028
133 #define MDIDSYSCALL 0x0029
134 #define MDBPWRITEBUFFERS 0x002A
136 #define MINITEXEC 0x002C
137 #define MEXITEXEC 0x002D
138 #define MRCCMD 0x002E
139 #define MDOWNLOAD 0x0050
141 #define StatRunning 0
142 #define StatExecBreak 1 /* an execution breakpoint has been reached */
143 #define StatStepped 2 /* a single step has been completed */
144 #define StatException 3 /* the target has stopped due to an exception */
145 #define StatHalted 4 /* target has been halted by a user request */
146 #define StatExited 5 /* target called exit */
147 #define StatTerminated 6 /* target program terminated by a user request */
148 #define StatNoProcess 7 /* no process on target and none of the above */
149 #define StatNeedInput 8 /* REV: obsolete */
150 #define StatNeedDirCmd 9 /* waiting for an entry in the remote window */
151 #define StatHardBreak 10 /* hit hardware breakpoint */
152 #define StatFailure 11 /* an error occured in the last run/single */
154 extern struct target_ops v850ice_ops
; /* Forward decl */
156 /* "pir", "tkcw", "chcw", "adtre" */
158 /* Code for opening a connection to the ICE. */
161 v850ice_open (name
, from_tty
)
168 error ("Too many arguments.");
170 target_preopen (from_tty
);
172 unpush_target (&v850ice_ops
);
175 puts_filtered ("V850ice debugging\n");
177 push_target (&v850ice_ops
); /* Switch to using v850ice target now */
179 target_terminal_init ();
181 /* Without this, some commands which require an active target (such as kill)
182 won't work. This variable serves (at least) double duty as both the pid
183 of the target process (if it has such), and as a flag indicating that a
184 target is active. These functions should be split out into seperate
185 variables, especially since GDB will someday have a notion of debugging
186 several processes. */
188 inferior_pid
= 42000;
190 /* Start the v850ice connection; if error (0), discard this target.
191 In particular, if the user quits, be sure to discard it
192 (we'd be in an inconsistent state otherwise). */
194 WinExec ("necsrv", SW_SHOW
); /* Start up necsrv */
196 retval
= RegisterClient (NULL
);
208 error ("v850ice_open: MINITEXEC return error: 0x%x", retval
);
211 /* Clean up connection to a remote debugger. */
215 v850ice_close (quitting
)
223 retval
= ExeAppReq ("GDB", MEXITEXEC
, NULL
, &null_iob
);
225 error ("ExeAppReq (MEXITEXEC) returned %d", retval
);
233 v850ice_detach (args
, from_tty
)
238 error ("Argument given to \"detach\" when remotely debugging.");
242 puts_filtered ("Ending v850ice debugging.\n");
245 /* Tell the remote machine to resume. */
248 v850ice_resume (pid
, step
, siggnal
)
250 enum target_signal siggnal
;
255 retval
= ExeAppReq ("GDB", MSINGLESTEP
, "step", &null_iob
);
257 retval
= ExeAppReq ("GDB", MRESUME
, "run", &null_iob
);
260 error ("ExeAppReq (step = %d) returned %d", step
, retval
);
263 /* Wait until the remote machine stops, then return,
264 storing status in STATUS just as `wait' would.
265 Returns "pid" (though it's not clear what, if anything, that
266 means in the case of this target). */
269 v850ice_wait (pid
, status
)
271 struct target_waitstatus
*status
;
275 v850_status
= ExeAppReq ("GDB", MCHECKSTATUS
, NULL
, &null_iob
);
277 status
->kind
= TARGET_WAITKIND_STOPPED
;
278 status
->value
.sig
= TARGET_SIGNAL_TRAP
;
284 convert_register (regno
, buf
)
289 sprintf (buf
, "r%d", regno
);
290 else if (reg_names
[regno
][0] == 's'
291 && reg_names
[regno
][1] == 'r')
294 sprintf (buf
, "%s", reg_names
[regno
]);
299 /* Read the remote registers into the block REGS. */
300 /* Note that the ICE returns register contents as ascii hex strings. We have
301 to convert that to an unsigned long, and then call store_unsigned_integer to
302 convert it to target byte-order if necessary. */
305 v850ice_fetch_registers (regno
)
311 struct MessageIO iob
;
312 unsigned long regval
;
317 for (regno
= 0; regno
< NUM_REGS
; regno
++)
318 v850ice_fetch_registers (regno
);
322 strcpy (cmd
, "reg ");
323 if (!convert_register (regno
, &cmd
[4]))
326 iob
.size
= sizeof val
;
328 retval
= ExeAppReq ("GDB", MREADREG
, cmd
, &iob
);
330 error ("ExeAppReq returned %d: cmd = %s", retval
, cmd
);
332 regval
= strtoul (val
, &p
, 16);
333 if (regval
== 0 && p
== val
)
334 error ("v850ice_fetch_registers (%d): bad value from ICE: %s.",
337 store_unsigned_integer (val
, REGISTER_RAW_SIZE (regno
), regval
);
338 supply_register (regno
, val
);
341 /* Store register REGNO, or all registers if REGNO == -1, from the contents
345 v850ice_store_registers (regno
)
350 unsigned long regval
;
354 for (regno
= 0; regno
< NUM_REGS
; regno
++)
355 v850ice_store_registers (regno
);
359 regval
= extract_unsigned_integer (®isters
[REGISTER_BYTE (regno
)],
360 REGISTER_RAW_SIZE (regno
));
361 strcpy (cmd
, "reg ");
362 if (!convert_register (regno
, &cmd
[4]))
364 sprintf (cmd
+ strlen (cmd
), "=0x%x", regval
);
366 retval
= ExeAppReq ("GDB", MWRITEREG
, cmd
, &null_iob
);
368 error ("ExeAppReq returned %d: cmd = %s", retval
, cmd
);
371 /* Prepare to store registers. Nothing to do here, since the ICE can write one
372 register at a time. */
375 v850ice_prepare_to_store ()
379 /* Read or write LEN bytes from inferior memory at MEMADDR, transferring
380 to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
381 nonzero. Returns length of data written or read; 0 for error. */
385 v850ice_xfer_memory (memaddr
, myaddr
, len
, should_write
, target
)
390 struct target_ops
*target
; /* ignored */
394 struct MessageIO iob
;
402 sprintf (cmd
, "memory b c 0x%x=0x00 l=%d", (int)memaddr
, len
);
403 retval
= ExeAppReq ("GDB", MWRITEBLOCK
, cmd
, &iob
);
405 sprintf (cmd
, "memory b c 0x%x=0x%x", (int)memaddr
, *myaddr
& 0xff);
406 retval
= ExeAppReq ("GDB", MWRITEBLOCK
, cmd
, &iob
);
415 tmp
= alloca (len
+ 100);
416 memset (tmp
+ len
, 0xff, 100);
419 sprintf (cmd
, "memory b 0x%x l=%d", (int)memaddr
, len
);
420 retval
= ExeAppReq ("GDB", MREADBLOCK
, cmd
, &iob
);
422 sprintf (cmd
, "memory h 0x%x", (int)memaddr
);
423 retval
= ExeAppReq ("GDB", MREADMEM
, cmd
, &iob
);
425 for (i
= 0; i
< 100; i
++)
427 if (tmp
[len
+ i
] != 0xff)
429 warning ("MREADBLOCK trashed bytes after transfer area.");
433 memcpy (myaddr
, tmp
, len
);
437 error ("ExeAppReq returned %d: cmd = %s", retval
, cmd
);
443 v850ice_files_info (ignore
)
444 struct target_ops
*ignore
;
446 puts_filtered ("Debugging a target via the NEC V850 ICE.\n");
450 v850ice_insert_breakpoint (addr
, contents_cache
)
452 char *contents_cache
;
457 sprintf (cmd
, "%d, ", addr
);
460 retval
= ExeAppReq ("GDB", MSETBREAK
, cmd
, &null_iob
);
462 retval
= ExeAppReq ("GDB", MSETHARDBRK
, cmd
, &null_iob
);
465 error ("ExeAppReq (MSETBREAK) returned %d: cmd = %s", retval
, cmd
);
471 v850ice_remove_breakpoint (addr
, contents_cache
)
473 char *contents_cache
;
478 sprintf (cmd
, "%d, ", addr
);
481 retval
= ExeAppReq ("GDB", MREMOVEBREAK
, cmd
, &null_iob
);
483 retval
= ExeAppReq ("GDB", MREMOVEHARDBRK
, cmd
, &null_iob
);
486 error ("ExeAppReq (MREMOVEBREAK) returned %d: cmd = %s", retval
, cmd
);
494 target_mourn_inferior ();
502 /* Define the target subroutine names */
504 struct target_ops v850ice_ops
= {
505 "ice", /* to_shortname */
506 "NEC V850 ICE interface", /* to_longname */
507 "Debug a system controlled by a NEC 850 ICE.", /* to_doc */
508 v850ice_open
, /* to_open */
509 v850ice_close
, /* to_close */
510 NULL
, /* to_attach */
511 v850ice_detach
, /* to_detach */
512 v850ice_resume
, /* to_resume */
513 v850ice_wait
, /* to_wait */
514 v850ice_fetch_registers
, /* to_fetch_registers */
515 v850ice_store_registers
, /* to_store_registers */
516 v850ice_prepare_to_store
, /* to_prepare_to_store */
517 v850ice_xfer_memory
, /* to_xfer_memory */
518 v850ice_files_info
, /* to_files_info */
519 v850ice_insert_breakpoint
, /* to_insert_breakpoint */
520 v850ice_remove_breakpoint
, /* to_remove_breakpoint */
521 NULL
, /* to_terminal_init */
522 NULL
, /* to_terminal_inferior */
523 NULL
, /* to_terminal_ours_for_output */
524 NULL
, /* to_terminal_ours */
525 NULL
, /* to_terminal_info */
526 v850ice_kill
, /* to_kill */
527 generic_load
, /* to_load */
528 NULL
, /* to_lookup_symbol */
529 NULL
, /* to_create_inferior */
530 v850ice_mourn
, /* to_mourn_inferior */
532 0, /* to_notice_signals */
533 NULL
, /* to_thread_alive */
535 process_stratum
, /* to_stratum */
537 1, /* to_has_all_memory */
538 1, /* to_has_memory */
539 1, /* to_has_stack */
540 1, /* to_has_registers */
541 1, /* to_has_execution */
543 NULL
, /* sections_end */
544 OPS_MAGIC
/* to_magic */
548 _initialize_v850ice ()
550 add_target (&v850ice_ops
);