gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / sim / common / dv-pal.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3 Copyright 2002-2020 Free Software Foundation, Inc.
4
5 Contributed by Andrew Cagney and Red Hat.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #include "config.h"
23 #include "sim-main.h"
24 #include "hw-main.h"
25 #include "sim-io.h"
26
27 /* NOTE: pal is naughty and grubs around looking at things outside of
28 its immediate domain */
29 #include "hw-tree.h"
30
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #else
34 #ifdef HAVE_STRINGS_H
35 #include <strings.h>
36 #endif
37 #endif
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #ifdef HAVE_STDLIB_H
43 #include <stdlib.h>
44 #endif
45
46 /* DEVICE
47
48
49 pal - glue logic device containing assorted junk
50
51
52 DESCRIPTION
53
54
55 Typical hardware dependant hack. This device allows the firmware
56 to gain access to all the things the firmware needs (but the OS
57 doesn't).
58
59 The pal contains the following registers:
60
61 |0 reset register (write, 8bit)
62 |4 processor id register (read, 8bit)
63 |8 interrupt register (8 - port, 9 - level) (write, 16bit)
64 |12 processor count register (read, 8bit)
65
66 |16 tty input fifo register (read, 8bit)
67 |20 tty input status register (read, 8bit)
68 |24 tty output fifo register (write, 8bit)
69 |28 tty output status register (read, 8bit)
70
71 |32 countdown register (read/write, 32bit, big-endian)
72 |36 countdown value register (read, 32bit, big-endian)
73 |40 timer register (read/write, 32bit, big-endian)
74 |44 timer value register (read, 32bit, big-endian)
75
76 RESET (write): halts the simulator. The value written to the
77 register is used as an exit status.
78
79 PROCESSOR ID (read): returns the processor identifier (0 .. N-1) of
80 the processor performing the read.
81
82 INTERRUPT (write): This register must be written using a two byte
83 store. The low byte specifies a port and the upper byte specifies
84 the a level. LEVEL is driven on the specified port. By
85 convention, the pal's interrupt ports (int0, int1, ...) are wired
86 up to the corresponding processor's level sensative external
87 interrupt pin. Eg: A two byte write to address 8 of 0x0102
88 (big-endian) will result in processor 2's external interrupt pin
89 being asserted.
90
91 PROCESSOR COUNT (read): returns the total number of processors
92 active in the current simulation.
93
94 TTY INPUT FIFO (read): if the TTY input status register indicates a
95 character is available by being nonzero, returns the next available
96 character from the pal's tty input port.
97
98 TTY OUTPUT FIFO (write): if the TTY output status register
99 indicates the output fifo is not full by being nonzero, outputs the
100 character written to the tty's output port.
101
102 COUNDOWN (read/write): The countdown registers provide a
103 non-repeating timed interrupt source. Writing a 32 bit big-endian
104 zero value to this register clears the countdown timer. Writing a
105 non-zero 32 bit big-endian value to this register sets the
106 countdown timer to expire in VALUE ticks (ticks is target
107 dependant). Reading the countdown register returns the last value
108 writen.
109
110 COUNTDOWN VALUE (read): Reading this 32 bit big-endian register
111 returns the number of ticks remaining until the countdown timer
112 expires.
113
114 TIMER (read/write): The timer registers provide a periodic timed
115 interrupt source. Writing a 32 bit big-endian zero value to this
116 register clears the periodic timer. Writing a 32 bit non-zero
117 value to this register sets the periodic timer to triger every
118 VALUE ticks (ticks is target dependant). Reading the timer
119 register returns the last value written.
120
121 TIMER VALUE (read): Reading this 32 bit big-endian register returns
122 the number of ticks until the next periodic interrupt.
123
124
125 PROPERTIES
126
127
128 reg = <address> <size> (required)
129
130 Specify the address (within the parent bus) that this device is to
131 be located.
132
133 poll? = <boolean>
134
135 If present and true, indicates that the device should poll its
136 input.
137
138
139 PORTS
140
141
142 int[0..NR_PROCESSORS] (output)
143
144 Driven as a result of a write to the interrupt-port /
145 interrupt-level register pair.
146
147
148 countdown
149
150 Driven whenever the countdown counter reaches zero.
151
152
153 timer
154
155 Driven whenever the timer counter reaches zero.
156
157
158 BUGS
159
160
161 At present the common simulator framework does not support input
162 polling.
163
164 */
165
166
167 enum {
168 hw_pal_reset_register = 0x0,
169 hw_pal_cpu_nr_register = 0x4,
170 hw_pal_int_register = 0x8,
171 hw_pal_nr_cpu_register = 0xa,
172 hw_pal_read_fifo = 0x10,
173 hw_pal_read_status = 0x14,
174 hw_pal_write_fifo = 0x18,
175 hw_pal_write_status = 0x1a,
176 hw_pal_countdown = 0x20,
177 hw_pal_countdown_value = 0x24,
178 hw_pal_timer = 0x28,
179 hw_pal_timer_value = 0x2c,
180 hw_pal_address_mask = 0x3f,
181 };
182
183
184 typedef struct _hw_pal_console_buffer {
185 char buffer;
186 int status;
187 } hw_pal_console_buffer;
188
189 typedef struct _hw_pal_counter {
190 struct hw_event *handler;
191 signed64 start;
192 unsigned32 delta;
193 int periodic_p;
194 } hw_pal_counter;
195
196
197 typedef struct _hw_pal_device {
198 hw_pal_console_buffer input;
199 hw_pal_console_buffer output;
200 hw_pal_counter countdown;
201 hw_pal_counter timer;
202 struct hw *disk;
203 do_hw_poll_read_method *reader;
204 } hw_pal_device;
205
206 enum {
207 COUNTDOWN_PORT,
208 TIMER_PORT,
209 INT_PORT,
210 };
211
212 static const struct hw_port_descriptor hw_pal_ports[] = {
213 { "countdown", COUNTDOWN_PORT, 0, output_port, },
214 { "timer", TIMER_PORT, 0, output_port, },
215 { "int", INT_PORT, MAX_NR_PROCESSORS, output_port, },
216 { NULL, 0, 0, 0 }
217 };
218
219
220 /* countdown and simple timer */
221
222 static void
223 do_counter_event (struct hw *me,
224 void *data)
225 {
226 hw_pal_counter *counter = (hw_pal_counter *) data;
227 if (counter->periodic_p)
228 {
229 HW_TRACE ((me, "timer expired"));
230 counter->start = hw_event_queue_time (me);
231 hw_port_event (me, TIMER_PORT, 1);
232 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
233 }
234 else
235 {
236 HW_TRACE ((me, "countdown expired"));
237 counter->delta = 0;
238 hw_port_event (me, COUNTDOWN_PORT, 1);
239 }
240 }
241
242 static void
243 do_counter_read (struct hw *me,
244 hw_pal_device *pal,
245 const char *reg,
246 hw_pal_counter *counter,
247 unsigned32 *word,
248 unsigned nr_bytes)
249 {
250 unsigned32 val;
251 if (nr_bytes != 4)
252 hw_abort (me, "%s - bad read size must be 4 bytes", reg);
253 val = counter->delta;
254 HW_TRACE ((me, "read - %s %ld", reg, (long) val));
255 *word = H2BE_4 (val);
256 }
257
258 static void
259 do_counter_value (struct hw *me,
260 hw_pal_device *pal,
261 const char *reg,
262 hw_pal_counter *counter,
263 unsigned32 *word,
264 unsigned nr_bytes)
265 {
266 unsigned32 val;
267 if (nr_bytes != 4)
268 hw_abort (me, "%s - bad read size must be 4 bytes", reg);
269 if (counter->delta != 0)
270 val = (counter->start + counter->delta
271 - hw_event_queue_time (me));
272 else
273 val = 0;
274 HW_TRACE ((me, "read - %s %ld", reg, (long) val));
275 *word = H2BE_4 (val);
276 }
277
278 static void
279 do_counter_write (struct hw *me,
280 hw_pal_device *pal,
281 const char *reg,
282 hw_pal_counter *counter,
283 const unsigned32 *word,
284 unsigned nr_bytes)
285 {
286 if (nr_bytes != 4)
287 hw_abort (me, "%s - bad write size must be 4 bytes", reg);
288 if (counter->handler != NULL)
289 {
290 hw_event_queue_deschedule (me, counter->handler);
291 counter->handler = NULL;
292 }
293 counter->delta = BE2H_4 (*word);
294 counter->start = hw_event_queue_time (me);
295 HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta));
296 if (counter->delta > 0)
297 hw_event_queue_schedule (me, counter->delta, do_counter_event, counter);
298 }
299
300
301
302
303 /* check the console for an available character */
304 static void
305 scan_hw_pal (struct hw *me)
306 {
307 hw_pal_device *hw_pal = (hw_pal_device *)hw_data (me);
308 char c;
309 int count;
310 count = do_hw_poll_read (me, hw_pal->reader, 0/*STDIN*/, &c, sizeof (c));
311 switch (count)
312 {
313 case HW_IO_NOT_READY:
314 case HW_IO_EOF:
315 hw_pal->input.buffer = 0;
316 hw_pal->input.status = 0;
317 break;
318 default:
319 hw_pal->input.buffer = c;
320 hw_pal->input.status = 1;
321 }
322 }
323
324 /* write the character to the hw_pal */
325
326 static void
327 write_hw_pal (struct hw *me,
328 char val)
329 {
330 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
331 sim_io_write_stdout (hw_system (me), &val, 1);
332 hw_pal->output.buffer = val;
333 hw_pal->output.status = 1;
334 }
335
336
337 /* Reads/writes */
338
339 static unsigned
340 hw_pal_io_read_buffer (struct hw *me,
341 void *dest,
342 int space,
343 unsigned_word addr,
344 unsigned nr_bytes)
345 {
346 hw_pal_device *hw_pal = (hw_pal_device *) hw_data (me);
347 unsigned_1 *byte = (unsigned_1 *) dest;
348 memset (dest, 0, nr_bytes);
349 switch (addr & hw_pal_address_mask)
350 {
351
352 case hw_pal_cpu_nr_register:
353 *byte = CPU_INDEX (hw_system_cpu (me));
354 HW_TRACE ((me, "read - cpu-nr %d\n", *byte));
355 break;
356
357 case hw_pal_nr_cpu_register:
358 if (hw_tree_find_property (me, "/openprom/options/smp") == NULL)
359 {
360 *byte = 1;
361 HW_TRACE ((me, "read - nr-cpu %d (not defined)\n", *byte));
362 }
363 else
364 {
365 *byte = hw_tree_find_integer_property (me, "/openprom/options/smp");
366 HW_TRACE ((me, "read - nr-cpu %d\n", *byte));
367 }
368 break;
369
370 case hw_pal_read_fifo:
371 *byte = hw_pal->input.buffer;
372 HW_TRACE ((me, "read - input-fifo %d\n", *byte));
373 break;
374
375 case hw_pal_read_status:
376 scan_hw_pal (me);
377 *byte = hw_pal->input.status;
378 HW_TRACE ((me, "read - input-status %d\n", *byte));
379 break;
380
381 case hw_pal_write_fifo:
382 *byte = hw_pal->output.buffer;
383 HW_TRACE ((me, "read - output-fifo %d\n", *byte));
384 break;
385
386 case hw_pal_write_status:
387 *byte = hw_pal->output.status;
388 HW_TRACE ((me, "read - output-status %d\n", *byte));
389 break;
390
391 case hw_pal_countdown:
392 do_counter_read (me, hw_pal, "countdown",
393 &hw_pal->countdown, dest, nr_bytes);
394 break;
395
396 case hw_pal_countdown_value:
397 do_counter_value (me, hw_pal, "countdown-value",
398 &hw_pal->countdown, dest, nr_bytes);
399 break;
400
401 case hw_pal_timer:
402 do_counter_read (me, hw_pal, "timer",
403 &hw_pal->timer, dest, nr_bytes);
404 break;
405
406 case hw_pal_timer_value:
407 do_counter_value (me, hw_pal, "timer-value",
408 &hw_pal->timer, dest, nr_bytes);
409 break;
410
411 default:
412 HW_TRACE ((me, "read - ???\n"));
413 break;
414
415 }
416 return nr_bytes;
417 }
418
419
420 static unsigned
421 hw_pal_io_write_buffer (struct hw *me,
422 const void *source,
423 int space,
424 unsigned_word addr,
425 unsigned nr_bytes)
426 {
427 hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me);
428 unsigned_1 *byte = (unsigned_1 *) source;
429
430 switch (addr & hw_pal_address_mask)
431 {
432
433 case hw_pal_reset_register:
434 hw_halt (me, sim_exited, byte[0]);
435 break;
436
437 case hw_pal_int_register:
438 hw_port_event (me,
439 INT_PORT + byte[0], /*port*/
440 (nr_bytes > 1 ? byte[1] : 0)); /* val */
441 break;
442
443 case hw_pal_read_fifo:
444 hw_pal->input.buffer = byte[0];
445 HW_TRACE ((me, "write - input-fifo %d\n", byte[0]));
446 break;
447
448 case hw_pal_read_status:
449 hw_pal->input.status = byte[0];
450 HW_TRACE ((me, "write - input-status %d\n", byte[0]));
451 break;
452
453 case hw_pal_write_fifo:
454 write_hw_pal (me, byte[0]);
455 HW_TRACE ((me, "write - output-fifo %d\n", byte[0]));
456 break;
457
458 case hw_pal_write_status:
459 hw_pal->output.status = byte[0];
460 HW_TRACE ((me, "write - output-status %d\n", byte[0]));
461 break;
462
463 case hw_pal_countdown:
464 do_counter_write (me, hw_pal, "countdown",
465 &hw_pal->countdown, source, nr_bytes);
466 break;
467
468 case hw_pal_timer:
469 do_counter_write (me, hw_pal, "timer",
470 &hw_pal->timer, source, nr_bytes);
471 break;
472
473 }
474 return nr_bytes;
475 }
476
477
478 /* instances of the hw_pal struct hw */
479
480 #if NOT_YET
481 static void
482 hw_pal_instance_delete_callback (hw_instance *instance)
483 {
484 /* nothing to delete, the hw_pal is attached to the struct hw */
485 return;
486 }
487 #endif
488
489 #if NOT_YET
490 static int
491 hw_pal_instance_read_callback (hw_instance *instance,
492 void *buf,
493 unsigned_word len)
494 {
495 DITRACE (pal, ("read - %s (%ld)", (const char*) buf, (long int) len));
496 return sim_io_read_stdin (buf, len);
497 }
498 #endif
499
500 #if NOT_YET
501 static int
502 hw_pal_instance_write_callback (hw_instance *instance,
503 const void *buf,
504 unsigned_word len)
505 {
506 int i;
507 const char *chp = buf;
508 hw_pal_device *hw_pal = hw_instance_data (instance);
509 DITRACE (pal, ("write - %s (%ld)", (const char*) buf, (long int) len));
510 for (i = 0; i < len; i++)
511 write_hw_pal (hw_pal, chp[i]);
512 sim_io_flush_stdoutput ();
513 return i;
514 }
515 #endif
516
517 #if NOT_YET
518 static const hw_instance_callbacks hw_pal_instance_callbacks = {
519 hw_pal_instance_delete_callback,
520 hw_pal_instance_read_callback,
521 hw_pal_instance_write_callback,
522 };
523 #endif
524
525 #if 0
526 static hw_instance *
527 hw_pal_create_instance (struct hw *me,
528 const char *path,
529 const char *args)
530 {
531 return hw_create_instance_from (me, NULL,
532 hw_data (me),
533 path, args,
534 &hw_pal_instance_callbacks);
535 }
536 #endif
537
538
539 static void
540 hw_pal_attach_address (struct hw *me,
541 int level,
542 int space,
543 address_word addr,
544 address_word nr_bytes,
545 struct hw *client)
546 {
547 hw_pal_device *pal = (hw_pal_device*) hw_data (me);
548 pal->disk = client;
549 }
550
551
552 #if 0
553 static hw_callbacks const hw_pal_callbacks = {
554 { generic_hw_init_address, },
555 { hw_pal_attach_address, }, /* address */
556 { hw_pal_io_read_buffer_callback,
557 hw_pal_io_write_buffer_callback, },
558 { NULL, }, /* DMA */
559 { NULL, NULL, hw_pal_interrupt_ports }, /* interrupt */
560 { generic_hw_unit_decode,
561 generic_hw_unit_encode,
562 generic_hw_address_to_attach_address,
563 generic_hw_size_to_attach_size },
564 hw_pal_create_instance,
565 };
566 #endif
567
568
569 static void
570 hw_pal_finish (struct hw *hw)
571 {
572 /* create the descriptor */
573 hw_pal_device *hw_pal = HW_ZALLOC (hw, hw_pal_device);
574 hw_pal->output.status = 1;
575 hw_pal->output.buffer = '\0';
576 hw_pal->input.status = 0;
577 hw_pal->input.buffer = '\0';
578 set_hw_data (hw, hw_pal);
579 set_hw_attach_address (hw, hw_pal_attach_address);
580 set_hw_io_read_buffer (hw, hw_pal_io_read_buffer);
581 set_hw_io_write_buffer (hw, hw_pal_io_write_buffer);
582 set_hw_ports (hw, hw_pal_ports);
583 /* attach ourselves */
584 do_hw_attach_regs (hw);
585 /* If so configured, enable polled input */
586 if (hw_find_property (hw, "poll?") != NULL
587 && hw_find_boolean_property (hw, "poll?"))
588 {
589 hw_pal->reader = sim_io_poll_read;
590 }
591 else
592 {
593 hw_pal->reader = sim_io_read;
594 }
595 /* tag the periodic timer */
596 hw_pal->timer.periodic_p = 1;
597 }
598
599
600 const struct hw_descriptor dv_pal_descriptor[] = {
601 { "pal", hw_pal_finish, },
602 { NULL, NULL },
603 };
This page took 0.070029 seconds and 4 git commands to generate.