Commit | Line | Data |
---|---|---|
a332e593 SC |
1 | /* Remote debugging interface for Zilog Z8000 simulator |
2 | Copyright 1992 Free Software Foundation, Inc. | |
3 | Contributed by Cygnus Support. Written by Steve Chamberlain | |
4 | (sac@cygnus.com). | |
5 | ||
6 | This file is part of GDB. | |
7 | ||
8 | This program is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2 of the License, or | |
11 | (at your option) any later version. | |
12 | ||
13 | This program is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with this program; if not, write to the Free Software | |
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
21 | ||
22 | #include "defs.h" | |
23 | #include "inferior.h" | |
24 | #include "wait.h" | |
25 | #include "value.h" | |
26 | #include <string.h> | |
27 | #include <ctype.h> | |
28 | #include <fcntl.h> | |
29 | #include <signal.h> | |
30 | #include <setjmp.h> | |
31 | #include <errno.h> | |
32 | #include "terminal.h" | |
33 | #include "target.h" | |
34 | #include "gdbcore.h" | |
35 | #include "../z8ksim/sim.h" | |
36 | ||
37 | /* External data declarations */ | |
38 | extern int stop_soon_quietly; /* for wait_for_inferior */ | |
39 | ||
40 | /* Forward data declarations */ | |
41 | extern struct target_ops sim_ops; /* Forward declaration */ | |
42 | ||
43 | /* Forward function declarations */ | |
44 | static void sim_fetch_registers (); | |
45 | static void sim_close (); | |
46 | ||
47 | void sim_store_register(); | |
48 | ||
49 | void sim_set_oc(); | |
50 | ||
51 | ||
52 | int | |
53 | sim_write_inferior_memory (memaddr, myaddr, len) | |
54 | CORE_ADDR memaddr; | |
55 | unsigned char *myaddr; | |
56 | int len; | |
57 | { | |
58 | return sim_write(memaddr, myaddr, len); | |
59 | } | |
60 | ||
61 | static int | |
62 | store_register(regno) | |
63 | int regno; | |
64 | { | |
65 | if (regno == -1) | |
66 | { | |
67 | for (regno = 0; regno < 16; regno++) | |
68 | store_register(regno); | |
69 | } | |
70 | else | |
71 | { | |
72 | sim_store_register(regno,read_register(regno)); | |
73 | } | |
74 | return 0; | |
75 | } | |
76 | ||
77 | ||
78 | ||
79 | void | |
80 | sim_kill(arg,from_tty) | |
81 | char *arg; | |
82 | int from_tty; | |
83 | { | |
84 | ||
85 | } | |
86 | ||
87 | ||
88 | ||
89 | /* | |
90 | * Download a file specified in 'args', to the sim. | |
91 | */ | |
92 | static void | |
93 | sim_load(args,fromtty) | |
94 | char *args; | |
95 | int fromtty; | |
96 | { | |
97 | bfd *abfd; | |
98 | asection *s; | |
99 | ||
100 | inferior_pid = 0; | |
101 | abfd = bfd_openr(args,"coff-z8k"); | |
102 | ||
103 | if (!abfd) | |
104 | { | |
105 | printf_filtered("Unable to open file %s\n", args); | |
106 | return; | |
107 | } | |
108 | ||
109 | if (bfd_check_format(abfd, bfd_object) ==0) | |
110 | { | |
111 | printf_filtered("File is not an object file\n"); | |
112 | return ; | |
113 | } | |
114 | ||
115 | s = abfd->sections; | |
116 | while (s != (asection *)NULL) | |
117 | { | |
118 | if (s->flags & SEC_LOAD) | |
119 | { | |
120 | int i; | |
121 | int delta = 4096; | |
122 | char *buffer = xmalloc(delta); | |
123 | printf_filtered("%s\t: 0x%4x .. 0x%4x ", | |
124 | s->name, s->vma, s->vma + s->_raw_size); | |
125 | for (i = 0; i < s->_raw_size; i+= delta) | |
126 | { | |
127 | int sub_delta = delta; | |
128 | if (sub_delta > s->_raw_size - i) | |
129 | sub_delta = s->_raw_size - i ; | |
130 | ||
131 | bfd_get_section_contents(abfd, s, buffer, i, sub_delta); | |
132 | sim_write_inferior_memory(s->vma + i, buffer, sub_delta); | |
133 | printf_filtered("*"); | |
134 | fflush(stdout); | |
135 | } | |
136 | printf_filtered( "\n"); | |
137 | free(buffer); | |
138 | } | |
139 | s = s->next; | |
140 | } | |
141 | ||
142 | sim_set_pc(abfd->start_address); | |
143 | } | |
144 | ||
145 | /* This is called not only when we first attach, but also when the | |
146 | user types "run" after having attached. */ | |
147 | void | |
148 | sim_create_inferior (execfile, args, env) | |
149 | char *execfile; | |
150 | char *args; | |
151 | char **env; | |
152 | { | |
153 | int entry_pt; | |
154 | char buffer[100]; | |
155 | ||
156 | if (args && *args) | |
157 | error ("Can't pass arguments to remote sim process."); | |
158 | ||
159 | if (execfile == 0 || exec_bfd == 0) | |
160 | error ("No exec file specified"); | |
161 | ||
162 | entry_pt = (int) bfd_get_start_address (exec_bfd); | |
163 | ||
164 | ||
165 | ||
166 | sim_kill(NULL,NULL); | |
167 | sim_clear_breakpoints(); | |
168 | init_wait_for_inferior (); | |
169 | ||
170 | ||
171 | ||
172 | insert_breakpoints (); /* Needed to get correct instruction in cache */ | |
173 | proceed(entry_pt, -1, 0); | |
174 | } | |
175 | ||
176 | ||
177 | ||
178 | static void | |
179 | sim_open (name, from_tty) | |
180 | char *name; | |
181 | int from_tty; | |
182 | { | |
183 | if(name == 0) | |
184 | { | |
185 | name = ""; | |
186 | } | |
187 | ||
188 | /* Clear any break points */ | |
189 | sim_clear_breakpoints(); | |
190 | ||
191 | push_target (&sim_ops); | |
192 | target_fetch_registers(-1); | |
193 | ||
194 | printf_filtered("Connected to the Z8000 Simulator.\n"); | |
195 | } | |
196 | ||
197 | /* Close out all files and local state before this target loses control. */ | |
198 | ||
199 | static void | |
200 | sim_close (quitting) | |
201 | int quitting; | |
202 | { | |
203 | ||
204 | ||
205 | /* Clear any break points */ | |
206 | sim_clear_breakpoints(); | |
207 | ||
208 | /* Put this port back into REMOTE mode */ | |
209 | sleep(1); /* Let any output make it all the way back */ | |
210 | } | |
211 | ||
212 | /* Terminate the open connection to the remote debugger. | |
213 | Use this when you want to detach and do something else | |
214 | with your gdb. */ | |
215 | int | |
216 | sim_detach (args,from_tty) | |
217 | char *args; | |
218 | int from_tty; | |
219 | { | |
220 | sim_clear_breakpoints(); | |
221 | ||
222 | pop_target(); /* calls sim_close to do the real work */ | |
223 | if (from_tty) | |
224 | printf_filtered ("Ending remote %s debugging\n", target_shortname); | |
225 | return 0; | |
226 | } | |
227 | ||
228 | /* Tell the remote machine to resume. */ | |
229 | ||
230 | ||
231 | /* Wait until the remote machine stops, then return, | |
232 | storing status in STATUS just as `wait' would. */ | |
233 | ||
234 | int | |
235 | sim_wait (status) | |
236 | WAITTYPE *status; | |
237 | { | |
238 | ||
239 | *status = sim_stop_signal(); | |
240 | return 0; | |
241 | } | |
242 | ||
243 | /* Return the name of register number REGNO | |
244 | in the form input and output by sim. | |
245 | ||
246 | Returns a pointer to a static buffer containing the answer. */ | |
247 | static char * | |
248 | get_reg_name (regno) | |
249 | int regno; | |
250 | { | |
251 | static char *rn[NUM_REGS]= REGISTER_NAMES; | |
252 | return rn[regno]; | |
253 | } | |
254 | ||
255 | ||
256 | ||
257 | ||
258 | ||
259 | /* Get ready to modify the registers array. On machines which store | |
260 | individual registers, this doesn't need to do anything. On machines | |
261 | which store all the registers in one fell swoop, this makes sure | |
262 | that registers contains all the registers from the program being | |
263 | debugged. */ | |
264 | ||
265 | void | |
266 | sim_prepare_to_store () | |
267 | { | |
268 | /* Do nothing, since we can store individual regs */ | |
269 | } | |
270 | ||
271 | static CORE_ADDR | |
272 | translate_addr(addr) | |
273 | CORE_ADDR addr; | |
274 | { | |
275 | ||
276 | return(addr); | |
277 | ||
278 | } | |
279 | ||
280 | /* Read a word from remote address ADDR and return it. | |
281 | * This goes through the data cache. | |
282 | */ | |
283 | int | |
284 | sim_fetch_word (addr) | |
285 | CORE_ADDR addr; | |
286 | { | |
287 | /* return dcache_fetch (addr);*/ | |
288 | } | |
289 | ||
290 | ||
291 | static void | |
292 | fetch_register(regno) | |
293 | int regno; | |
294 | { | |
295 | if (regno == -1) | |
296 | { | |
297 | for (regno = 0; regno < 16; regno++) | |
298 | fetch_register(regno); | |
299 | } | |
300 | else { | |
301 | char buf[MAX_REGISTER_RAW_SIZE]; | |
302 | sim_fetch_register(regno, buf); | |
303 | supply_register(regno, buf); | |
304 | } | |
305 | } | |
306 | ||
307 | /* Write a word WORD into remote address ADDR. | |
308 | This goes through the data cache. */ | |
309 | ||
310 | void | |
311 | sim_store_word (addr, word) | |
312 | CORE_ADDR addr; | |
313 | int word; | |
314 | { | |
315 | /* dcache_poke (addr, word);*/ | |
316 | } | |
317 | ||
318 | int | |
319 | sim_xfer_inferior_memory(memaddr, myaddr, len, write, target) | |
320 | CORE_ADDR memaddr; | |
321 | char *myaddr; | |
322 | int len; | |
323 | int write; | |
324 | struct target_ops *target; /* ignored */ | |
325 | { | |
326 | if (write) | |
327 | { | |
328 | sim_write(memaddr, myaddr, len); | |
329 | ||
330 | } | |
331 | else | |
332 | { | |
333 | sim_read(memaddr, myaddr, len); | |
334 | } | |
335 | return len; | |
336 | } | |
337 | ||
338 | void | |
339 | sim_files_info () | |
340 | { | |
341 | char *file = "nothing"; | |
342 | if (exec_bfd) | |
343 | file = bfd_get_filename(exec_bfd); | |
344 | ||
345 | if (exec_bfd) | |
346 | #ifdef __GO32__ | |
347 | printf_filtered("\tAttached to DOS asynctsr and running program %s\n",file); | |
348 | #else | |
349 | printf_filtered("\tAttached to %s at %d baud and running program %s\n",file); | |
350 | #endif | |
351 | printf_filtered("\ton an H8/300 processor.\n"); | |
352 | } | |
353 | ||
354 | /* This routine is run as a hook, just before the main command loop is | |
355 | entered. If gdb is configured for the H8, but has not had its | |
356 | target specified yet, this will loop prompting the user to do so. | |
357 | */ | |
358 | ||
359 | void | |
360 | sim_before_main_loop () | |
361 | { | |
362 | char ttyname[100]; | |
363 | char *p, *p2; | |
364 | extern FILE *instream; | |
365 | extern jmp_buf to_top_level; | |
366 | ||
367 | push_target (&sim_ops); | |
368 | } | |
369 | ||
370 | ||
371 | #define MAX_BREAKS 16 | |
372 | static int num_brkpts=0; | |
373 | static int | |
374 | sim_insert_breakpoint(addr, save) | |
375 | CORE_ADDR addr; | |
376 | char *save; /* Throw away, let sim save instructions */ | |
377 | { | |
378 | abort(); | |
379 | } | |
380 | static int | |
381 | sim_remove_breakpoint(addr, save) | |
382 | CORE_ADDR addr; | |
383 | char *save; /* Throw away, let sim save instructions */ | |
384 | { | |
385 | abort(); | |
386 | } | |
387 | ||
388 | /* Clear the sims notion of what the break points are */ | |
389 | static int | |
390 | sim_mourn() | |
391 | { | |
392 | sim_clear_breakpoints(); | |
393 | generic_mourn_inferior (); | |
394 | return 0; | |
395 | } | |
396 | ||
397 | static int rem_resume(a,b) | |
398 | { | |
399 | sim_resume(a,b); | |
400 | return 0; | |
401 | } | |
402 | ||
403 | /* Define the target subroutine names */ | |
404 | ||
405 | struct target_ops sim_ops = | |
406 | { | |
407 | "sim", "Remote SIM monitor", | |
408 | "Use the Z8000 simulator", | |
409 | sim_open, sim_close, | |
410 | 0, sim_detach, rem_resume, sim_wait, /* attach */ | |
411 | fetch_register, store_register, | |
412 | sim_prepare_to_store, | |
413 | sim_xfer_inferior_memory, | |
414 | sim_files_info, | |
415 | 0, 0, /* Breakpoints */ | |
416 | 0, 0, 0, 0, 0, /* Terminal handling */ | |
417 | sim_kill, /* FIXME, kill */ | |
418 | sim_load, | |
419 | 0, /* lookup_symbol */ | |
420 | sim_create_inferior, /* create_inferior */ | |
421 | sim_mourn, /* mourn_inferior FIXME */ | |
422 | 0, /* can_run */ | |
423 | 0, /* notice_signals */ | |
424 | process_stratum, 0, /* next */ | |
425 | 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ | |
426 | 0,0, /* Section pointers */ | |
427 | OPS_MAGIC, /* Always the last thing */ | |
428 | }; | |
429 | ||
430 | ||
431 | ||
432 | ||
433 | ||
434 | ||
435 | /***********************************************************************/ | |
436 | ||
437 | void | |
438 | _initialize_remote_sim () | |
439 | { | |
440 | extern int sim_z8001_mode; | |
441 | sim_z8001_mode = z8001_mode; | |
442 | add_target (&sim_ops); | |
443 | } | |
444 | ||
445 |