Commit | Line | Data |
---|---|---|
48e696ce DE |
1 | /* Remote target communications for the ARC |
2 | Copyright 1995, 1997 Free Software Foundation, Inc. | |
249abc98 KH |
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 | ||
48e696ce DE |
121 | #define UNUSED1_PROCESSOR 0 |
122 | #define UNUSED2_PROCESSOR 1 | |
123 | #define UNUSED3_PROCESSOR 2 | |
249abc98 KH |
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 | ||
48e696ce | 127 | static int curr_processor = UNUSED1_PROCESSOR; |
249abc98 KH |
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 | ||
48e696ce | 325 | if (processor == UNUSED1_PROCESSOR) |
249abc98 KH |
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) */ | |
48e696ce | 339 | arc_set_addrreg (/*processor == ??? ? 0x10 :*/ 0xf); |
249abc98 KH |
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 | |
48e696ce DE |
471 | #if 0 |
472 | if ((curr_processor != UNUSED1_PROCESSOR) && | |
473 | !(cntl_reg & cntl_reg_halt_bit[UNUSED1_PROCESSOR])) | |
abed6bc2 | 474 | { |
48e696ce | 475 | cmd = cntl_reg | cntl_reg_halt_bit[UNUSED1_PROCESSOR]; |
abed6bc2 KH |
476 | arc_xfer_cntlreg (0, &cmd); |
477 | while (1) | |
478 | { | |
479 | unsigned char *p; | |
480 | ||
481 | ofunc = (void (*)()) signal (SIGINT, arc_interrupt); | |
482 | arc_xfer_cntlreg (1, &cntl_reg); | |
483 | signal (SIGINT, ofunc); | |
48e696ce | 484 | if (cntl_reg & cntl_reg_halt_bit[UNUSED1_PROCESSOR]) |
abed6bc2 KH |
485 | break; |
486 | } | |
487 | } | |
488 | ||
48e696ce | 489 | for (proc = UNUSED1_PROCESSOR ; proc <= UNUSED3_PROCESSOR; proc++) |
abed6bc2 KH |
490 | { |
491 | if ((cntl_reg & cntl_reg_halt_bit[proc])) | |
492 | continue; | |
493 | cmd = cntl_reg | cntl_reg_halt_bit[proc]; | |
494 | arc_xfer_cntlreg (0, &cmd); | |
495 | } | |
48e696ce | 496 | #endif |
abed6bc2 KH |
497 | |
498 | arc_xfer_reg (curr_processor, 1, 1, 0, &status_reg); | |
249abc98 KH |
499 | return inferior_pid; |
500 | } | |
501 | ||
502 | /* Number of bytes of registers this implements. */ | |
503 | static int register_bytes_found; | |
504 | ||
505 | /* Read the remote registers into the block REGS. */ | |
506 | /* Currently we just read all the registers, so we don't use regno. */ | |
507 | ||
508 | static void | |
509 | arc_fetch_registers (regno) | |
510 | int regno; | |
511 | { | |
512 | int i; | |
513 | char regs[REGISTER_BYTES]; | |
514 | ||
515 | /* Unimplemented registers read as all bits zero. */ | |
516 | memset (regs, 0, REGISTER_BYTES); | |
517 | ||
518 | /* get core register */ | |
519 | arc_set_addrreg (0); | |
520 | for (i = 0; i < AUX_BEG_REGNUM; i++) | |
521 | { | |
48e696ce | 522 | if (curr_processor == UNUSED1_PROCESSOR) |
249abc98 KH |
523 | arc_xfer_datareg (1, 0, 1, ®s[REGISTER_BYTE(i)]); |
524 | else | |
525 | arc_xfer_reg (curr_processor, 1, 0, regno, ®s[REGISTER_BYTE(i)]); | |
526 | } | |
527 | ||
528 | /* get aux register */ | |
529 | for (i = AUX_BEG_REGNUM; i < AUX_END_REGNUM; i++) | |
530 | { | |
531 | int auxregnum = aux_reg_map[curr_processor][i-AUX_BEG_REGNUM+1]; | |
532 | if (auxregnum == -1) | |
533 | continue; | |
534 | arc_xfer_reg (curr_processor, 1, 1, auxregnum, ®s[REGISTER_BYTE(i)]); | |
535 | } | |
536 | /* copy from status register to pc */ | |
537 | for (i = 1; i <= 3; i++) | |
538 | registers[REGISTER_BYTE (PC_REGNUM)+i] = | |
539 | registers[REGISTER_BYTE (STA_REGNUM)+i]; | |
540 | ||
541 | /* | |
542 | if (i != register_bytes_found) | |
543 | { | |
544 | register_bytes_found = i; | |
545 | if (!REGISTER_BYTES_OK (i)) | |
546 | warning ("Remote reply is too short: %s", buf); | |
547 | } | |
548 | */ | |
549 | ||
550 | for (i = 0; i < NUM_REGS; i++) | |
551 | supply_register (i, ®s[REGISTER_BYTE(i)]); | |
552 | } | |
553 | ||
554 | /* Prepare to store registers. Since we may send them all, | |
555 | we have to read out the ones we don't want to change first. */ | |
556 | ||
557 | static void | |
558 | arc_prepare_to_store () | |
559 | { | |
560 | /* Make sure the entire registers array is valid. */ | |
561 | read_register_bytes (0, (char *)NULL, REGISTER_BYTES); | |
562 | } | |
563 | ||
564 | /* Store register REGNO, or all registers if REGNO == -1, from the contents | |
565 | of REGISTERS. FIXME: ignores errors. */ | |
566 | ||
567 | static void | |
568 | arc_store_registers (regno) | |
569 | int regno; | |
570 | { | |
571 | int i; | |
572 | char *regp; | |
573 | ||
574 | /* Try storing a single register. */ | |
575 | if (regno >= 0) | |
576 | { | |
577 | int isaux = (regno >= AUX_BEG_REGNUM ? 1 : 0); | |
578 | ||
579 | regp = ®isters[REGISTER_BYTE (regno)]; | |
580 | arc_xfer_reg (curr_processor, 0, isaux, regno, regp); | |
581 | } | |
582 | ||
583 | /* store core regs */ | |
584 | arc_set_addrreg (0); | |
585 | for (i = 0; i < AUX_BEG_REGNUM; i++) | |
586 | { | |
587 | regp = ®isters[REGISTER_BYTE (i)]; | |
48e696ce | 588 | if (curr_processor == UNUSED1_PROCESSOR) |
249abc98 KH |
589 | arc_xfer_datareg (0, 0, 1, regp); |
590 | else | |
591 | arc_xfer_reg (curr_processor, 0, 0, regno, regp); | |
592 | } | |
593 | ||
594 | /* store aux regs */ | |
595 | /* copy pc back to status register */ | |
596 | for (i = 1; i <= 3; i++) | |
597 | registers[REGISTER_BYTE (STA_REGNUM)+i] = | |
598 | registers[REGISTER_BYTE (PC_REGNUM)+i]; | |
599 | for (i = AUX_BEG_REGNUM; i <= AUX_END_REGNUM; i++) | |
600 | { | |
601 | int auxregnum = aux_reg_map[curr_processor][i-AUX_BEG_REGNUM+1]; | |
602 | if (auxregnum == -1) | |
603 | continue; | |
604 | regp = ®isters[REGISTER_BYTE (i)]; | |
605 | arc_xfer_reg (curr_processor, 0, 1, auxregnum, regp); | |
606 | } | |
607 | ||
608 | } | |
609 | ||
610 | #if 0 | |
611 | /* Use of the data cache is disabled because it loses for looking at | |
612 | and changing hardware I/O ports and the like. Accepting `voltile' | |
613 | would perhaps be one way to fix it, but a better way which would | |
614 | win for more cases would be to use the executable file for the text | |
615 | segment, like the `icache' code below but done cleanly (in some | |
616 | target-independent place, perhaps in target_xfer_memory, perhaps | |
617 | based on assigning each target a speed or perhaps by some simpler | |
618 | mechanism). */ | |
619 | ||
620 | /* Read a word from remote address ADDR and return it. | |
621 | This goes through the data cache. */ | |
622 | ||
623 | static int | |
624 | arc_fetch_word (addr) | |
625 | CORE_ADDR addr; | |
626 | { | |
627 | #if 0 | |
628 | if (icache) | |
629 | { | |
630 | extern CORE_ADDR text_start, text_end; | |
631 | ||
632 | if (addr >= text_start && addr < text_end) | |
633 | { | |
634 | int buffer; | |
635 | xfer_core_file (addr, &buffer, sizeof (int)); | |
636 | return buffer; | |
637 | } | |
638 | } | |
639 | #endif | |
640 | return dcache_fetch (remote_dcache, addr); | |
641 | } | |
642 | ||
643 | /* Write a word WORD into remote address ADDR. | |
644 | This goes through the data cache. */ | |
645 | ||
646 | static void | |
647 | arc_store_word (addr, word) | |
648 | CORE_ADDR addr; | |
649 | int word; | |
650 | { | |
651 | dcache_poke (remote_dcache, addr, word); | |
652 | } | |
653 | #endif /* 0 */ | |
654 | ||
655 | \f | |
656 | /* Write memory data directly to the remote machine. | |
657 | This does not inform the data cache; the data cache uses this. | |
658 | MEMADDR is the address in the remote memory space. | |
659 | MYADDR is the address of the buffer in our space. | |
660 | LEN is the number of bytes. | |
661 | ||
662 | Returns number of bytes transferred, or 0 for error. */ | |
663 | ||
664 | static int | |
665 | arc_write_bytes (memaddr, myaddr, len) | |
666 | CORE_ADDR memaddr; | |
667 | unsigned char *myaddr; | |
668 | int len; | |
669 | { | |
670 | char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
671 | char buf2[6] = {0x21, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
672 | int i; | |
673 | char *p; | |
674 | ||
675 | /* We send target system values byte by byte, in increasing byte addresses*/ | |
676 | ||
677 | buf1[4] = memaddr & 0xff; | |
678 | buf1[3] = (memaddr >> 8) & 0xff; | |
679 | buf1[2] = (memaddr >> 16) & 0xff; | |
680 | buf1[1] = (memaddr >> 24) & 0xff; | |
681 | putpkt (buf1, 5); | |
682 | ||
683 | for (i = 0; i < len; ) | |
684 | { | |
685 | buf2[1] = myaddr[i++]; | |
686 | buf2[2] = myaddr[i++]; | |
687 | buf2[3] = myaddr[i++]; | |
688 | buf2[4] = myaddr[i++]; | |
689 | putpkt (buf2, 5); | |
690 | } | |
691 | ||
692 | return len; | |
693 | } | |
694 | ||
695 | /* Read memory data directly from the remote machine. | |
696 | This does not use the data cache; the data cache uses this. | |
697 | MEMADDR is the address in the remote memory space. | |
698 | MYADDR is the address of the buffer in our space. | |
699 | LEN is the number of bytes. | |
700 | ||
701 | Returns number of bytes transferred, or 0 for error. */ | |
702 | ||
703 | static int | |
704 | arc_read_bytes (memaddr, myaddr, len) | |
705 | CORE_ADDR memaddr; | |
706 | unsigned char *myaddr; | |
707 | int len; | |
708 | { | |
709 | unsigned char buf1[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; | |
710 | unsigned char buf2[3] = {0x31, 0x0, 0x0}; | |
711 | unsigned char buf3[5]; | |
712 | int i; | |
713 | char *p; | |
714 | ||
715 | /* We send target system values byte by byte, in increasing byte addresses*/ | |
716 | ||
717 | buf1[4] = memaddr & 0xff; | |
718 | buf1[3] = (memaddr >> 8) & 0xff; | |
719 | buf1[2] = (memaddr >> 16) & 0xff; | |
720 | buf1[1] = (memaddr >> 24) & 0xff; | |
721 | putpkt (buf1, 5); | |
722 | ||
723 | for (i = 0; i < len; ) | |
724 | { | |
725 | putpkt (buf2, 2); | |
726 | getpkt (buf3, 4); | |
727 | myaddr[i++] = buf3[1]; | |
728 | myaddr[i++] = buf3[2]; | |
729 | myaddr[i++] = buf3[3]; | |
730 | myaddr[i++] = buf3[4]; | |
731 | } | |
732 | ||
733 | return i; | |
734 | } | |
735 | ||
736 | \f | |
737 | /* Read or write LEN bytes from inferior memory at MEMADDR, transferring | |
738 | to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is | |
739 | nonzero. Returns length of data written or read; 0 for error. */ | |
740 | ||
741 | /* ARGSUSED */ | |
742 | static int | |
743 | arc_xfer_memory(memaddr, myaddr, len, should_write, target) | |
744 | CORE_ADDR memaddr; | |
745 | char *myaddr; | |
746 | int len; | |
747 | int should_write; | |
748 | struct target_ops *target; /* ignored */ | |
749 | { | |
750 | int xfersize; | |
751 | int bytes_xferred; | |
752 | int total_xferred = 0; | |
753 | ||
754 | while (len > 0) | |
755 | { | |
756 | if (len > MAXBUFBYTES) | |
757 | xfersize = MAXBUFBYTES; | |
758 | else | |
759 | xfersize = len; | |
760 | ||
761 | if (should_write) | |
762 | bytes_xferred = arc_write_bytes (memaddr, | |
763 | (unsigned char *)myaddr, xfersize); | |
764 | else | |
765 | bytes_xferred = arc_read_bytes (memaddr, | |
766 | (unsigned char *)myaddr, xfersize); | |
767 | ||
768 | /* If we get an error, we are done xferring. */ | |
769 | if (bytes_xferred == 0) | |
770 | break; | |
771 | ||
772 | memaddr += bytes_xferred; | |
773 | myaddr += bytes_xferred; | |
774 | len -= bytes_xferred; | |
775 | total_xferred += bytes_xferred; | |
776 | } | |
777 | return total_xferred; | |
778 | } | |
779 | ||
780 | \f | |
781 | static void | |
782 | arc_files_info (ignore) | |
783 | struct target_ops *ignore; | |
784 | { | |
785 | puts_filtered ("Debugging a target over a serial line.\n"); | |
786 | } | |
787 | \f | |
788 | ||
789 | /* Read a single character from the remote end, masking it down to 7 bits. */ | |
790 | static int | |
791 | readchar () | |
792 | { | |
793 | int ch; | |
794 | ||
795 | ch = SERIAL_READCHAR (arc_desc, 0); | |
796 | ||
797 | switch (ch) | |
798 | { | |
799 | case SERIAL_EOF: | |
800 | error ("Remote connection closed"); | |
801 | case SERIAL_ERROR: | |
802 | perror_with_name ("Remote communication error"); | |
803 | case SERIAL_TIMEOUT: | |
804 | return ch; | |
805 | default: | |
806 | return ch & 0x7f; | |
807 | } | |
808 | } | |
809 | ||
810 | /* Send a packet to the remote machine, with error checking. | |
811 | The data of the packet is in BUF. */ | |
812 | ||
813 | static int | |
814 | putpkt (buf, len) | |
815 | char *buf; | |
816 | int len; | |
817 | { | |
818 | int i = 0; | |
819 | unsigned char csum = 0; | |
820 | ||
821 | while (i < len) | |
822 | { | |
823 | if (remote_debug) | |
824 | { | |
825 | printf_unfiltered ("Sending packet: %s...", buf); | |
826 | gdb_flush(gdb_stdout); | |
827 | } | |
828 | if (SERIAL_WRITE (arc_desc, buf, i)) | |
829 | perror_with_name ("putpkt: write failed"); | |
830 | i++; | |
831 | ||
832 | #if 0 | |
833 | /* This is wrong. If doing a long backtrace, the user should be | |
834 | able to get out next time we call QUIT, without anything as violent | |
835 | as interrupt_query. If we want to provide a way out of here | |
836 | without getting to the next QUIT, it should be based on hitting | |
837 | ^C twice as in arc_wait. */ | |
838 | if (quit_flag) | |
839 | { | |
840 | quit_flag = 0; | |
841 | interrupt_query (); | |
842 | } | |
843 | #endif | |
844 | } | |
845 | } | |
846 | ||
847 | /* Read a packet from the remote machine, with error checking, | |
848 | and store it in BUF. BUF is expected to be of size PBUFSIZ. | |
849 | If FOREVER, wait forever rather than timing out; this is used | |
850 | while the target is executing user code. */ | |
851 | ||
852 | static void | |
853 | getpkt (buf, len) | |
854 | char *buf; | |
855 | int len; | |
856 | { | |
857 | int c; | |
858 | int i; | |
859 | ||
860 | for (i = 0; i < len; i++) | |
861 | { | |
862 | c = readchar (); | |
863 | if (c == SERIAL_ERROR) | |
864 | { | |
865 | if (remote_debug) | |
866 | puts_filtered ("Read error.\n"); | |
867 | } | |
868 | } | |
869 | buf[i] = '\0'; | |
870 | ||
871 | if (remote_debug) | |
872 | fprintf_unfiltered (gdb_stderr, "Packet received: %s\n", buf); | |
873 | if (i != len) | |
874 | printf_unfiltered ("Ignoring packet error, continuing...\n"); | |
875 | } | |
876 | \f | |
877 | static void | |
878 | arc_kill () | |
879 | { | |
880 | /* For some mysterious reason, wait_for_inferior calls kill instead of | |
881 | mourn after it gets TARGET_WAITKIND_SIGNALLED. Work around it. */ | |
882 | if (kill_kludge) | |
883 | { | |
884 | kill_kludge = 0; | |
885 | target_mourn_inferior (); | |
886 | return; | |
887 | } | |
888 | target_mourn_inferior (); | |
889 | } | |
890 | ||
891 | static void | |
892 | arc_mourn () | |
893 | { | |
894 | unpush_target (&arc_ops); | |
895 | generic_mourn_inferior (); | |
896 | } | |
897 | ||
898 | \f | |
249abc98 | 899 | |
f0d795fa DE |
900 | static unsigned char big_break_insn[] = BIG_BREAKPOINT; |
901 | static unsigned char little_break_insn[] = LITTLE_BREAKPOINT; | |
902 | #define BREAKPOINT_LEN (sizeof little_break_insn) | |
249abc98 KH |
903 | |
904 | /* Insert a breakpoint on targets that don't have any better breakpoint | |
905 | support. We read the contents of the target location and stash it, | |
906 | then overwrite it with a breakpoint instruction. ADDR is the target | |
907 | location in the target machine. CONTENTS_CACHE is a pointer to | |
908 | memory allocated for saving the target contents. It is guaranteed | |
909 | by the caller to be long enough to save sizeof BREAKPOINT bytes (this | |
910 | is accomplished via BREAKPOINT_MAX). */ | |
911 | ||
912 | static int | |
913 | arc_insert_breakpoint (addr, contents_cache) | |
914 | CORE_ADDR addr; | |
915 | char *contents_cache; | |
916 | { | |
917 | int val; | |
918 | ||
f0d795fa | 919 | val = target_read_memory (addr, contents_cache, BREAKPOINT_LEN); |
249abc98 | 920 | if (val == 0) |
f0d795fa DE |
921 | { |
922 | if (TARGET_BYTE_ORDER == BIG_ENDIAN) | |
923 | val = target_write_memory (addr, (char *) big_break_insn, | |
924 | BREAKPOINT_LEN); | |
925 | else | |
926 | val = target_write_memory (addr, (char *) little_break_insn, | |
927 | BREAKPOINT_LEN); | |
928 | } | |
249abc98 KH |
929 | return val; |
930 | } | |
931 | ||
932 | static int | |
933 | arc_remove_breakpoint (addr, contents_cache) | |
934 | CORE_ADDR addr; | |
935 | char *contents_cache; | |
936 | { | |
f0d795fa | 937 | return target_write_memory (addr, contents_cache, BREAKPOINT_LEN); |
249abc98 | 938 | } |
249abc98 KH |
939 | \f |
940 | /* Define the target subroutine names */ | |
941 | ||
942 | struct target_ops arc_ops = { | |
943 | "arc", /* to_shortname */ | |
944 | "Remote target in arc-specific protocol", /* to_longname */ | |
945 | "Use a remote computer via a parallel line, using a arc-specific protocol.\n\ | |
946 | Specify the device it is connected to.", /* to_doc */ | |
947 | arc_open, /* to_open */ | |
948 | arc_close, /* to_close */ | |
949 | NULL, /* to_attach */ | |
950 | arc_detach, /* to_detach */ | |
951 | arc_resume, /* to_resume */ | |
952 | arc_wait, /* to_wait */ | |
953 | arc_fetch_registers, /* to_fetch_registers */ | |
954 | arc_store_registers, /* to_store_registers */ | |
955 | arc_prepare_to_store, /* to_prepare_to_store */ | |
956 | arc_xfer_memory, /* to_xfer_memory */ | |
957 | arc_files_info, /* to_files_info */ | |
958 | ||
959 | arc_insert_breakpoint, /* to_insert_breakpoint */ | |
960 | arc_remove_breakpoint, /* to_remove_breakpoint */ | |
961 | ||
962 | NULL, /* to_terminal_init */ | |
963 | NULL, /* to_terminal_inferior */ | |
964 | NULL, /* to_terminal_ours_for_output */ | |
965 | NULL, /* to_terminal_ours */ | |
966 | NULL, /* to_terminal_info */ | |
967 | arc_kill, /* to_kill */ | |
968 | generic_load, /* to_load */ | |
969 | NULL, /* to_lookup_symbol */ | |
970 | NULL, /* to_create_inferior */ | |
971 | arc_mourn, /* to_mourn_inferior */ | |
972 | 0, /* to_can_run */ | |
973 | 0, /* to_notice_signals */ | |
43fc25c8 | 974 | 0, /* to_thread_alive */ |
249abc98 KH |
975 | 0, /* to_stop */ |
976 | process_stratum, /* to_stratum */ | |
977 | NULL, /* to_next */ | |
978 | 1, /* to_has_all_memory */ | |
979 | 1, /* to_has_memory */ | |
980 | 1, /* to_has_stack */ | |
981 | 1, /* to_has_registers */ | |
982 | 1, /* to_has_execution */ | |
983 | NULL, /* sections */ | |
984 | NULL, /* sections_end */ | |
985 | OPS_MAGIC /* to_magic */ | |
986 | }; | |
987 | ||
988 | void | |
989 | _initialize_remote_arc () | |
990 | { | |
991 | add_target (&arc_ops); | |
249abc98 | 992 | } |