1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002-2015 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"
36 /* property entries */
38 struct hw_property_data
40 struct hw_property_data *next;
41 struct hw_property *property;
42 const void *init_array;
43 unsigned sizeof_init_array;
47 create_hw_property_data (struct hw *me)
52 delete_hw_property_data (struct hw *me)
57 /* Device Properties: */
59 static struct hw_property_data *
60 find_property_data (struct hw *me,
63 struct hw_property_data *entry;
64 ASSERT (property != NULL);
65 entry = me->properties_of_hw;
68 if (strcmp (entry->property->name, property) == 0)
77 hw_add_property (struct hw *me,
79 hw_property_type type,
80 const void *init_array,
81 unsigned sizeof_init_array,
83 unsigned sizeof_array,
84 const struct hw_property *original,
85 object_disposition disposition)
87 struct hw_property_data *new_entry = NULL;
88 struct hw_property *new_value = NULL;
90 /* find the list end */
91 struct hw_property_data **insertion_point = &me->properties_of_hw;
92 while (*insertion_point != NULL)
94 if (strcmp ((*insertion_point)->property->name, property) == 0)
96 insertion_point = &(*insertion_point)->next;
99 /* create a new value */
100 new_value = HW_ZALLOC (me, struct hw_property);
101 new_value->name = (char *) strdup (property);
102 new_value->type = type;
103 if (sizeof_array > 0)
105 void *new_array = hw_zalloc (me, sizeof_array);
106 memcpy (new_array, array, sizeof_array);
107 new_value->array = new_array;
108 new_value->sizeof_array = sizeof_array;
110 new_value->owner = me;
111 new_value->original = original;
112 new_value->disposition = disposition;
114 /* insert the value into the list */
115 new_entry = HW_ZALLOC (me, struct hw_property_data);
116 *insertion_point = new_entry;
117 if (sizeof_init_array > 0)
119 void *new_init_array = hw_zalloc (me, sizeof_init_array);
120 memcpy (new_init_array, init_array, sizeof_init_array);
121 new_entry->init_array = new_init_array;
122 new_entry->sizeof_init_array = sizeof_init_array;
124 new_entry->property = new_value;
129 hw_set_property (struct hw *me,
130 const char *property,
131 hw_property_type type,
135 /* find the property */
136 struct hw_property_data *entry = find_property_data (me, property);
139 /* existing property - update it */
141 struct hw_property *value = entry->property;
142 /* check the type matches */
143 if (value->type != type)
144 hw_abort (me, "conflict between type of new and old value for property %s", property);
145 /* replace its value */
146 if (value->array != NULL)
147 hw_free (me, (void*)value->array);
148 new_array = (sizeof_array > 0
149 ? hw_zalloc (me, sizeof_array)
151 value->array = new_array;
152 value->sizeof_array = sizeof_array;
153 if (sizeof_array > 0)
154 memcpy (new_array, array, sizeof_array);
159 /* new property - create it */
160 hw_add_property (me, property, type,
161 NULL, 0, array, sizeof_array,
162 NULL, temporary_object);
169 clean_hw_properties (struct hw *me)
171 struct hw_property_data **delete_point = &me->properties_of_hw;
172 while (*delete_point != NULL)
174 struct hw_property_data *current = *delete_point;
175 switch (current->property->disposition)
177 case permenant_object:
178 /* zap the current value, will be initialized later */
179 ASSERT (current->init_array != NULL);
180 if (current->property->array != NULL)
182 hw_free (me, (void*)current->property->array);
183 current->property->array = NULL;
185 delete_point = &(*delete_point)->next;
187 case temporary_object:
188 /* zap the actual property, was created during simulation run */
189 ASSERT (current->init_array == NULL);
190 *delete_point = current->next;
191 if (current->property->array != NULL)
192 hw_free (me, (void*)current->property->array);
193 hw_free (me, current->property);
194 hw_free (me, current);
203 hw_init_static_properties (SIM_DESC sd,
207 struct hw_property_data *property;
208 for (property = me->properties_of_hw;
210 property = property->next)
212 ASSERT (property->init_array != NULL);
213 ASSERT (property->property->array == NULL);
214 ASSERT (property->property->disposition == permenant_object);
215 switch (property->property->type)
218 case boolean_property:
219 case range_array_property:
220 case reg_array_property:
221 case string_property:
222 case string_array_property:
223 case integer_property:
224 /* delete the property, and replace it with the original */
225 hw_set_property (me, property->property->name,
226 property->property->type,
227 property->init_array,
228 property->sizeof_init_array);
231 case ihandle_property:
242 hw_init_runtime_properties (SIM_DESC sd,
246 struct hw_property_data *property;
247 for (property = me->properties_of_hw;
249 property = property->next)
251 switch (property->property->disposition)
253 case permenant_object:
254 switch (property->property->type)
257 case ihandle_property:
259 struct hw_instance *ihandle;
260 ihandle_runtime_property_spec spec;
261 ASSERT (property->init_array != NULL);
262 ASSERT (property->property->array == NULL);
263 hw_find_ihandle_runtime_property (me, property->property->name, &spec);
264 ihandle = tree_instance (me, spec.full_path);
265 hw_set_ihandle_property (me, property->property->name, ihandle);
270 case boolean_property:
271 case range_array_property:
272 case integer_property:
273 case reg_array_property:
274 case string_property:
275 case string_array_property:
276 ASSERT (property->init_array != NULL);
277 ASSERT (property->property->array != NULL);
281 case temporary_object:
282 ASSERT (property->init_array == NULL);
283 ASSERT (property->property->array != NULL);
292 const struct hw_property *
293 hw_next_property (const struct hw_property *property)
295 /* find the property in the list */
296 struct hw *owner = property->owner;
297 struct hw_property_data *entry = owner->properties_of_hw;
298 while (entry != NULL && entry->property != property)
300 /* now return the following property */
301 ASSERT (entry != NULL); /* must be a member! */
302 if (entry->next != NULL)
303 return entry->next->property;
309 const struct hw_property *
310 hw_find_property (struct hw *me,
311 const char *property)
317 else if (property == NULL || strcmp (property, "") == 0)
319 if (me->properties_of_hw == NULL)
322 return me->properties_of_hw->property;
326 struct hw_property_data *entry = find_property_data (me, property);
328 return entry->property;
335 hw_add_array_property (struct hw *me,
336 const char *property,
340 hw_add_property (me, property, array_property,
341 array, sizeof_array, array, sizeof_array,
342 NULL, permenant_object);
346 hw_set_array_property (struct hw *me,
347 const char *property,
351 hw_set_property (me, property, array_property, array, sizeof_array);
354 const struct hw_property *
355 hw_find_array_property (struct hw *me,
356 const char *property)
358 const struct hw_property *node;
359 node = hw_find_property (me, property);
361 hw_abort (me, "property \"%s\" not found", property);
362 if (node->type != array_property)
363 hw_abort (me, "property \"%s\" of wrong type (array)", property);
370 hw_add_boolean_property (struct hw *me,
371 const char *property,
374 signed32 new_boolean = (boolean ? -1 : 0);
375 hw_add_property (me, property, boolean_property,
376 &new_boolean, sizeof (new_boolean),
377 &new_boolean, sizeof (new_boolean),
378 NULL, permenant_object);
382 hw_find_boolean_property (struct hw *me,
383 const char *property)
385 const struct hw_property *node;
386 unsigned_cell boolean;
387 node = hw_find_property (me, property);
389 hw_abort (me, "property \"%s\" not found", property);
390 if (node->type != boolean_property)
391 hw_abort (me, "property \"%s\" of wrong type (boolean)", property);
392 ASSERT (sizeof (boolean) == node->sizeof_array);
393 memcpy (&boolean, node->array, sizeof (boolean));
401 hw_add_ihandle_runtime_property (struct hw *me,
402 const char *property,
403 const ihandle_runtime_property_spec *ihandle)
405 /* enter the full path as the init array */
406 hw_add_property (me, property, ihandle_property,
407 ihandle->full_path, strlen (ihandle->full_path) + 1,
409 NULL, permenant_object);
415 hw_find_ihandle_runtime_property (struct hw *me,
416 const char *property,
417 ihandle_runtime_property_spec *ihandle)
419 struct hw_property_data *entry = find_property_data (me, property);
420 HW_TRACE ((me, "hw_find_ihandle_runtime_property(property=%s)\n", property));
422 hw_abort (me, "property \"%s\" not found", property);
423 if (entry->property->type != ihandle_property
424 || entry->property->disposition != permenant_object)
425 hw_abort (me, "property \"%s\" of wrong type", property);
426 ASSERT (entry->init_array != NULL);
428 ihandle->full_path = entry->init_array;
436 hw_set_ihandle_property (struct hw *me,
437 const char *property,
438 hw_instance *ihandle)
441 cells = H2BE_cell (hw_instance_to_external (ihandle));
442 hw_set_property (me, property, ihandle_property,
443 &cells, sizeof (cells));
450 hw_find_ihandle_property (struct hw *me,
451 const char *property)
453 const hw_property_data *node;
454 unsigned_cell ihandle;
455 hw_instance *instance;
457 node = hw_find_property (me, property);
459 hw_abort (me, "property \"%s\" not found", property);
460 if (node->type != ihandle_property)
461 hw_abort (me, "property \"%s\" of wrong type (ihandle)", property);
462 if (node->array == NULL)
463 hw_abort (me, "runtime property \"%s\" not yet initialized", property);
465 ASSERT (sizeof (ihandle) == node->sizeof_array);
466 memcpy (&ihandle, node->array, sizeof (ihandle));
467 instance = external_to_hw_instance (me, BE2H_cell (ihandle));
468 ASSERT (instance != NULL);
475 hw_add_integer_property (struct hw *me,
476 const char *property,
480 hw_add_property (me, property, integer_property,
481 &integer, sizeof (integer),
482 &integer, sizeof (integer),
483 NULL, permenant_object);
487 hw_find_integer_property (struct hw *me,
488 const char *property)
490 const struct hw_property *node;
492 HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
493 node = hw_find_property (me, property);
495 hw_abort (me, "property \"%s\" not found", property);
496 if (node->type != integer_property)
497 hw_abort (me, "property \"%s\" of wrong type (integer)", property);
498 ASSERT (sizeof (integer) == node->sizeof_array);
499 memcpy (&integer, node->array, sizeof (integer));
500 return BE2H_cell (integer);
504 hw_find_integer_array_property (struct hw *me,
505 const char *property,
507 signed_cell *integer)
509 const struct hw_property *node;
510 int sizeof_integer = sizeof (*integer);
512 HW_TRACE ((me, "hw_find_integer(property=%s)\n", property));
514 /* check things sane */
515 node = hw_find_property (me, property);
517 hw_abort (me, "property \"%s\" not found", property);
518 if (node->type != integer_property
519 && node->type != array_property)
520 hw_abort (me, "property \"%s\" of wrong type (integer or array)", property);
521 if ((node->sizeof_array % sizeof_integer) != 0)
522 hw_abort (me, "property \"%s\" contains an incomplete number of cells", property);
523 if (node->sizeof_array <= sizeof_integer * index)
526 /* Find and convert the value */
527 cell = ((signed_cell*)node->array) + index;
528 *integer = BE2H_cell (*cell);
530 return node->sizeof_array / sizeof_integer;
534 static unsigned_cell *
535 unit_address_to_cells (const hw_unit *unit,
540 ASSERT (nr_cells == unit->nr_cells);
541 for (i = 0; i < unit->nr_cells; i++)
543 *cell = H2BE_cell (unit->cells[i]);
550 static const unsigned_cell *
551 cells_to_unit_address (const unsigned_cell *cell,
556 memset (unit, 0, sizeof (*unit));
557 unit->nr_cells = nr_cells;
558 for (i = 0; i < unit->nr_cells; i++)
560 unit->cells[i] = BE2H_cell (*cell);
568 nr_range_property_cells (struct hw *me,
571 return ((hw_unit_nr_address_cells (me)
572 + hw_unit_nr_address_cells (hw_parent (me))
573 + hw_unit_nr_size_cells (me))
578 hw_add_range_array_property (struct hw *me,
579 const char *property,
580 const range_property_spec *ranges,
583 unsigned sizeof_cells = (nr_range_property_cells (me, nr_ranges)
584 * sizeof (unsigned_cell));
585 unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
589 /* copy the property elements over */
591 for (i = 0; i < nr_ranges; i++)
593 const range_property_spec *range = &ranges[i];
594 /* copy the child address */
595 cell = unit_address_to_cells (&range->child_address, cell,
596 hw_unit_nr_address_cells (me));
597 /* copy the parent address */
598 cell = unit_address_to_cells (&range->parent_address, cell,
599 hw_unit_nr_address_cells (hw_parent (me)));
601 cell = unit_address_to_cells (&range->size, cell,
602 hw_unit_nr_size_cells (me));
604 ASSERT (cell == &cells[nr_range_property_cells (me, nr_ranges)]);
607 hw_add_property (me, property, range_array_property,
610 NULL, permenant_object);
616 hw_find_range_array_property (struct hw *me,
617 const char *property,
619 range_property_spec *range)
621 const struct hw_property *node;
622 unsigned sizeof_entry = (nr_range_property_cells (me, 1)
623 * sizeof (unsigned_cell));
624 const unsigned_cell *cells;
626 /* locate the property */
627 node = hw_find_property (me, property);
629 hw_abort (me, "property \"%s\" not found", property);
630 if (node->type != range_array_property)
631 hw_abort (me, "property \"%s\" of wrong type (range array)", property);
634 if ((node->sizeof_array % sizeof_entry) != 0)
635 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
639 if (node->sizeof_array < sizeof_entry * (index + 1))
642 /* find the range of interest */
643 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
645 /* copy the child address out - converting as we go */
646 cells = cells_to_unit_address (cells, &range->child_address,
647 hw_unit_nr_address_cells (me));
649 /* copy the parent address out - converting as we go */
650 cells = cells_to_unit_address (cells, &range->parent_address,
651 hw_unit_nr_address_cells (hw_parent (me)));
653 /* copy the size - converting as we go */
654 cells = cells_to_unit_address (cells, &range->size,
655 hw_unit_nr_size_cells (me));
657 return node->sizeof_array / sizeof_entry;
662 nr_reg_property_cells (struct hw *me,
665 return (hw_unit_nr_address_cells (hw_parent (me))
666 + hw_unit_nr_size_cells (hw_parent (me))
671 hw_add_reg_array_property (struct hw *me,
672 const char *property,
673 const reg_property_spec *regs,
676 unsigned sizeof_cells = (nr_reg_property_cells (me, nr_regs)
677 * sizeof (unsigned_cell));
678 unsigned_cell *cells = hw_zalloc (me, sizeof_cells);
682 /* copy the property elements over */
684 for (i = 0; i < nr_regs; i++)
686 const reg_property_spec *reg = ®s[i];
687 /* copy the address */
688 cell = unit_address_to_cells (®->address, cell,
689 hw_unit_nr_address_cells (hw_parent (me)));
691 cell = unit_address_to_cells (®->size, cell,
692 hw_unit_nr_size_cells (hw_parent (me)));
694 ASSERT (cell == &cells[nr_reg_property_cells (me, nr_regs)]);
697 hw_add_property (me, property, reg_array_property,
700 NULL, permenant_object);
706 hw_find_reg_array_property (struct hw *me,
707 const char *property,
709 reg_property_spec *reg)
711 const struct hw_property *node;
712 unsigned sizeof_entry = (nr_reg_property_cells (me, 1)
713 * sizeof (unsigned_cell));
714 const unsigned_cell *cells;
716 /* locate the property */
717 node = hw_find_property (me, property);
719 hw_abort (me, "property \"%s\" not found", property);
720 if (node->type != reg_array_property)
721 hw_abort (me, "property \"%s\" of wrong type (reg array)", property);
724 if ((node->sizeof_array % sizeof_entry) != 0)
725 hw_abort (me, "property \"%s\" contains an incomplete number of entries",
729 if (node->sizeof_array < sizeof_entry * (index + 1))
732 /* find the range of interest */
733 cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
735 /* copy the address out - converting as we go */
736 cells = cells_to_unit_address (cells, ®->address,
737 hw_unit_nr_address_cells (hw_parent (me)));
739 /* copy the size out - converting as we go */
740 cells = cells_to_unit_address (cells, ®->size,
741 hw_unit_nr_size_cells (hw_parent (me)));
743 return node->sizeof_array / sizeof_entry;
748 hw_add_string_property (struct hw *me,
749 const char *property,
752 hw_add_property (me, property, string_property,
753 string, strlen (string) + 1,
754 string, strlen (string) + 1,
755 NULL, permenant_object);
759 hw_find_string_property (struct hw *me,
760 const char *property)
762 const struct hw_property *node;
764 node = hw_find_property (me, property);
766 hw_abort (me, "property \"%s\" not found", property);
767 if (node->type != string_property)
768 hw_abort (me, "property \"%s\" of wrong type (string)", property);
769 string = node->array;
770 ASSERT (strlen (string) + 1 == node->sizeof_array);
775 hw_add_string_array_property (struct hw *me,
776 const char *property,
777 const string_property_spec *strings,
785 hw_abort (me, "property \"%s\" must be non-null", property);
786 /* total up the size of the needed array */
787 for (sizeof_array = 0, string_nr = 0;
788 string_nr < nr_strings;
791 sizeof_array += strlen (strings[string_nr]) + 1;
793 /* create the array */
794 array = (char*) hw_zalloc (me, sizeof_array);
797 string_nr < nr_strings;
800 strcpy (chp, strings[string_nr]);
801 chp += strlen (chp) + 1;
803 ASSERT (chp == array + sizeof_array);
805 hw_add_property (me, property, string_array_property,
808 NULL, permenant_object);
812 hw_find_string_array_property (struct hw *me,
813 const char *property,
815 string_property_spec *string)
817 const struct hw_property *node;
818 node = hw_find_property (me, property);
820 hw_abort (me, "property \"%s\" not found", property);
824 hw_abort (me, "property \"%s\" of wrong type", property);
826 case string_property:
829 *string = node->array;
830 ASSERT (strlen (*string) + 1 == node->sizeof_array);
835 if (node->sizeof_array == 0
836 || ((char*)node->array)[node->sizeof_array - 1] != '\0')
837 hw_abort (me, "property \"%s\" invalid for string array", property);
839 case string_array_property:
840 ASSERT (node->sizeof_array > 0);
841 ASSERT (((char*)node->array)[node->sizeof_array - 1] == '\0');
843 const char *chp = node->array;
845 /* count the number of strings, keeping an eye out for the one
855 if (nr_entries == index)
862 } while (chp < (char*)node->array + node->sizeof_array);
863 if (index < nr_entries)
877 hw_add_duplicate_property (struct hw *me,
878 const char *property,
879 const struct hw_property *original)
881 struct hw_property_data *master;
882 HW_TRACE ((me, "hw_add_duplicate_property(property=%s, ...)\n", property));
883 if (original->disposition != permenant_object)
884 hw_abort (me, "Can only duplicate permenant objects");
885 /* find the original's master */
886 master = original->owner->properties_of_hw;
887 while (master->property != original)
889 master = master->next;
890 ASSERT (master != NULL);
892 /* now duplicate it */
893 hw_add_property (me, property,
895 master->init_array, master->sizeof_init_array,
896 original->array, original->sizeof_array,
897 original, permenant_object);