x86: fold narrowing VCVT* templates
[external/binutils.git] / sim / common / dv-pal.c
1 /* The common simulator framework for GDB, the GNU Debugger.
2
3    Copyright 2002-2018 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 };