PowerPC64 ld segfault with code in non-executable sections
[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 3 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, see <http://www.gnu.org/licenses/>.
17  
18     */
19
20
21 #ifndef _HW_CPU_C_
22 #define _HW_CPU_C_
23
24 #ifndef STATIC_INLINE_HW_CPU
25 #define STATIC_INLINE_HW_CPU STATIC_INLINE
26 #endif
27
28 #include "device_table.h"
29 #include "hw_cpu.h"
30
31 #include "interrupts.h"
32 #include "cpu.h"
33
34
35 /* DEVICE
36
37
38    cpu - Interface to a Processor
39
40
41    DESCRIPTION
42
43
44    The CPU device provides the connection between the interrupt net
45    (linking the devices and the interrupt controller) and the
46    simulated model of each processor.  This device contains interrupt
47    ports that correspond directly to the external interrupt stimulus
48    that can be sent to a given processor.  Sending an interrupt to one
49    of the ports results in an interrupt being delivered to the
50    corresponding processor.
51
52    Typically, an interrupt controller would have its inputs connected
53    to device interrupt sources and its outputs (sreset, int, et.al.)
54    connected to this device.
55
56
57    PROPERTIES
58
59
60    cpu-nr = <integer> (required)
61
62
63    Specify the processor (1..N) that this cpu device node should
64    control.
65
66
67    EXAMPLES
68
69    
70    Connect an OpenPIC interrupt controller interrupt ports to
71    processor zero.
72
73    | -o '/phb/opic@0 > irq0 int /cpus/cpu@0' \
74    | -o '/phb/opic@0 > init hreset /cpus/cpu@0' \
75
76
77    */
78
79 typedef struct _hw_cpu_device {
80   int cpu_nr;
81   cpu *processor;
82 } hw_cpu_device;
83
84 static const device_interrupt_port_descriptor hw_cpu_interrupt_ports[] = {
85   { "hreset", hw_cpu_hard_reset },
86   { "sreset", hw_cpu_soft_reset },
87   { "int", hw_cpu_external_interrupt },
88   { "mci", hw_cpu_machine_check_interrupt },
89   { "smi", hw_cpu_system_management_interrupt },
90   { NULL }
91 };
92
93
94 static void *
95 hw_cpu_create(const char *name,
96               const device_unit *unit_address,
97               const char *args)
98 {
99   hw_cpu_device *hw_cpu = ZALLOC(hw_cpu_device);
100   return hw_cpu;
101 }
102
103
104 /* during address initialization ensure that any missing cpu
105    properties are added to this devices node */
106
107 static void
108 hw_cpu_init_address(device *me)
109 {
110   hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
111   /* populate the node with properties */
112   /* clear our data */
113   memset(hw_cpu, 0x0, sizeof(hw_cpu_device));
114   hw_cpu->cpu_nr = device_find_integer_property(me, "cpu-nr");
115   hw_cpu->processor = psim_cpu(device_system(me), hw_cpu->cpu_nr);
116 }
117
118
119 /* Take the interrupt and synchronize its delivery with the clock.  If
120    we've not yet scheduled an interrupt for the next clock tick, take
121    the oportunity to do it now */
122
123 static void
124 hw_cpu_interrupt_event(device *me,
125                        int my_port,
126                        device *source,
127                        int source_port,
128                        int level,
129                        cpu *processor,
130                        unsigned_word cia)
131 {
132   hw_cpu_device *hw_cpu = (hw_cpu_device*)device_data(me);
133   if (my_port < 0 || my_port >= hw_cpu_nr_interrupt_ports)
134     error("hw_cpu_interrupt_event_callback: interrupt port out of range %d\n",
135           my_port);
136   switch (my_port) {
137     /*case hw_cpu_hard_reset:*/
138     /*case hw_cpu_soft_reset:*/
139   case hw_cpu_external_interrupt:
140     external_interrupt(hw_cpu->processor, level);
141     break;
142     /*case hw_cpu_machine_check_interrupt:*/
143   default:
144     error("hw_cpu_deliver_interrupt: unimplemented interrupt port %d\n",
145           my_port);
146     break;
147   }
148 }
149
150
151 static device_callbacks const hw_cpu_callbacks = {
152   { hw_cpu_init_address, }, /* init */
153   { NULL, }, /* address */
154   { NULL, }, /* io */
155   { NULL, }, /* DMA */
156   { hw_cpu_interrupt_event, NULL, hw_cpu_interrupt_ports }, /* interrupts */
157   { NULL, NULL, },
158 };
159
160 const device_descriptor hw_cpu_device_descriptor[] = {
161   { "hw-cpu", hw_cpu_create, &hw_cpu_callbacks },
162   { "cpu", hw_cpu_create, &hw_cpu_callbacks },
163   { NULL, },
164 };
165
166 #endif /* _HW_CPU_C_ */