Silence uninitialized warning on ehdr_start_save
[platform/upstream/binutils.git] / sim / common / hw-ports.c
1 /* Hardware ports.
2    Copyright (C) 1998-2014 Free Software Foundation, Inc.
3    Contributed by Andrew Cagney and Cygnus Solutions.
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20
21 #include "hw-main.h"
22 #include "hw-base.h"
23
24 #ifdef HAVE_STDLIB_H
25 #include <stdlib.h>
26 #endif
27
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #else
31 #ifdef HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
34 #endif
35
36 #include <ctype.h>
37
38
39 struct hw_port_edge
40 {
41   int my_port;
42   struct hw *dest;
43   int dest_port;
44   struct hw_port_edge *next;
45   object_disposition disposition;
46 };
47
48 struct hw_port_data
49 {
50   hw_port_event_method *to_port_event;
51   const struct hw_port_descriptor *ports;
52   struct hw_port_edge *edges;
53 };
54
55 const struct hw_port_descriptor empty_hw_ports[] =
56 {
57   { NULL, 0, 0, 0 },
58 };
59
60 static void
61 panic_hw_port_event (struct hw *me,
62                      int my_port,
63                      struct hw *source,
64                      int source_port,
65                      int level)
66 {
67   hw_abort (me, "no port method");
68 }
69
70 void
71 create_hw_port_data (struct hw *me)
72 {
73   me->ports_of_hw = HW_ZALLOC (me, struct hw_port_data);
74   set_hw_port_event (me, panic_hw_port_event);
75   set_hw_ports (me, empty_hw_ports);
76 }
77
78 void
79 delete_hw_port_data (struct hw *me)
80 {
81   hw_free (me, me->ports_of_hw);
82   me->ports_of_hw = NULL;
83 }
84
85 void
86 set_hw_ports (struct hw *me,
87               const struct hw_port_descriptor ports[])
88 {
89   me->ports_of_hw->ports = ports;
90 }
91
92 void
93 set_hw_port_event (struct hw *me,
94                    hw_port_event_method *port_event)
95 {
96   me->ports_of_hw->to_port_event = port_event;
97 }
98
99
100 static void
101 attach_hw_port_edge (struct hw *me,
102                      struct hw_port_edge **list,
103                      int my_port,
104                      struct hw *dest,
105                      int dest_port,
106                      object_disposition disposition)
107 {
108   struct hw_port_edge *new_edge = HW_ZALLOC (me, struct hw_port_edge);
109   new_edge->my_port = my_port;
110   new_edge->dest = dest;
111   new_edge->dest_port = dest_port;
112   new_edge->next = *list;
113   new_edge->disposition = disposition;
114   *list = new_edge;
115 }
116
117
118 static void
119 detach_hw_port_edge (struct hw *me,
120                      struct hw_port_edge **list,
121                      int my_port,
122                      struct hw *dest,
123                      int dest_port)
124 {
125   while (*list != NULL)
126     {
127       struct hw_port_edge *old_edge = *list;
128       if (old_edge->dest == dest
129           && old_edge->dest_port == dest_port
130           && old_edge->my_port == my_port)
131         {
132           if (old_edge->disposition == permenant_object)
133             hw_abort (me, "attempt to delete permenant port edge");
134           *list = old_edge->next;
135           hw_free (me, old_edge);
136           return;
137         }
138     }
139   hw_abort (me, "attempt to delete unattached port");
140 }
141
142
143 #if 0
144 static void
145 clean_hw_port_edges (struct hw_port_edge **list)
146 {
147   while (*list != NULL)
148     {
149       struct hw_port_edge *old_edge = *list;
150       switch (old_edge->disposition)
151         {
152         case permenant_object:
153           list = &old_edge->next;
154           break;
155         case temporary_object:
156           *list = old_edge->next;
157           hw_free (me, old_edge);
158           break;
159         }
160     }
161 }
162 #endif
163
164
165 /* Ports: */
166
167 void
168 hw_port_event (struct hw *me,
169                int my_port,
170                int level)
171 {
172   int found_an_edge = 0;
173   struct hw_port_edge *edge;
174   /* device's lines directly connected */
175   for (edge = me->ports_of_hw->edges;
176        edge != NULL;
177        edge = edge->next)
178     {
179       if (edge->my_port == my_port)
180         {
181           edge->dest->ports_of_hw->to_port_event (edge->dest,
182                                                   edge->dest_port,
183                                                   me,
184                                                   my_port,
185                                                   level);
186           found_an_edge = 1;
187         }
188     }
189   if (!found_an_edge)
190     hw_abort (me, "No edge for port %d", my_port);
191 }
192
193
194 void
195 hw_port_attach (struct hw *me,
196                 int my_port,
197                 struct hw *dest,
198                 int dest_port,
199                 object_disposition disposition)
200 {
201   attach_hw_port_edge (me,
202                        &me->ports_of_hw->edges,
203                        my_port,
204                        dest,
205                        dest_port,
206                        disposition);
207 }
208
209
210 void
211 hw_port_detach (struct hw *me,
212                 int my_port,
213                 struct hw *dest,
214                 int dest_port)
215 {
216   detach_hw_port_edge (me,
217                        &me->ports_of_hw->edges,
218                        my_port,
219                        dest,
220                        dest_port);
221 }
222
223
224 void
225 hw_port_traverse (struct hw *me,
226                   hw_port_traverse_function *handler,
227                   void *data)
228 {
229   struct hw_port_edge *port_edge;
230   for (port_edge = me->ports_of_hw->edges;
231        port_edge != NULL;
232        port_edge = port_edge->next)
233     {
234       handler (me, port_edge->my_port,
235                port_edge->dest, port_edge->dest_port,
236                data);
237     }
238 }
239
240
241 int
242 hw_port_decode (struct hw *me,
243                 const char *port_name,
244                 port_direction direction)
245 {
246   if (port_name == NULL || port_name[0] == '\0')
247     return 0;
248   if (isdigit (port_name[0]))
249     {
250       return strtoul (port_name, NULL, 0);
251     }
252   else
253     {
254       const struct hw_port_descriptor *ports =
255         me->ports_of_hw->ports;
256       if (ports != NULL)
257         {
258           while (ports->name != NULL)
259             {
260               if (ports->direction == bidirect_port
261                   || ports->direction == direction)
262                 {
263                   if (ports->nr_ports > 0)
264                     {
265                       int len = strlen (ports->name);
266                       if (strncmp (port_name, ports->name, len) == 0)
267                         {
268                           if (port_name[len] == '\0')
269                             return ports->number;
270                           else if (isdigit (port_name[len]))
271                             {
272                               int port = (ports->number
273                                           + strtoul (&port_name[len], NULL, 0));
274                               if (port >= ports->number + ports->nr_ports)
275                                 hw_abort (me,
276                                           "Port %s out of range",
277                                           port_name);
278                               return port;
279                             }
280                         }
281                     }
282                   else if (strcmp (port_name, ports->name) == 0)
283                     return ports->number;
284                 }
285               ports++;
286             }
287         }
288     }
289   hw_abort (me, "Unrecognized port %s", port_name);
290   return 0;
291 }
292
293
294 int
295 hw_port_encode (struct hw *me,
296                 int port_number,
297                 char *buf,
298                 int sizeof_buf,
299                 port_direction direction)
300 {
301   const struct hw_port_descriptor *ports = NULL;
302   ports = me->ports_of_hw->ports;
303   if (ports != NULL) {
304     while (ports->name != NULL)
305       {
306         if (ports->direction == bidirect_port
307             || ports->direction == direction)
308           {
309             if (ports->nr_ports > 0)
310               {
311                 if (port_number >= ports->number
312                     && port_number < ports->number + ports->nr_ports)
313                   {
314                     strcpy (buf, ports->name);
315                     sprintf (buf + strlen (buf), "%d", port_number - ports->number);
316                     if (strlen (buf) >= sizeof_buf)
317                       hw_abort (me, "hw_port_encode: buffer overflow");
318                     return strlen (buf);
319                   }
320               }
321             else
322               {
323                 if (ports->number == port_number)
324                   {
325                     if (strlen (ports->name) >= sizeof_buf)
326                       hw_abort (me, "hw_port_encode: buffer overflow");
327                     strcpy (buf, ports->name);
328                     return strlen (buf);
329                   }
330               }
331           }
332         ports++;
333       }
334   }
335   sprintf (buf, "%d", port_number);
336   if (strlen (buf) >= sizeof_buf)
337     hw_abort (me, "hw_port_encode: buffer overflow");
338   return strlen (buf);
339 }