1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002, 2007 Free Software Foundation, Inc.
5 Contributed by Andrew Cagney and Red Hat.
7 This file is part of GDB.
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.
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.
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/>. */
26 #include "sim-assert.h"
38 /* property entries */
40 struct hw_property_data
{
41 struct hw_property_data
*next
;
42 struct hw_property
*property
;
43 const void *init_array
;
44 unsigned sizeof_init_array
;
48 create_hw_property_data (struct hw
*me
)
53 delete_hw_property_data (struct hw
*me
)
58 /* Device Properties: */
60 static struct hw_property_data
*
61 find_property_data (struct hw
*me
,
64 struct hw_property_data
*entry
;
65 ASSERT (property
!= NULL
);
66 entry
= me
->properties_of_hw
;
69 if (strcmp (entry
->property
->name
, property
) == 0)
78 hw_add_property (struct hw
*me
,
80 hw_property_type type
,
81 const void *init_array
,
82 unsigned sizeof_init_array
,
84 unsigned sizeof_array
,
85 const struct hw_property
*original
,
86 object_disposition disposition
)
88 struct hw_property_data
*new_entry
= NULL
;
89 struct hw_property
*new_value
= NULL
;
91 /* find the list end */
92 struct hw_property_data
**insertion_point
= &me
->properties_of_hw
;
93 while (*insertion_point
!= NULL
)
95 if (strcmp ((*insertion_point
)->property
->name
, property
) == 0)
97 insertion_point
= &(*insertion_point
)->next
;
100 /* create a new value */
101 new_value
= HW_ZALLOC (me
, struct hw_property
);
102 new_value
->name
= (char *) strdup (property
);
103 new_value
->type
= type
;
104 if (sizeof_array
> 0)
106 void *new_array
= hw_zalloc (me
, sizeof_array
);
107 memcpy (new_array
, array
, sizeof_array
);
108 new_value
->array
= new_array
;
109 new_value
->sizeof_array
= sizeof_array
;
111 new_value
->owner
= me
;
112 new_value
->original
= original
;
113 new_value
->disposition
= disposition
;
115 /* insert the value into the list */
116 new_entry
= HW_ZALLOC (me
, struct hw_property_data
);
117 *insertion_point
= new_entry
;
118 if (sizeof_init_array
> 0)
120 void *new_init_array
= hw_zalloc (me
, sizeof_init_array
);
121 memcpy (new_init_array
, init_array
, sizeof_init_array
);
122 new_entry
->init_array
= new_init_array
;
123 new_entry
->sizeof_init_array
= sizeof_init_array
;
125 new_entry
->property
= new_value
;
130 hw_set_property (struct hw
*me
,
131 const char *property
,
132 hw_property_type type
,
136 /* find the property */
137 struct hw_property_data
*entry
= find_property_data (me
, property
);
140 /* existing property - update it */
142 struct hw_property
*value
= entry
->property
;
143 /* check the type matches */
144 if (value
->type
!= type
)
145 hw_abort (me
, "conflict between type of new and old value for property %s", property
);
146 /* replace its value */
147 if (value
->array
!= NULL
)
148 hw_free (me
, (void*)value
->array
);
149 new_array
= (sizeof_array
> 0
150 ? hw_zalloc (me
, sizeof_array
)
152 value
->array
= new_array
;
153 value
->sizeof_array
= sizeof_array
;
154 if (sizeof_array
> 0)
155 memcpy (new_array
, array
, sizeof_array
);
160 /* new property - create it */
161 hw_add_property (me
, property
, type
,
162 NULL
, 0, array
, sizeof_array
,
163 NULL
, temporary_object
);
170 clean_hw_properties (struct hw
*me
)
172 struct hw_property_data
**delete_point
= &me
->properties_of_hw
;
173 while (*delete_point
!= NULL
)
175 struct hw_property_data
*current
= *delete_point
;
176 switch (current
->property
->disposition
)
178 case permenant_object
:
179 /* zap the current value, will be initialized later */
180 ASSERT (current
->init_array
!= NULL
);
181 if (current
->property
->array
!= NULL
)
183 hw_free (me
, (void*)current
->property
->array
);
184 current
->property
->array
= NULL
;
186 delete_point
= &(*delete_point
)->next
;
188 case temporary_object
:
189 /* zap the actual property, was created during simulation run */
190 ASSERT (current
->init_array
== NULL
);
191 *delete_point
= current
->next
;
192 if (current
->property
->array
!= NULL
)
193 hw_free (me
, (void*)current
->property
->array
);
194 hw_free (me
, current
->property
);
195 hw_free (me
, current
);
204 hw_init_static_properties (SIM_DESC sd
,
208 struct hw_property_data
*property
;
209 for (property
= me
->properties_of_hw
;
211 property
= property
->next
)
213 ASSERT (property
->init_array
!= NULL
);
214 ASSERT (property
->property
->array
== NULL
);
215 ASSERT(property
->property
->disposition
== permenant_object
);
216 switch (property
->property
->type
)
219 case boolean_property
:
220 case range_array_property
:
221 case reg_array_property
:
222 case string_property
:
223 case string_array_property
:
224 case integer_property
:
225 /* delete the property, and replace it with the original */
226 hw_set_property (me
, property
->property
->name
,
227 property
->property
->type
,
228 property
->init_array
,
229 property
->sizeof_init_array
);
232 case ihandle_property
:
243 hw_init_runtime_properties (SIM_DESC sd
,
247 struct hw_property_data
*property
;
248 for (property
= me
->properties_of_hw
;
250 property
= property
->next
)
252 switch (property
->property
->disposition
)
254 case permenant_object
:
255 switch (property
->property
->type
)
258 case ihandle_property
:
260 struct hw_instance
*ihandle
;
261 ihandle_runtime_property_spec spec
;
262 ASSERT (property
->init_array
!= NULL
);
263 ASSERT (property
->property
->array
== NULL
);
264 hw_find_ihandle_runtime_property (me
, property
->property
->name
, &spec
);
265 ihandle
= tree_instance (me
, spec
.full_path
);
266 hw_set_ihandle_property (me
, property
->property
->name
, ihandle
);
271 case boolean_property
:
272 case range_array_property
:
273 case integer_property
:
274 case reg_array_property
:
275 case string_property
:
276 case string_array_property
:
277 ASSERT (property
->init_array
!= NULL
);
278 ASSERT (property
->property
->array
!= NULL
);
282 case temporary_object
:
283 ASSERT (property
->init_array
== NULL
);
284 ASSERT (property
->property
->array
!= NULL
);
293 const struct hw_property
*
294 hw_next_property (const struct hw_property
*property
)
296 /* find the property in the list */
297 struct hw
*owner
= property
->owner
;
298 struct hw_property_data
*entry
= owner
->properties_of_hw
;
299 while (entry
!= NULL
&& entry
->property
!= property
)
301 /* now return the following property */
302 ASSERT (entry
!= NULL
); /* must be a member! */
303 if (entry
->next
!= NULL
)
304 return entry
->next
->property
;
310 const struct hw_property
*
311 hw_find_property (struct hw
*me
,
312 const char *property
)
318 else if (property
== NULL
|| strcmp (property
, "") == 0)
320 if (me
->properties_of_hw
== NULL
)
323 return me
->properties_of_hw
->property
;
327 struct hw_property_data
*entry
= find_property_data (me
, property
);
329 return entry
->property
;
336 hw_add_array_property (struct hw
*me
,
337 const char *property
,
341 hw_add_property (me
, property
, array_property
,
342 array
, sizeof_array
, array
, sizeof_array
,
343 NULL
, permenant_object
);
347 hw_set_array_property (struct hw
*me
,
348 const char *property
,
352 hw_set_property (me
, property
, array_property
, array
, sizeof_array
);
355 const struct hw_property
*
356 hw_find_array_property (struct hw
*me
,
357 const char *property
)
359 const struct hw_property
*node
;
360 node
= hw_find_property (me
, property
);
362 hw_abort (me
, "property \"%s\" not found", property
);
363 if (node
->type
!= array_property
)
364 hw_abort (me
, "property \"%s\" of wrong type (array)", property
);
371 hw_add_boolean_property (struct hw
*me
,
372 const char *property
,
375 signed32 new_boolean
= (boolean
? -1 : 0);
376 hw_add_property (me
, property
, boolean_property
,
377 &new_boolean
, sizeof(new_boolean
),
378 &new_boolean
, sizeof(new_boolean
),
379 NULL
, permenant_object
);
383 hw_find_boolean_property (struct hw
*me
,
384 const char *property
)
386 const struct hw_property
*node
;
387 unsigned_cell boolean
;
388 node
= hw_find_property (me
, property
);
390 hw_abort (me
, "property \"%s\" not found", property
);
391 if (node
->type
!= boolean_property
)
392 hw_abort (me
, "property \"%s\" of wrong type (boolean)", property
);
393 ASSERT (sizeof (boolean
) == node
->sizeof_array
);
394 memcpy (&boolean
, node
->array
, sizeof (boolean
));
402 hw_add_ihandle_runtime_property (struct hw
*me
,
403 const char *property
,
404 const ihandle_runtime_property_spec
*ihandle
)
406 /* enter the full path as the init array */
407 hw_add_property (me
, property
, ihandle_property
,
408 ihandle
->full_path
, strlen(ihandle
->full_path
) + 1,
410 NULL
, permenant_object
);
416 hw_find_ihandle_runtime_property (struct hw
*me
,
417 const char *property
,
418 ihandle_runtime_property_spec
*ihandle
)
420 struct hw_property_data
*entry
= find_property_data (me
, property
);
421 TRACE (trace_devices
,
422 ("hw_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
423 (long)me
, property
));
425 hw_abort (me
, "property \"%s\" not found", property
);
426 if (entry
->property
->type
!= ihandle_property
427 || entry
->property
->disposition
!= permenant_object
)
428 hw_abort (me
, "property \"%s\" of wrong type", property
);
429 ASSERT (entry
->init_array
!= NULL
);
431 ihandle
->full_path
= entry
->init_array
;
439 hw_set_ihandle_property (struct hw
*me
,
440 const char *property
,
441 hw_instance
*ihandle
)
444 cells
= H2BE_cell (hw_instance_to_external (ihandle
));
445 hw_set_property (me
, property
, ihandle_property
,
446 &cells
, sizeof (cells
));
453 hw_find_ihandle_property (struct hw
*me
,
454 const char *property
)
456 const hw_property_data
*node
;
457 unsigned_cell ihandle
;
458 hw_instance
*instance
;
460 node
= hw_find_property (me
, property
);
462 hw_abort (me
, "property \"%s\" not found", property
);
463 if (node
->type
!= ihandle_property
)
464 hw_abort(me
, "property \"%s\" of wrong type (ihandle)", property
);
465 if (node
->array
== NULL
)
466 hw_abort(me
, "runtime property \"%s\" not yet initialized", property
);
468 ASSERT (sizeof(ihandle
) == node
->sizeof_array
);
469 memcpy (&ihandle
, node
->array
, sizeof(ihandle
));
470 instance
= external_to_hw_instance (me
, BE2H_cell(ihandle
));
471 ASSERT (instance
!= NULL
);
478 hw_add_integer_property (struct hw
*me
,
479 const char *property
,
483 hw_add_property (me
, property
, integer_property
,
484 &integer
, sizeof(integer
),
485 &integer
, sizeof(integer
),
486 NULL
, permenant_object
);
490 hw_find_integer_property (struct hw
*me
,
491 const char *property
)
493 const struct hw_property
*node
;
495 TRACE (trace_devices
,
496 ("hw_find_integer(me=0x%lx, property=%s)\n",
497 (long)me
, property
));
498 node
= hw_find_property (me
, property
);
500 hw_abort (me
, "property \"%s\" not found", property
);
501 if (node
->type
!= integer_property
)
502 hw_abort (me
, "property \"%s\" of wrong type (integer)", property
);
503 ASSERT (sizeof(integer
) == node
->sizeof_array
);
504 memcpy (&integer
, node
->array
, sizeof (integer
));
505 return BE2H_cell (integer
);
509 hw_find_integer_array_property (struct hw
*me
,
510 const char *property
,
512 signed_cell
*integer
)
514 const struct hw_property
*node
;
515 int sizeof_integer
= sizeof (*integer
);
517 TRACE (trace_devices
,
518 ("hw_find_integer(me=0x%lx, property=%s)\n",
519 (long)me
, property
));
521 /* check things sane */
522 node
= hw_find_property (me
, property
);
524 hw_abort (me
, "property \"%s\" not found", property
);
525 if (node
->type
!= integer_property
526 && node
->type
!= array_property
)
527 hw_abort (me
, "property \"%s\" of wrong type (integer or array)", property
);
528 if ((node
->sizeof_array
% sizeof_integer
) != 0)
529 hw_abort (me
, "property \"%s\" contains an incomplete number of cells", property
);
530 if (node
->sizeof_array
<= sizeof_integer
* index
)
533 /* Find and convert the value */
534 cell
= ((signed_cell
*)node
->array
) + index
;
535 *integer
= BE2H_cell (*cell
);
537 return node
->sizeof_array
/ sizeof_integer
;
541 static unsigned_cell
*
542 unit_address_to_cells (const hw_unit
*unit
,
547 ASSERT(nr_cells
== unit
->nr_cells
);
548 for (i
= 0; i
< unit
->nr_cells
; i
++)
550 *cell
= H2BE_cell (unit
->cells
[i
]);
557 static const unsigned_cell
*
558 cells_to_unit_address (const unsigned_cell
*cell
,
563 memset(unit
, 0, sizeof(*unit
));
564 unit
->nr_cells
= nr_cells
;
565 for (i
= 0; i
< unit
->nr_cells
; i
++)
567 unit
->cells
[i
] = BE2H_cell (*cell
);
575 nr_range_property_cells (struct hw
*me
,
578 return ((hw_unit_nr_address_cells (me
)
579 + hw_unit_nr_address_cells (hw_parent (me
))
580 + hw_unit_nr_size_cells (me
))
585 hw_add_range_array_property (struct hw
*me
,
586 const char *property
,
587 const range_property_spec
*ranges
,
590 unsigned sizeof_cells
= (nr_range_property_cells (me
, nr_ranges
)
591 * sizeof (unsigned_cell
));
592 unsigned_cell
*cells
= hw_zalloc (me
, sizeof_cells
);
596 /* copy the property elements over */
598 for (i
= 0; i
< nr_ranges
; i
++)
600 const range_property_spec
*range
= &ranges
[i
];
601 /* copy the child address */
602 cell
= unit_address_to_cells (&range
->child_address
, cell
,
603 hw_unit_nr_address_cells (me
));
604 /* copy the parent address */
605 cell
= unit_address_to_cells (&range
->parent_address
, cell
,
606 hw_unit_nr_address_cells (hw_parent (me
)));
608 cell
= unit_address_to_cells (&range
->size
, cell
,
609 hw_unit_nr_size_cells (me
));
611 ASSERT (cell
== &cells
[nr_range_property_cells (me
, nr_ranges
)]);
614 hw_add_property (me
, property
, range_array_property
,
617 NULL
, permenant_object
);
623 hw_find_range_array_property (struct hw
*me
,
624 const char *property
,
626 range_property_spec
*range
)
628 const struct hw_property
*node
;
629 unsigned sizeof_entry
= (nr_range_property_cells (me
, 1)
630 * sizeof (unsigned_cell
));
631 const unsigned_cell
*cells
;
633 /* locate the property */
634 node
= hw_find_property (me
, property
);
636 hw_abort (me
, "property \"%s\" not found", property
);
637 if (node
->type
!= range_array_property
)
638 hw_abort (me
, "property \"%s\" of wrong type (range array)", property
);
641 if ((node
->sizeof_array
% sizeof_entry
) != 0)
642 hw_abort (me
, "property \"%s\" contains an incomplete number of entries",
646 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
649 /* find the range of interest */
650 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
652 /* copy the child address out - converting as we go */
653 cells
= cells_to_unit_address (cells
, &range
->child_address
,
654 hw_unit_nr_address_cells (me
));
656 /* copy the parent address out - converting as we go */
657 cells
= cells_to_unit_address (cells
, &range
->parent_address
,
658 hw_unit_nr_address_cells (hw_parent (me
)));
660 /* copy the size - converting as we go */
661 cells
= cells_to_unit_address (cells
, &range
->size
,
662 hw_unit_nr_size_cells (me
));
664 return node
->sizeof_array
/ sizeof_entry
;
669 nr_reg_property_cells (struct hw
*me
,
672 return (hw_unit_nr_address_cells (hw_parent(me
))
673 + hw_unit_nr_size_cells (hw_parent(me
))
678 hw_add_reg_array_property (struct hw
*me
,
679 const char *property
,
680 const reg_property_spec
*regs
,
683 unsigned sizeof_cells
= (nr_reg_property_cells (me
, nr_regs
)
684 * sizeof (unsigned_cell
));
685 unsigned_cell
*cells
= hw_zalloc (me
, sizeof_cells
);
689 /* copy the property elements over */
691 for (i
= 0; i
< nr_regs
; i
++)
693 const reg_property_spec
*reg
= ®s
[i
];
694 /* copy the address */
695 cell
= unit_address_to_cells (®
->address
, cell
,
696 hw_unit_nr_address_cells (hw_parent (me
)));
698 cell
= unit_address_to_cells (®
->size
, cell
,
699 hw_unit_nr_size_cells (hw_parent (me
)));
701 ASSERT (cell
== &cells
[nr_reg_property_cells (me
, nr_regs
)]);
704 hw_add_property (me
, property
, reg_array_property
,
707 NULL
, permenant_object
);
713 hw_find_reg_array_property (struct hw
*me
,
714 const char *property
,
716 reg_property_spec
*reg
)
718 const struct hw_property
*node
;
719 unsigned sizeof_entry
= (nr_reg_property_cells (me
, 1)
720 * sizeof (unsigned_cell
));
721 const unsigned_cell
*cells
;
723 /* locate the property */
724 node
= hw_find_property (me
, property
);
726 hw_abort (me
, "property \"%s\" not found", property
);
727 if (node
->type
!= reg_array_property
)
728 hw_abort (me
, "property \"%s\" of wrong type (reg array)", property
);
731 if ((node
->sizeof_array
% sizeof_entry
) != 0)
732 hw_abort (me
, "property \"%s\" contains an incomplete number of entries",
736 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
739 /* find the range of interest */
740 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
742 /* copy the address out - converting as we go */
743 cells
= cells_to_unit_address (cells
, ®
->address
,
744 hw_unit_nr_address_cells (hw_parent (me
)));
746 /* copy the size out - converting as we go */
747 cells
= cells_to_unit_address (cells
, ®
->size
,
748 hw_unit_nr_size_cells (hw_parent (me
)));
750 return node
->sizeof_array
/ sizeof_entry
;
755 hw_add_string_property (struct hw
*me
,
756 const char *property
,
759 hw_add_property (me
, property
, string_property
,
760 string
, strlen(string
) + 1,
761 string
, strlen(string
) + 1,
762 NULL
, permenant_object
);
766 hw_find_string_property (struct hw
*me
,
767 const char *property
)
769 const struct hw_property
*node
;
771 node
= hw_find_property (me
, property
);
773 hw_abort (me
, "property \"%s\" not found", property
);
774 if (node
->type
!= string_property
)
775 hw_abort (me
, "property \"%s\" of wrong type (string)", property
);
776 string
= node
->array
;
777 ASSERT (strlen(string
) + 1 == node
->sizeof_array
);
782 hw_add_string_array_property (struct hw
*me
,
783 const char *property
,
784 const string_property_spec
*strings
,
792 hw_abort (me
, "property \"%s\" must be non-null", property
);
793 /* total up the size of the needed array */
794 for (sizeof_array
= 0, string_nr
= 0;
795 string_nr
< nr_strings
;
798 sizeof_array
+= strlen (strings
[string_nr
]) + 1;
800 /* create the array */
801 array
= (char*) hw_zalloc (me
, sizeof_array
);
804 string_nr
< nr_strings
;
807 strcpy (chp
, strings
[string_nr
]);
808 chp
+= strlen (chp
) + 1;
810 ASSERT (chp
== array
+ sizeof_array
);
812 hw_add_property (me
, property
, string_array_property
,
815 NULL
, permenant_object
);
819 hw_find_string_array_property (struct hw
*me
,
820 const char *property
,
822 string_property_spec
*string
)
824 const struct hw_property
*node
;
825 node
= hw_find_property (me
, property
);
827 hw_abort (me
, "property \"%s\" not found", property
);
831 hw_abort (me
, "property \"%s\" of wrong type", property
);
833 case string_property
:
836 *string
= node
->array
;
837 ASSERT (strlen(*string
) + 1 == node
->sizeof_array
);
842 if (node
->sizeof_array
== 0
843 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
844 hw_abort (me
, "property \"%s\" invalid for string array", property
);
846 case string_array_property
:
847 ASSERT (node
->sizeof_array
> 0);
848 ASSERT (((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
850 const char *chp
= node
->array
;
852 /* count the number of strings, keeping an eye out for the one
862 if (nr_entries
== index
)
869 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
870 if (index
< nr_entries
)
884 hw_add_duplicate_property (struct hw
*me
,
885 const char *property
,
886 const struct hw_property
*original
)
888 struct hw_property_data
*master
;
889 TRACE (trace_devices
,
890 ("hw_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
891 (long)me
, property
));
892 if (original
->disposition
!= permenant_object
)
893 hw_abort (me
, "Can only duplicate permenant objects");
894 /* find the original's master */
895 master
= original
->owner
->properties_of_hw
;
896 while (master
->property
!= original
)
898 master
= master
->next
;
899 ASSERT(master
!= NULL
);
901 /* now duplicate it */
902 hw_add_property (me
, property
,
904 master
->init_array
, master
->sizeof_init_array
,
905 original
->array
, original
->sizeof_array
,
906 original
, permenant_object
);