update from Andrew
[external/binutils.git] / sim / ppc / hw_cpu.c
1 /*  This file is part of the program psim.
2
3     Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  
19     */
20
21
22 #ifndef _HW_CPU_C_
23 #define _HW_CPU_C_
24
25 #ifndef STATIC_INLINE_HW_CPU
26 #define STATIC_INLINE_HW_CPU STATIC_INLINE
27 #endif
28
29 #include "device_table.h"
30 #include "hw_cpu.h"
31
32 #include "interrupts.h"
33 #include "cpu.h"
34
35
36 /* CPU (HW) - Interface to a Processor
37
38    Description:
39
40    The CPU device provides the connection between the interrupt net
41    (linking the devices and the interrupt controller) and the
42    simulated model of each processor.  This device contains interrupt
43    ports that correspond directly to the external interrupt stimulus
44    that can be sent to a given processor.  Sending an interrupt to one
45    of the ports results in an interrupt being delivered to the
46    corresponding processor.
47
48    Typically, an interrupt controller would have its inputs connected
49    to device interrupt sources and its outputs (sreset, int, et.al.)
50    connected to this device.
51
52    Properties:
53
54    cpu-nr = <integer>.  Specify the processor (1..N) that this cpu
55    device node should control. */
56
57 typedef struct _hw_cpu_device {
58   int cpu_nr;
59   cpu *processor;
60 } hw_cpu_device;
61
62 static const device_interrupt_port_descriptor hw_cpu_interrupt_ports[] = {
63   { "hreset", hw_cpu_hard_reset },
64   { "sreset", hw_cpu_soft_reset },
65   { "int", hw_cpu_external_interrupt },
66   { "mci", hw_cpu_machine_check_interrupt },
67   { "smi", hw_cpu_system_management_interrupt },
68   { NULL }
69 };
70
71
72 static void *
73 hw_cpu_create(const char *name,
74               const device_unit *unit_address,
75               const char *args,
76               device *parent)
77 {
78   hw_cpu_device *hw_cpu = ZALLOC(hw_cpu_device);
79   return hw_cpu;
80 }
81
82
83 /* during address initialization ensure that any missing cpu
84    properties are added to this devices node */
85
86 static void
87 hw_cpu_init_address(device *me)
88 {
89   hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
90   /* populate the node with properties */
91   /* clear our data */
92   memset(hw_cpu, 0x0, sizeof(hw_cpu_device));
93   hw_cpu->cpu_nr = device_find_integer_property(me, "cpu-nr");
94   hw_cpu->processor = psim_cpu(device_system(me), hw_cpu->cpu_nr);
95 }
96
97
98 /* Take the interrupt and synchronize its delivery with the clock.  If
99    we've not yet scheduled an interrupt for the next clock tick, take
100    the oportunity to do it now */
101
102 static void
103 hw_cpu_interrupt_event(device *me,
104                        int my_port,
105                        device *source,
106                        int source_port,
107                        int level,
108                        cpu *processor,
109                        unsigned_word cia)
110 {
111   hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
112   if (my_port < 0 || my_port >= hw_cpu_nr_interrupt_ports)
113     error("hw_cpu_interrupt_event_callback: interrupt port out of range %d\n",
114           my_port);
115   switch (my_port) {
116     /*case hw_cpu_hard_reset:*/
117     /*case hw_cpu_soft_reset:*/
118   case hw_cpu_external_interrupt:
119     external_interrupt(hw_cpu->processor, level);
120     break;
121     /*case hw_cpu_machine_check_interrupt:*/
122   default:
123     error("hw_cpu_deliver_interrupt: unimplemented interrupt port %d\n",
124           my_port);
125     break;
126   }
127 }
128
129
130 static device_callbacks const hw_cpu_callbacks = {
131   { hw_cpu_init_address, }, /* init */
132   { NULL, }, /* address */
133   { NULL, }, /* io */
134   { NULL, }, /* DMA */
135   { hw_cpu_interrupt_event, NULL, hw_cpu_interrupt_ports }, /* interrupts */
136   { NULL, NULL, },
137 };
138
139 const device_descriptor hw_cpu_device_descriptor[] = {
140   { "hw-cpu", hw_cpu_create, &hw_cpu_callbacks },
141   { "cpu", hw_cpu_create, &hw_cpu_callbacks },
142   { NULL, },
143 };
144
145 #endif /* _HW_CPU_C_ */