No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / dist / gdb6 / sim / cris / dv-cris.c
blobb98a6b734256550182faad7d896da6785cda1cf6
1 /* The CRIS interrupt framework for GDB, the GNU Debugger.
3 Copyright 2006 Free Software Foundation, Inc.
5 This file is part of GDB.
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 2 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "sim-main.h"
23 #include "hw-main.h"
25 /* DEVICE
27 CRIS cpu virtual device (very rudimental; generic enough for all
28 currently used CRIS versions).
31 DESCRIPTION
33 Implements the external CRIS functionality. This includes the
34 delivery of interrupts generated from other devices.
37 PROPERTIES
39 vec-for-int = <int-a> <vec-a> <int-b> <vec-b> ...
40 These are the translations to interrupt vector for values appearing
41 on the "int" port, as pairs of the value and the corresponding
42 vector. Defaults to no translation. All values that may appear on
43 the "int" port must be defined, or the device aborts.
45 multiple-int = ("abort" | "ignore_previous" | <vector>)
46 If multiple interrupt values are dispatched, this property decides
47 what to do. The value is either a number corresponding to the
48 vector to use, or the string "abort" to cause a hard abort, or the
49 string "ignore_previous", to silently use the new vector instead.
50 The default is "abort".
53 PORTS
55 int (input)
56 Interrupt port. An event with a non-zero value on this port causes
57 an interrupt. If, after an event but before the interrupt has been
58 properly dispatched, a non-zero value appears that is different
59 after mapping than the previous, then the property multiple_int
60 decides what to do.
62 FIXME: reg port so internal registers can be read. Requires
63 chip-specific versions, though. Ports "nmi" and "reset".
66 BUGS
67 When delivering an interrupt, this code assumes that there is only
68 one processor (number 0).
70 This code does not attempt to be efficient at handling pending
71 interrupts. It simply schedules the interrupt delivery handler
72 every instruction cycle until all pending interrupts go away.
73 It also works around a bug in sim_events_process when doing so.
76 /* Keep this an enum for simple addition of "reset" and "nmi". */
77 enum
79 INT_PORT,
82 static const struct hw_port_descriptor cris_ports[] =
84 { "int", INT_PORT, 0, input_port },
85 { NULL, 0, 0, 0 }
88 struct cris_vec_tr
90 unsigned32 portval, vec;
93 enum cris_multiple_ints
95 cris_multint_abort,
96 cris_multint_ignore_previous,
97 cris_multint_vector
100 struct cris_hw
102 struct hw_event *pending_handler;
103 unsigned32 pending_vector;
104 struct cris_vec_tr *int_to_vec;
105 enum cris_multiple_ints multi_int_action;
106 unsigned32 multiple_int_vector;
109 /* An event function, calling the actual CPU-model-specific
110 interrupt-delivery function. */
112 static void
113 deliver_cris_interrupt (struct hw *me, void *data)
115 struct cris_hw *crishw = hw_data (me);
116 SIM_DESC simulator = hw_system (me);
117 sim_cpu *cpu = STATE_CPU (simulator, 0);
118 unsigned int intno = crishw->pending_vector;
120 if (CPU_CRIS_DELIVER_INTERRUPT (cpu) (cpu, CRIS_INT_INT, intno))
122 crishw->pending_vector = 0;
123 crishw->pending_handler = NULL;
124 return;
128 /* Bug workaround: at time T with a pending number of cycles N to
129 process, if re-scheduling an event at time T+M, M < N,
130 sim_events_process gets stuck at T (updating the "time" to
131 before the event rather than after the event, or somesuch).
133 Hacking this locally is thankfully easy: if we see the same
134 simulation time, increase the number of cycles. Do this every
135 time we get here, until a new time is seen (supposedly unstuck
136 re-delivery). (Fixing in SIM/GDB source will hopefully then
137 also be easier, having a tangible test-case.) */
138 static signed64 last_events_time = 0;
139 static signed64 delta = 1;
140 signed64 this_events_time = hw_event_queue_time (me);
142 if (this_events_time == last_events_time)
143 delta++;
144 else
146 delta = 1;
147 last_events_time = this_events_time;
150 crishw->pending_handler
151 = hw_event_queue_schedule (me, delta, deliver_cris_interrupt, NULL);
156 /* A port-event function for events arriving to an interrupt port. */
158 static void
159 cris_port_event (struct hw *me,
160 int my_port,
161 struct hw *source,
162 int source_port,
163 int intparam)
165 struct cris_hw *crishw = hw_data (me);
166 unsigned32 vec;
168 /* A few placeholders; only the INT port is implemented. */
169 switch (my_port)
171 case INT_PORT:
172 HW_TRACE ((me, "INT value=0x%x", intparam));
173 break;
175 default:
176 hw_abort (me, "bad switch");
177 break;
180 if (intparam == 0)
181 return;
183 if (crishw->int_to_vec != NULL)
185 unsigned int i;
186 for (i = 0; crishw->int_to_vec[i].portval != 0; i++)
187 if (crishw->int_to_vec[i].portval == intparam)
188 break;
190 if (crishw->int_to_vec[i].portval == 0)
191 hw_abort (me, "unsupported value for int port: 0x%x", intparam);
193 vec = crishw->int_to_vec[i].vec;
195 else
196 vec = (unsigned32) intparam;
198 if (crishw->pending_vector != 0)
200 if (vec == crishw->pending_vector)
201 return;
203 switch (crishw->multi_int_action)
205 case cris_multint_abort:
206 hw_abort (me, "int 0x%x (0x%x) while int 0x%x hasn't been delivered",
207 vec, intparam, crishw->pending_vector);
208 break;
210 case cris_multint_ignore_previous:
211 break;
213 case cris_multint_vector:
214 vec = crishw->multiple_int_vector;
215 break;
217 default:
218 hw_abort (me, "bad switch");
222 crishw->pending_vector = vec;
224 /* Schedule our event handler *now*. */
225 if (crishw->pending_handler == NULL)
226 crishw->pending_handler
227 = hw_event_queue_schedule (me, 0, deliver_cris_interrupt, NULL);
230 /* Instance initializer function. */
232 static void
233 cris_finish (struct hw *me)
235 struct cris_hw *crishw;
236 const struct hw_property *vec_for_int;
237 const struct hw_property *multiple_int;
239 crishw = HW_ZALLOC (me, struct cris_hw);
240 set_hw_data (me, crishw);
241 set_hw_ports (me, cris_ports);
242 set_hw_port_event (me, cris_port_event);
244 vec_for_int = hw_find_property (me, "vec-for-int");
245 if (vec_for_int != NULL)
247 unsigned32 vecsize;
248 unsigned32 i;
250 if (hw_property_type (vec_for_int) != array_property)
251 hw_abort (me, "property \"vec-for-int\" has the wrong type");
253 vecsize = hw_property_sizeof_array (vec_for_int) / sizeof (signed_cell);
255 if ((vecsize % 2) != 0)
256 hw_abort (me, "translation vector does not consist of even pairs");
258 crishw->int_to_vec
259 = hw_malloc (me, (vecsize/2 + 1) * sizeof (crishw->int_to_vec[0]));
261 for (i = 0; i < vecsize/2; i++)
263 signed_cell portval_sc;
264 signed_cell vec_sc;
266 if (!hw_find_integer_array_property (me, "vec-for-int", i*2,
267 &portval_sc)
268 || !hw_find_integer_array_property (me, "vec-for-int", i*2 + 1,
269 &vec_sc)
270 || portval_sc < 0
271 || vec_sc < 0)
272 hw_abort (me, "no valid vector translation pair %u", i);
274 crishw->int_to_vec[i].portval = (unsigned32) portval_sc;
275 crishw->int_to_vec[i].vec = (unsigned32) vec_sc;
278 crishw->int_to_vec[i].portval = 0;
279 crishw->int_to_vec[i].vec = 0;
282 multiple_int = hw_find_property (me, "multiple-int");
283 if (multiple_int != NULL)
285 if (hw_property_type (multiple_int) == integer_property)
287 crishw->multiple_int_vector
288 = hw_find_integer_property (me, "multiple-int");
289 crishw->multi_int_action = cris_multint_vector;
291 else
293 const char *action = hw_find_string_property (me, "multiple-int");
295 if (action == NULL)
296 hw_abort (me, "property \"multiple-int\" has the wrong type");
298 if (strcmp (action, "abort") == 0)
299 crishw->multi_int_action = cris_multint_abort;
300 else if (strcmp (action, "ignore_previous") == 0)
301 crishw->multi_int_action = cris_multint_ignore_previous;
302 else
303 hw_abort (me, "property \"multiple-int\" must be one of <vector number>\n"
304 "\"abort\" and \"ignore_previous\", not \"%s\"", action);
307 else
308 crishw->multi_int_action = cris_multint_abort;
311 const struct hw_descriptor dv_cris_descriptor[] = {
312 { "cris", cris_finish, },
313 { NULL },