]>
Commit | Line | Data |
---|---|---|
249abc98 KH |
1 | /* Remote target communications for serial-line targets in custom GDB protocol |
2 | Copyright 1988, 1991, 1992, 1993, 1994 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 | |
6c9638b4 | 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
249abc98 KH |
19 | |
20 | #include "defs.h" | |
2b576293 | 21 | #include "gdb_string.h" |
249abc98 KH |
22 | #include <fcntl.h> |
23 | #include "frame.h" | |
24 | #include "inferior.h" | |
25 | #include "bfd.h" | |
26 | #include "symfile.h" | |
27 | #include "target.h" | |
28 | #include "wait.h" | |
29 | #include "terminal.h" | |
30 | #include "gdbcmd.h" | |
31 | #include "objfiles.h" | |
32 | #include "gdb-stabs.h" | |
33 | ||
34 | #include "dcache.h" | |
35 | ||
36 | #ifdef USG | |
37 | #include <sys/types.h> | |
38 | #endif | |
39 | ||
40 | #include <signal.h> | |
41 | #include "serial.h" | |
42 | ||
43 | /* Prototypes for local functions */ | |
44 | ||
45 | static int | |
46 | arc_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len)); | |
47 | ||
48 | static int | |
49 | arc_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len)); | |
50 | ||
51 | static void | |
52 | arc_files_info PARAMS ((struct target_ops *ignore)); | |
53 | ||
54 | static int | |
55 | arc_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, | |
56 | int should_write, struct target_ops *target)); | |
57 | ||
58 | static void | |
59 | arc_xfer_cntlreg PARAMS ((int rw, unsigned char *data)); | |
60 | ||
61 | static void | |
62 | arc_prepare_to_store PARAMS ((void)); | |
63 | ||
64 | static void | |
65 | arc_fetch_registers PARAMS ((int regno)); | |
66 | ||
67 | static void | |
68 | arc_resume PARAMS ((int pid, int step, enum target_signal siggnal)); | |
69 | ||
70 | static int | |
71 | arc_start_remote PARAMS ((char *dummy)); | |
72 | ||
73 | static void | |
74 | arc_open PARAMS ((char *name, int from_tty)); | |
75 | ||
76 | static void | |
77 | arc_close PARAMS ((int quitting)); | |
78 | ||
79 | static void | |
80 | arc_store_registers PARAMS ((int regno)); | |
81 | ||
82 | static void | |
83 | getpkt PARAMS ((char *buf, int len)); | |
84 | ||
85 | static int | |
86 | putpkt PARAMS ((char *buf, int len)); | |
87 | ||
88 | static int arc_wait PARAMS ((int pid, struct target_waitstatus *status)); | |
89 | ||
90 | static void | |
91 | arc_detach PARAMS ((char *args, int from_tty)); | |
92 | ||
93 | static void | |
94 | arc_interrupt PARAMS ((int signo)); | |
95 | ||
96 | static void | |
97 | arc_interrupt_twice PARAMS ((int signo)); | |
98 | ||
99 | static void | |
100 | interrupt_query PARAMS ((void)); | |
101 | ||
102 | extern struct target_ops arc_ops; /* Forward decl */ | |
103 | ||
abed6bc2 | 104 | static int aux_reg_map[3][31] = AUX_REG_MAP; |
249abc98 KH |
105 | |
106 | /* This was 5 seconds, which is a long time to sit and wait. | |
107 | Unless this is going though some terminal server or multiplexer or | |
108 | other form of hairy serial connection, I would think 2 seconds would | |
109 | be plenty. */ | |
110 | static int remote_timeout = 2; | |
111 | ||
112 | #if 0 | |
113 | int icache; | |
114 | #endif | |
115 | ||
116 | /* Descriptor for I/O to remote machine. Initialize it to NULL so that | |
117 | arc_open knows that we don't have a file open when the program | |
118 | starts. */ | |
119 | static serial_t arc_desc = NULL; | |
120 | ||
121 | #define AUDIO_PROCESSOR 0 | |
122 | #define GRAPHIC_PROCESSOR 1 | |
123 | #define HOST_PROCESSOR 2 | |
124 | static unsigned char cntl_reg_halt_bit[3] = { 0x08, 0x10, 0x20 }; | |
125 | static unsigned char cntl_reg_step_bit[3] = { 0x01, 0x02, 0x04 }; | |
126 | ||
127 | static int curr_processor = HOST_PROCESSOR; | |
128 | static unsigned char cntl_reg = 0; | |
129 | static unsigned int status_reg = 0; | |
130 | ||
131 | #define PBUFSIZ 32 | |
132 | #define MAXBUFBYTES 32 | |
133 | ||
134 | \f | |
135 | /* Clean up connection to a remote debugger. */ | |
136 | ||
137 | /* ARGSUSED */ | |
138 | static void | |
139 | arc_close (quitting) | |
140 | int quitting; | |
141 | { | |
142 | if (arc_desc) | |
143 | SERIAL_CLOSE (arc_desc); | |
144 | arc_desc = NULL; | |
145 | } | |
146 | ||
147 | static int | |
148 | arc_start_remote (dummy) | |
149 | char *dummy; | |
150 | { | |
151 | immediate_quit = 1; /* Allow user to interrupt it */ | |
152 | arc_xfer_cntlreg (1, &cntl_reg); | |
153 | immediate_quit = 0; | |
154 | ||
155 | start_remote (); /* Initialize gdb process mechanisms */ | |
156 | return 1; | |
157 | } | |
158 | ||
159 | /* Open a connection to a remote debugger. | |
160 | NAME is the filename used for communication. */ | |
161 | ||
162 | static DCACHE *remote_dcache; | |
163 | ||
164 | static void | |
165 | arc_open (name, from_tty) | |
166 | char *name; | |
167 | int from_tty; | |
168 | { | |
169 | if (name == 0) | |
170 | error ( | |
171 | "To open a arc debug connection, you need to specify what parallel\n\ | |
172 | device is attached to the remote system."); | |
173 | ||
174 | target_preopen (from_tty); | |
175 | ||
176 | unpush_target (&arc_ops); | |
177 | ||
178 | remote_dcache = dcache_init (arc_read_bytes, arc_write_bytes); | |
179 | ||
180 | arc_desc = SERIAL_OPEN (name); | |
181 | if (!arc_desc) | |
182 | perror_with_name (name); | |
183 | ||
184 | /* If there is something sitting in the buffer we might take it as a | |
185 | response to a command, which would be bad. */ | |
186 | SERIAL_FLUSH_INPUT (arc_desc); | |
187 | ||
188 | if (from_tty) | |
189 | { | |
190 | puts_filtered ("Remote debugging using "); | |
191 | puts_filtered (name); | |
192 | puts_filtered ("\n"); | |
193 | } | |
194 | push_target (&arc_ops); /* Switch to using remote target now */ | |
195 | ||
196 | /* Without this, some commands which require an active target (such as kill) | |
197 | won't work. This variable serves (at least) double duty as both the pid | |
198 | of the target process (if it has such), and as a flag indicating that a | |
199 | target is active. These functions should be split out into seperate | |
200 | variables, especially since GDB will someday have a notion of debugging | |
201 | several processes. */ | |
202 | ||
203 | inferior_pid = 42000; | |
204 | ||
205 | /* Start the remote connection; if error (0), discard this target. | |
206 | In particular, if the user quits, be sure to discard it | |
207 | (we'd be in an inconsistent state otherwise). */ | |
208 | if (!catch_errors (arc_start_remote, (char *)0, | |
209 | "Couldn't establish connection to remote target\n", RETURN_MASK_ALL)) | |
210 | pop_target(); | |
211 | } | |
212 | ||
213 | /* arc_detach() | |
214 | takes a program previously attached to and detaches it. | |
215 | We better not have left any breakpoints | |
216 | in the program or it'll die when it hits one. | |
217 | Close the open connection to the remote debugger. | |
218 | Use this when you want to detach and do something else | |
219 | with your gdb. */ | |
220 | ||
221 | static void | |
222 | arc_detach (args, from_tty) | |
223 | char *args; | |
224 | int from_tty; | |
225 | { | |
226 | if (args) | |
227 | error ("Argument given to \"detach\" when remotely debugging."); | |
228 | ||
229 | pop_target (); | |
230 | if (from_tty) | |
231 | puts_filtered ("Ending remote debugging.\n"); | |
232 | } | |
233 | ||
234 | /* arc_set_addrreg | |
235 | set addr reg from debug system. */ | |
236 | ||
237 | static void | |
238 | arc_set_addrreg (addr) | |
239 | unsigned int addr; | |
240 | { | |
241 | unsigned char buf[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
242 | ||
243 | buf[0] = 0x0; | |
244 | buf[4] = addr & 0xff; | |
245 | buf[3] = (addr >> 8) & 0xff; | |
246 | buf[2] = (addr >> 16) & 0xff; | |
247 | buf[1] = (addr >> 24) & 0xff; | |
248 | ||
249 | putpkt (buf, 5); | |
250 | } | |
251 | ||
252 | /* arc_xfer_datareg | |
253 | read or write data reg from debug system. */ | |
254 | ||
255 | static void | |
256 | arc_xfer_datareg (rw, aux, incr, data) | |
257 | int rw; | |
258 | int aux; | |
259 | int incr; | |
260 | unsigned int *data; | |
261 | { | |
262 | unsigned char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
263 | unsigned char buf2[5]; | |
264 | unsigned int tmp; | |
265 | ||
266 | /* read or write data */ | |
267 | buf1[0] = (aux ? 0x81 : 0x41); | |
268 | if (incr) | |
269 | buf1[0] += 0x20; | |
270 | if (rw) /* read */ | |
271 | { | |
272 | buf1[0] += 0x10; | |
273 | putpkt (buf1, 1); | |
274 | getpkt (buf2, 4); | |
275 | *data = *(int *)buf2; | |
276 | } | |
277 | else | |
278 | { | |
279 | tmp = *data; | |
280 | buf1[4] = tmp & 0xff; | |
281 | buf1[3] = (tmp >> 8) & 0xff; | |
282 | buf1[2] = (tmp >> 16) & 0xff; | |
283 | buf1[1] = (tmp >> 24) & 0xff; | |
284 | putpkt (buf1, 5); | |
285 | } | |
286 | } | |
287 | ||
288 | /* arc_xfer_cntlreg | |
289 | read or write control reg from debug system. */ | |
290 | ||
291 | static void | |
292 | arc_xfer_cntlreg (rw, data) | |
293 | int rw; | |
294 | unsigned char *data; | |
295 | { | |
296 | unsigned char buf[3] = {0x0, 0x0, 0x0}; | |
297 | ||
298 | if (rw) | |
299 | { | |
300 | buf[0] = 0x12; | |
301 | putpkt (buf, 1); | |
302 | getpkt (data, 1); | |
303 | } | |
304 | else | |
305 | { | |
306 | buf[0] = 0x02; | |
307 | buf[1] = *data; | |
308 | putpkt (buf, 2); | |
309 | } | |
310 | } | |
311 | ||
312 | /* arc_xfer_reg | |
313 | read or write a reg to arc processors. */ | |
314 | ||
315 | static void | |
316 | arc_xfer_reg (processor, rw, aux, regnum, data) | |
317 | int processor; | |
318 | int rw; | |
319 | int aux; | |
320 | int regnum; | |
321 | unsigned int *data; | |
322 | { | |
323 | unsigned int tmp; | |
324 | ||
325 | if (processor == HOST_PROCESSOR) | |
326 | { | |
327 | /* write addr (regnum) */ | |
328 | arc_set_addrreg (regnum); | |
329 | arc_xfer_datareg (rw, aux, 0, data); | |
330 | } | |
331 | else | |
332 | { | |
333 | /* write addr register (aux r14) */ | |
334 | arc_set_addrreg (0xe); | |
335 | tmp = aux ? (regnum | 0x80000000) : regnum; | |
336 | arc_xfer_datareg (0, 1, 0, tmp); | |
337 | ||
338 | /* read/write from data reg (aux reg 15/16) */ | |
339 | arc_set_addrreg (processor == AUDIO_PROCESSOR ? 0x10 : 0xf); | |
340 | arc_xfer_datareg (rw, 1, 0, data); | |
341 | } | |
342 | } | |
343 | ||
344 | \f | |
345 | /* Tell the remote machine to resume. */ | |
346 | ||
347 | static enum target_signal last_sent_signal = TARGET_SIGNAL_0; | |
348 | int last_sent_step; | |
349 | ||
350 | static void | |
351 | arc_resume (pid, step, siggnal) | |
352 | int pid, step; | |
353 | enum target_signal siggnal; | |
354 | { | |
355 | unsigned int tmp; | |
356 | ||
357 | dcache_flush (remote_dcache); | |
358 | ||
359 | last_sent_signal = siggnal; | |
360 | last_sent_step = step; | |
361 | ||
362 | /* don't know how to handle signal in ARC *** | |
363 | if (siggnal != TARGET_SIGNAL_0) | |
364 | { | |
365 | buf[0] = step ? 'S' : 'C'; | |
366 | buf[1] = tohex (((int)siggnal >> 4) & 0xf); | |
367 | buf[2] = tohex ((int)siggnal & 0xf); | |
368 | buf[3] = '\0'; | |
369 | } | |
370 | */ | |
371 | ||
372 | if (step) | |
373 | { | |
374 | /* write the step bit in control reg of debug system */ | |
375 | unsigned char tmp_char = cntl_reg | cntl_reg_step_bit[curr_processor]; | |
376 | arc_xfer_cntlreg (0, &tmp_char); | |
377 | } | |
378 | else | |
379 | { | |
380 | /* clear the halt bit in the status register */ | |
381 | tmp = status_reg | 0x02000000; | |
382 | arc_xfer_reg (curr_processor, 0, 1, 0, &tmp); | |
383 | } | |
384 | } | |
385 | ||
386 | \f | |
387 | static void (*ofunc)(); | |
388 | ||
389 | /* Send to target to halt it. */ | |
390 | static void | |
391 | arc_interrupt (signo) | |
392 | int signo; | |
393 | { | |
394 | unsigned char buf[3] = {0x02, 0x0, 0x0}; | |
395 | /* If this doesn't work, try more severe steps. */ | |
396 | signal (signo, arc_interrupt_twice); | |
397 | ||
398 | if (remote_debug) | |
399 | printf_unfiltered ("arc_interrupt called\n"); | |
400 | ||
401 | if (cntl_reg & cntl_reg_halt_bit[curr_processor]) | |
402 | return; | |
403 | ||
404 | buf[1] = cntl_reg | cntl_reg_halt_bit[curr_processor]; | |
405 | putpkt (buf, 2); | |
406 | return; | |
407 | } | |
408 | ||
409 | /* The user typed ^C twice. */ | |
410 | static void | |
411 | arc_interrupt_twice (signo) | |
412 | int signo; | |
413 | { | |
414 | signal (signo, ofunc); | |
415 | ||
416 | interrupt_query (); | |
417 | ||
418 | signal (signo, arc_interrupt); | |
419 | } | |
420 | ||
421 | /* Ask the user what to do when an interrupt is received. */ | |
422 | ||
423 | static void | |
424 | interrupt_query () | |
425 | { | |
426 | target_terminal_ours (); | |
427 | ||
428 | if (query ("Interrupted while waiting for the program.\n\ | |
429 | Give up (and stop debugging it)? ")) | |
430 | { | |
431 | target_mourn_inferior (); | |
432 | return_to_top_level (RETURN_QUIT); | |
433 | } | |
434 | ||
435 | target_terminal_inferior (); | |
436 | } | |
437 | ||
438 | /* If nonzero, ignore the next kill. */ | |
439 | int kill_kludge; | |
440 | ||
441 | /* Wait until the remote machine stops, then return, | |
442 | storing status in STATUS just as `wait' would. | |
443 | Returns "pid" (though it's not clear what, if anything, that | |
444 | means in the case of this target). */ | |
445 | ||
446 | static int | |
447 | arc_wait (pid, status) | |
448 | int pid; | |
449 | struct target_waitstatus *status; | |
450 | { | |
451 | unsigned char buf[PBUFSIZ]; | |
452 | int thread_num = -1; | |
abed6bc2 KH |
453 | unsigned char cmd; |
454 | int proc; | |
249abc98 KH |
455 | |
456 | status->kind = TARGET_WAITKIND_EXITED; | |
457 | status->value.integer = 0; | |
458 | ||
459 | while (1) | |
460 | { | |
461 | unsigned char *p; | |
462 | ||
463 | ofunc = (void (*)()) signal (SIGINT, arc_interrupt); | |
464 | arc_xfer_cntlreg (1, &cntl_reg); | |
465 | signal (SIGINT, ofunc); | |
466 | if (cntl_reg & cntl_reg_halt_bit[curr_processor]) | |
467 | break; | |
468 | status->kind = TARGET_WAITKIND_STOPPED; | |
469 | } | |
249abc98 | 470 | |
abed6bc2 KH |
471 | if ((curr_processor != HOST_PROCESSOR) && |
472 | !(cntl_reg & cntl_reg_halt_bit[HOST_PROCESSOR])) | |
473 | { | |
474 | cmd = cntl_reg | cntl_reg_halt_bit[HOST_PROCESSOR]; | |
475 | arc_xfer_cntlreg (0, &cmd); | |
476 | while (1) | |
477 | { | |
478 | unsigned char *p; | |
479 | ||
480 | ofunc = (void (*)()) signal (SIGINT, arc_interrupt); | |
481 | arc_xfer_cntlreg (1, &cntl_reg); | |
482 | signal (SIGINT, ofunc); | |
483 | if (cntl_reg & cntl_reg_halt_bit[HOST_PROCESSOR]) | |
484 | break; | |
485 | } | |
486 | } | |
487 | ||
488 | for (proc = AUDIO_PROCESSOR ; proc <= GRAPHIC_PROCESSOR; proc++) | |
489 | { | |
490 | if ((cntl_reg & cntl_reg_halt_bit[proc])) | |
491 | continue; | |
492 | cmd = cntl_reg | cntl_reg_halt_bit[proc]; | |
493 | arc_xfer_cntlreg (0, &cmd); | |
494 | } | |
495 | ||
496 | arc_xfer_reg (curr_processor, 1, 1, 0, &status_reg); | |
249abc98 KH |
497 | return inferior_pid; |
498 | } | |
499 | ||
500 | /* Number of bytes of registers this implements. */ | |
501 | static int register_bytes_found; | |
502 | ||
503 | /* Read the remote registers into the block REGS. */ | |
504 | /* Currently we just read all the registers, so we don't use regno. */ | |
505 | ||
506 | static void | |
507 | arc_fetch_registers (regno) | |
508 | int regno; | |
509 | { | |
510 | int i; | |
511 | char regs[REGISTER_BYTES]; | |
512 | ||
513 | /* Unimplemented registers read as all bits zero. */ | |
514 | memset (regs, 0, REGISTER_BYTES); | |
515 | ||
516 | /* get core register */ | |
517 | arc_set_addrreg (0); | |
518 | for (i = 0; i < AUX_BEG_REGNUM; i++) | |
519 | { | |
520 | if (curr_processor == HOST_PROCESSOR) | |
521 | arc_xfer_datareg (1, 0, 1, ®s[REGISTER_BYTE(i)]); | |
522 | else | |
523 | arc_xfer_reg (curr_processor, 1, 0, regno, ®s[REGISTER_BYTE(i)]); | |
524 | } | |
525 | ||
526 | /* get aux register */ | |
527 | for (i = AUX_BEG_REGNUM; i < AUX_END_REGNUM; i++) | |
528 | { | |
529 | int auxregnum = aux_reg_map[curr_processor][i-AUX_BEG_REGNUM+1]; | |
530 | if (auxregnum == -1) | |
531 | continue; | |
532 | arc_xfer_reg (curr_processor, 1, 1, auxregnum, ®s[REGISTER_BYTE(i)]); | |
533 | } | |
534 | /* copy from status register to pc */ | |
535 | for (i = 1; i <= 3; i++) | |
536 | registers[REGISTER_BYTE (PC_REGNUM)+i] = | |
537 | registers[REGISTER_BYTE (STA_REGNUM)+i]; | |
538 | ||
539 | /* | |
540 | if (i != register_bytes_found) | |
541 | { | |
542 | register_bytes_found = i; | |
543 | if (!REGISTER_BYTES_OK (i)) | |
544 | warning ("Remote reply is too short: %s", buf); | |
545 | } | |
546 | */ | |
547 | ||
548 | for (i = 0; i < NUM_REGS; i++) | |
549 | supply_register (i, ®s[REGISTER_BYTE(i)]); | |
550 | } | |
551 | ||
552 | /* Prepare to store registers. Since we may send them all, | |
553 | we have to read out the ones we don't want to change first. */ | |
554 | ||
555 | static void | |
556 | arc_prepare_to_store () | |
557 | { | |
558 | /* Make sure the entire registers array is valid. */ | |
559 | read_register_bytes (0, (char *)NULL, REGISTER_BYTES); | |
560 | } | |
561 | ||
562 | /* Store register REGNO, or all registers if REGNO == -1, from the contents | |
563 | of REGISTERS. FIXME: ignores errors. */ | |
564 | ||
565 | static void | |
566 | arc_store_registers (regno) | |
567 | int regno; | |
568 | { | |
569 | int i; | |
570 | char *regp; | |
571 | ||
572 | /* Try storing a single register. */ | |
573 | if (regno >= 0) | |
574 | { | |
575 | int isaux = (regno >= AUX_BEG_REGNUM ? 1 : 0); | |
576 | ||
577 | regp = ®isters[REGISTER_BYTE (regno)]; | |
578 | arc_xfer_reg (curr_processor, 0, isaux, regno, regp); | |
579 | } | |
580 | ||
581 | /* store core regs */ | |
582 | arc_set_addrreg (0); | |
583 | for (i = 0; i < AUX_BEG_REGNUM; i++) | |
584 | { | |
585 | regp = ®isters[REGISTER_BYTE (i)]; | |
586 | if (curr_processor == HOST_PROCESSOR) | |
587 | arc_xfer_datareg (0, 0, 1, regp); | |
588 | else | |
589 | arc_xfer_reg (curr_processor, 0, 0, regno, regp); | |
590 | } | |
591 | ||
592 | /* store aux regs */ | |
593 | /* copy pc back to status register */ | |
594 | for (i = 1; i <= 3; i++) | |
595 | registers[REGISTER_BYTE (STA_REGNUM)+i] = | |
596 | registers[REGISTER_BYTE (PC_REGNUM)+i]; | |
597 | for (i = AUX_BEG_REGNUM; i <= AUX_END_REGNUM; i++) | |
598 | { | |
599 | int auxregnum = aux_reg_map[curr_processor][i-AUX_BEG_REGNUM+1]; | |
600 | if (auxregnum == -1) | |
601 | continue; | |
602 | regp = ®isters[REGISTER_BYTE (i)]; | |
603 | arc_xfer_reg (curr_processor, 0, 1, auxregnum, regp); | |
604 | } | |
605 | ||
606 | } | |
607 | ||
608 | #if 0 | |
609 | /* Use of the data cache is disabled because it loses for looking at | |
610 | and changing hardware I/O ports and the like. Accepting `voltile' | |
611 | would perhaps be one way to fix it, but a better way which would | |
612 | win for more cases would be to use the executable file for the text | |
613 | segment, like the `icache' code below but done cleanly (in some | |
614 | target-independent place, perhaps in target_xfer_memory, perhaps | |
615 | based on assigning each target a speed or perhaps by some simpler | |
616 | mechanism). */ | |
617 | ||
618 | /* Read a word from remote address ADDR and return it. | |
619 | This goes through the data cache. */ | |
620 | ||
621 | static int | |
622 | arc_fetch_word (addr) | |
623 | CORE_ADDR addr; | |
624 | { | |
625 | #if 0 | |
626 | if (icache) | |
627 | { | |
628 | extern CORE_ADDR text_start, text_end; | |
629 | ||
630 | if (addr >= text_start && addr < text_end) | |
631 | { | |
632 | int buffer; | |
633 | xfer_core_file (addr, &buffer, sizeof (int)); | |
634 | return buffer; | |
635 | } | |
636 | } | |
637 | #endif | |
638 | return dcache_fetch (remote_dcache, addr); | |
639 | } | |
640 | ||
641 | /* Write a word WORD into remote address ADDR. | |
642 | This goes through the data cache. */ | |
643 | ||
644 | static void | |
645 | arc_store_word (addr, word) | |
646 | CORE_ADDR addr; | |
647 | int word; | |
648 | { | |
649 | dcache_poke (remote_dcache, addr, word); | |
650 | } | |
651 | #endif /* 0 */ | |
652 | ||
653 | \f | |
654 | /* Write memory data directly to the remote machine. | |
655 | This does not inform the data cache; the data cache uses this. | |
656 | MEMADDR is the address in the remote memory space. | |
657 | MYADDR is the address of the buffer in our space. | |
658 | LEN is the number of bytes. | |
659 | ||
660 | Returns number of bytes transferred, or 0 for error. */ | |
661 | ||
662 | static int | |
663 | arc_write_bytes (memaddr, myaddr, len) | |
664 | CORE_ADDR memaddr; | |
665 | unsigned char *myaddr; | |
666 | int len; | |
667 | { | |
668 | char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
669 | char buf2[6] = {0x21, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
670 | int i; | |
671 | char *p; | |
672 | ||
673 | /* We send target system values byte by byte, in increasing byte addresses*/ | |
674 | ||
675 | buf1[4] = memaddr & 0xff; | |
676 | buf1[3] = (memaddr >> 8) & 0xff; | |
677 | buf1[2] = (memaddr >> 16) & 0xff; | |
678 | buf1[1] = (memaddr >> 24) & 0xff; | |
679 | putpkt (buf1, 5); | |
680 | ||
681 | for (i = 0; i < len; ) | |
682 | { | |
683 | buf2[1] = myaddr[i++]; | |
684 | buf2[2] = myaddr[i++]; | |
685 | buf2[3] = myaddr[i++]; | |
686 | buf2[4] = myaddr[i++]; | |
687 | putpkt (buf2, 5); | |
688 | } | |
689 | ||
690 | return len; | |
691 | } | |
692 | ||
693 | /* Read memory data directly from the remote machine. | |
694 | This does not use the data cache; the data cache uses this. | |
695 | MEMADDR is the address in the remote memory space. | |
696 | MYADDR is the address of the buffer in our space. | |
697 | LEN is the number of bytes. | |
698 | ||
699 | Returns number of bytes transferred, or 0 for error. */ | |
700 | ||
701 | static int | |
702 | arc_read_bytes (memaddr, myaddr, len) | |
703 | CORE_ADDR memaddr; | |
704 | unsigned char *myaddr; | |
705 | int len; | |
706 | { | |
707 | unsigned char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
708 | unsigned char buf2[3] = {0x31, 0x0, 0x0}; | |
709 | unsigned char buf3[5]; | |
710 | int i; | |
711 | char *p; | |
712 | ||
713 | /* We send target system values byte by byte, in increasing byte addresses*/ | |
714 | ||
715 | buf1[4] = memaddr & 0xff; | |
716 | buf1[3] = (memaddr >> 8) & 0xff; | |
717 | buf1[2] = (memaddr >> 16) & 0xff; | |
718 | buf1[1] = (memaddr >> 24) & 0xff; | |
719 | putpkt (buf1, 5); | |
720 | ||
721 | for (i = 0; i < len; ) | |
722 | { | |
723 | putpkt (buf2, 2); | |
724 | getpkt (buf3, 4); | |
725 | myaddr[i++] = buf3[1]; | |
726 | myaddr[i++] = buf3[2]; | |
727 | myaddr[i++] = buf3[3]; | |
728 | myaddr[i++] = buf3[4]; | |
729 | } | |
730 | ||
731 | return i; | |
732 | } | |
733 | ||
734 | \f | |
735 | /* Read or write LEN bytes from inferior memory at MEMADDR, transferring | |
736 | to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is | |
737 | nonzero. Returns length of data written or read; 0 for error. */ | |
738 | ||
739 | /* ARGSUSED */ | |
740 | static int | |
741 | arc_xfer_memory(memaddr, myaddr, len, should_write, target) | |
742 | CORE_ADDR memaddr; | |
743 | char *myaddr; | |
744 | int len; | |
745 | int should_write; | |
746 | struct target_ops *target; /* ignored */ | |
747 | { | |
748 | int xfersize; | |
749 | int bytes_xferred; | |
750 | int total_xferred = 0; | |
751 | ||
752 | while (len > 0) | |
753 | { | |
754 | if (len > MAXBUFBYTES) | |
755 | xfersize = MAXBUFBYTES; | |
756 | else | |
757 | xfersize = len; | |
758 | ||
759 | if (should_write) | |
760 | bytes_xferred = arc_write_bytes (memaddr, | |
761 | (unsigned char *)myaddr, xfersize); | |
762 | else | |
763 | bytes_xferred = arc_read_bytes (memaddr, | |
764 | (unsigned char *)myaddr, xfersize); | |
765 | ||
766 | /* If we get an error, we are done xferring. */ | |
767 | if (bytes_xferred == 0) | |
768 | break; | |
769 | ||
770 | memaddr += bytes_xferred; | |
771 | myaddr += bytes_xferred; | |
772 | len -= bytes_xferred; | |
773 | total_xferred += bytes_xferred; | |
774 | } | |
775 | return total_xferred; | |
776 | } | |
777 | ||
778 | \f | |
779 | static void | |
780 | arc_files_info (ignore) | |
781 | struct target_ops *ignore; | |
782 | { | |
783 | puts_filtered ("Debugging a target over a serial line.\n"); | |
784 | } | |
785 | \f | |
786 | ||
787 | /* Read a single character from the remote end, masking it down to 7 bits. */ | |
788 | static int | |
789 | readchar () | |
790 | { | |
791 | int ch; | |
792 | ||
793 | ch = SERIAL_READCHAR (arc_desc, 0); | |
794 | ||
795 | switch (ch) | |
796 | { | |
797 | case SERIAL_EOF: | |
798 | error ("Remote connection closed"); | |
799 | case SERIAL_ERROR: | |
800 | perror_with_name ("Remote communication error"); | |
801 | case SERIAL_TIMEOUT: | |
802 | return ch; | |
803 | default: | |
804 | return ch & 0x7f; | |
805 | } | |
806 | } | |
807 | ||
808 | /* Send a packet to the remote machine, with error checking. | |
809 | The data of the packet is in BUF. */ | |
810 | ||
811 | static int | |
812 | putpkt (buf, len) | |
813 | char *buf; | |
814 | int len; | |
815 | { | |
816 | int i = 0; | |
817 | unsigned char csum = 0; | |
818 | ||
819 | while (i < len) | |
820 | { | |
821 | if (remote_debug) | |
822 | { | |
823 | printf_unfiltered ("Sending packet: %s...", buf); | |
824 | gdb_flush(gdb_stdout); | |
825 | } | |
826 | if (SERIAL_WRITE (arc_desc, buf, i)) | |
827 | perror_with_name ("putpkt: write failed"); | |
828 | i++; | |
829 | ||
830 | #if 0 | |
831 | /* This is wrong. If doing a long backtrace, the user should be | |
832 | able to get out next time we call QUIT, without anything as violent | |
833 | as interrupt_query. If we want to provide a way out of here | |
834 | without getting to the next QUIT, it should be based on hitting | |
835 | ^C twice as in arc_wait. */ | |
836 | if (quit_flag) | |
837 | { | |
838 | quit_flag = 0; | |
839 | interrupt_query (); | |
840 | } | |
841 | #endif | |
842 | } | |
843 | } | |
844 | ||
845 | /* Read a packet from the remote machine, with error checking, | |
846 | and store it in BUF. BUF is expected to be of size PBUFSIZ. | |
847 | If FOREVER, wait forever rather than timing out; this is used | |
848 | while the target is executing user code. */ | |
849 | ||
850 | static void | |
851 | getpkt (buf, len) | |
852 | char *buf; | |
853 | int len; | |
854 | { | |
855 | int c; | |
856 | int i; | |
857 | ||
858 | for (i = 0; i < len; i++) | |
859 | { | |
860 | c = readchar (); | |
861 | if (c == SERIAL_ERROR) | |
862 | { | |
863 | if (remote_debug) | |
864 | puts_filtered ("Read error.\n"); | |
865 | } | |
866 | } | |
867 | buf[i] = '\0'; | |
868 | ||
869 | if (remote_debug) | |
870 | fprintf_unfiltered (gdb_stderr, "Packet received: %s\n", buf); | |
871 | if (i != len) | |
872 | printf_unfiltered ("Ignoring packet error, continuing...\n"); | |
873 | } | |
874 | \f | |
875 | static void | |
876 | arc_kill () | |
877 | { | |
878 | /* For some mysterious reason, wait_for_inferior calls kill instead of | |
879 | mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */ | |
880 | if (kill_kludge) | |
881 | { | |
882 | kill_kludge = 0; | |
883 | target_mourn_inferior (); | |
884 | return; | |
885 | } | |
886 | target_mourn_inferior (); | |
887 | } | |
888 | ||
889 | static void | |
890 | arc_mourn () | |
891 | { | |
892 | unpush_target (&arc_ops); | |
893 | generic_mourn_inferior (); | |
894 | } | |
895 | ||
896 | \f | |
249abc98 | 897 | |
f0d795fa DE |
898 | static unsigned char big_break_insn[] = BIG_BREAKPOINT; |
899 | static unsigned char little_break_insn[] = LITTLE_BREAKPOINT; | |
900 | #define BREAKPOINT_LEN (sizeof little_break_insn) | |
249abc98 KH |
901 | |
902 | /* Insert a breakpoint on targets that don't have any better breakpoint | |
903 | support. We read the contents of the target location and stash it, | |
904 | then overwrite it with a breakpoint instruction. ADDR is the target | |
905 | location in the target machine. CONTENTS_CACHE is a pointer to | |
906 | memory allocated for saving the target contents. It is guaranteed | |
907 | by the caller to be long enough to save sizeof BREAKPOINT bytes (this | |
908 | is accomplished via BREAKPOINT_MAX). */ | |
909 | ||
910 | static int | |
911 | arc_insert_breakpoint (addr, contents_cache) | |
912 | CORE_ADDR addr; | |
913 | char *contents_cache; | |
914 | { | |
915 | int val; | |
916 | ||
f0d795fa | 917 | val = target_read_memory (addr, contents_cache, BREAKPOINT_LEN); |
249abc98 | 918 | if (val == 0) |
f0d795fa DE |
919 | { |
920 | if (TARGET_BYTE_ORDER == BIG_ENDIAN) | |
921 | val = target_write_memory (addr, (char *) big_break_insn, | |
922 | BREAKPOINT_LEN); | |
923 | else | |
924 | val = target_write_memory (addr, (char *) little_break_insn, | |
925 | BREAKPOINT_LEN); | |
926 | } | |
249abc98 KH |
927 | return val; |
928 | } | |
929 | ||
930 | static int | |
931 | arc_remove_breakpoint (addr, contents_cache) | |
932 | CORE_ADDR addr; | |
933 | char *contents_cache; | |
934 | { | |
f0d795fa | 935 | return target_write_memory (addr, contents_cache, BREAKPOINT_LEN); |
249abc98 KH |
936 | } |
937 | ||
938 | /* switch_command | |
939 | support 'switch' command to switch among the three processors of ARC. */ | |
940 | ||
941 | static void | |
942 | switch_command (args, fromtty) | |
943 | char *args; | |
944 | int fromtty; | |
945 | { | |
249abc98 | 946 | struct target_waitstatus status; |
abed6bc2 | 947 | int proc; |
249abc98 KH |
948 | |
949 | if (strncmp (args, "audio", 3) == 0) | |
950 | proc = 0; | |
951 | else if (strncmp (args, "graphic", 3) == 0) | |
952 | proc = 1; | |
953 | else if (strncmp (args, "host", 4) == 0) | |
954 | proc = 2; | |
955 | ||
abed6bc2 KH |
956 | curr_processor = proc; |
957 | ||
958 | switch (proc) | |
249abc98 | 959 | { |
abed6bc2 | 960 | case 0: |
f0d795fa DE |
961 | tm_print_insn = arc_get_disassembler (bfd_mach_arc_audio, |
962 | TARGET_BYTE_ORDER == BIG_ENDIAN); | |
abed6bc2 KH |
963 | break; |
964 | case 1: | |
f0d795fa DE |
965 | tm_print_insn = arc_get_disassembler (bfd_mach_arc_graphics, |
966 | TARGET_BYTE_ORDER == BIG_ENDIAN); | |
abed6bc2 KH |
967 | break; |
968 | case 2: | |
f0d795fa DE |
969 | tm_print_insn = arc_get_disassembler (bfd_mach_arc_host, |
970 | TARGET_BYTE_ORDER == BIG_ENDIAN); | |
abed6bc2 | 971 | break; |
249abc98 KH |
972 | } |
973 | ||
abed6bc2 | 974 | return; |
249abc98 KH |
975 | } |
976 | ||
977 | \f | |
978 | /* Define the target subroutine names */ | |
979 | ||
980 | struct target_ops arc_ops = { | |
981 | "arc", /* to_shortname */ | |
982 | "Remote target in arc-specific protocol", /* to_longname */ | |
983 | "Use a remote computer via a parallel line, using a arc-specific protocol.\n\ | |
984 | Specify the device it is connected to.", /* to_doc */ | |
985 | arc_open, /* to_open */ | |
986 | arc_close, /* to_close */ | |
987 | NULL, /* to_attach */ | |
988 | arc_detach, /* to_detach */ | |
989 | arc_resume, /* to_resume */ | |
990 | arc_wait, /* to_wait */ | |
991 | arc_fetch_registers, /* to_fetch_registers */ | |
992 | arc_store_registers, /* to_store_registers */ | |
993 | arc_prepare_to_store, /* to_prepare_to_store */ | |
994 | arc_xfer_memory, /* to_xfer_memory */ | |
995 | arc_files_info, /* to_files_info */ | |
996 | ||
997 | arc_insert_breakpoint, /* to_insert_breakpoint */ | |
998 | arc_remove_breakpoint, /* to_remove_breakpoint */ | |
999 | ||
1000 | NULL, /* to_terminal_init */ | |
1001 | NULL, /* to_terminal_inferior */ | |
1002 | NULL, /* to_terminal_ours_for_output */ | |
1003 | NULL, /* to_terminal_ours */ | |
1004 | NULL, /* to_terminal_info */ | |
1005 | arc_kill, /* to_kill */ | |
1006 | generic_load, /* to_load */ | |
1007 | NULL, /* to_lookup_symbol */ | |
1008 | NULL, /* to_create_inferior */ | |
1009 | arc_mourn, /* to_mourn_inferior */ | |
1010 | 0, /* to_can_run */ | |
1011 | 0, /* to_notice_signals */ | |
43fc25c8 | 1012 | 0, /* to_thread_alive */ |
249abc98 KH |
1013 | 0, /* to_stop */ |
1014 | process_stratum, /* to_stratum */ | |
1015 | NULL, /* to_next */ | |
1016 | 1, /* to_has_all_memory */ | |
1017 | 1, /* to_has_memory */ | |
1018 | 1, /* to_has_stack */ | |
1019 | 1, /* to_has_registers */ | |
1020 | 1, /* to_has_execution */ | |
1021 | NULL, /* sections */ | |
1022 | NULL, /* sections_end */ | |
1023 | OPS_MAGIC /* to_magic */ | |
1024 | }; | |
1025 | ||
1026 | void | |
1027 | _initialize_remote_arc () | |
1028 | { | |
1029 | add_target (&arc_ops); | |
249abc98 | 1030 | } |