1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002-2021 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"
30 /* property entries */
32 struct hw_property_data
34 struct hw_property_data
*next
;
35 struct hw_property
*property
;
36 const void *init_array
;
37 unsigned sizeof_init_array
;
41 create_hw_property_data (struct hw
*me
)
46 delete_hw_property_data (struct hw
*me
)
51 /* Device Properties: */
53 static struct hw_property_data
*
54 find_property_data (struct hw
*me
,
57 struct hw_property_data
*entry
;
58 ASSERT (property
!= NULL
);
59 entry
= me
->properties_of_hw
;
62 if (strcmp (entry
->property
->name
, property
) == 0)
71 hw_add_property (struct hw
*me
,
73 hw_property_type type
,
74 const void *init_array
,
75 unsigned sizeof_init_array
,
77 unsigned sizeof_array
,
78 const struct hw_property
*original
,
79 object_disposition disposition
)
81 struct hw_property_data
*new_entry
= NULL
;
82 struct hw_property
*new_value
= NULL
;
84 /* find the list end */
85 struct hw_property_data
**insertion_point
= &me
->properties_of_hw
;
86 while (*insertion_point
!= NULL
)
88 if (strcmp ((*insertion_point
)->property
->name
, property
) == 0)
90 insertion_point
= &(*insertion_point
)->next
;
93 /* create a new value */
94 new_value
= HW_ZALLOC (me
, struct hw_property
);
95 new_value
->name
= (char *) strdup (property
);
96 new_value
->type
= type
;
99 void *new_array
= hw_zalloc (me
, sizeof_array
);
100 memcpy (new_array
, array
, sizeof_array
);
101 new_value
->array
= new_array
;
102 new_value
->sizeof_array
= sizeof_array
;
104 new_value
->owner
= me
;
105 new_value
->original
= original
;
106 new_value
->disposition
= disposition
;
108 /* insert the value into the list */
109 new_entry
= HW_ZALLOC (me
, struct hw_property_data
);
110 *insertion_point
= new_entry
;
111 if (sizeof_init_array
> 0)
113 void *new_init_array
= hw_zalloc (me
, sizeof_init_array
);
114 memcpy (new_init_array
, init_array
, sizeof_init_array
);
115 new_entry
->init_array
= new_init_array
;
116 new_entry
->sizeof_init_array
= sizeof_init_array
;
118 new_entry
->property
= new_value
;
123 hw_set_property (struct hw
*me
,
124 const char *property
,
125 hw_property_type type
,
129 /* find the property */
130 struct hw_property_data
*entry
= find_property_data (me
, property
);
133 /* existing property - update it */
135 struct hw_property
*value
= entry
->property
;
136 /* check the type matches */
137 if (value
->type
!= type
)
138 hw_abort (me
, "conflict between type of new and old value for property %s", property
);
139 /* replace its value */
140 if (value
->array
!= NULL
)
141 hw_free (me
, (void*)value
->array
);
142 new_array
= (sizeof_array
> 0
143 ? hw_zalloc (me
, sizeof_array
)
145 value
->array
= new_array
;
146 value
->sizeof_array
= sizeof_array
;
147 if (sizeof_array
> 0)
148 memcpy (new_array
, array
, sizeof_array
);
153 /* new property - create it */
154 hw_add_property (me
, property
, type
,
155 NULL
, 0, array
, sizeof_array
,
156 NULL
, temporary_object
);
163 clean_hw_properties (struct hw
*me
)
165 struct hw_property_data
**delete_point
= &me
->properties_of_hw
;
166 while (*delete_point
!= NULL
)
168 struct hw_property_data
*current
= *delete_point
;
169 switch (current
->property
->disposition
)
171 case permenant_object
:
172 /* zap the current value, will be initialized later */
173 ASSERT (current
->init_array
!= NULL
);
174 if (current
->property
->array
!= NULL
)
176 hw_free (me
, (void*)current
->property
->array
);
177 current
->property
->array
= NULL
;
179 delete_point
= &(*delete_point
)->next
;
181 case temporary_object
:
182 /* zap the actual property, was created during simulation run */
183 ASSERT (current
->init_array
== NULL
);
184 *delete_point
= current
->next
;
185 if (current
->property
->array
!= NULL
)
186 hw_free (me
, (void*)current
->property
->array
);
187 hw_free (me
, current
->property
);
188 hw_free (me
, current
);
197 hw_init_static_properties (SIM_DESC sd
,
201 struct hw_property_data
*property
;
202 for (property
= me
->properties_of_hw
;
204 property
= property
->next
)
206 ASSERT (property
->init_array
!= NULL
);
207 ASSERT (property
->property
->array
== NULL
);
208 ASSERT (property
->property
->disposition
== permenant_object
);
209 switch (property
->property
->type
)
212 case boolean_property
:
213 case range_array_property
:
214 case reg_array_property
:
215 case string_property
:
216 case string_array_property
:
217 case integer_property
:
218 /* delete the property, and replace it with the original */
219 hw_set_property (me
, property
->property
->name
,
220 property
->property
->type
,
221 property
->init_array
,
222 property
->sizeof_init_array
);
225 case ihandle_property
:
236 hw_init_runtime_properties (SIM_DESC sd
,
240 struct hw_property_data
*property
;
241 for (property
= me
->properties_of_hw
;
243 property
= property
->next
)
245 switch (property
->property
->disposition
)
247 case permenant_object
:
248 switch (property
->property
->type
)
251 case ihandle_property
:
253 struct hw_instance
*ihandle
;
254 ihandle_runtime_property_spec spec
;
255 ASSERT (property
->init_array
!= NULL
);
256 ASSERT (property
->property
->array
== NULL
);
257 hw_find_ihandle_runtime_property (me
, property
->property
->name
, &spec
);
258 ihandle
= tree_instance (me
, spec
.full_path
);
259 hw_set_ihandle_property (me
, property
->property
->name
, ihandle
);
264 case boolean_property
:
265 case range_array_property
:
266 case integer_property
:
267 case reg_array_property
:
268 case string_property
:
269 case string_array_property
:
270 ASSERT (property
->init_array
!= NULL
);
271 ASSERT (property
->property
->array
!= NULL
);
275 case temporary_object
:
276 ASSERT (property
->init_array
== NULL
);
277 ASSERT (property
->property
->array
!= NULL
);
286 const struct hw_property
*
287 hw_next_property (const struct hw_property
*property
)
289 /* find the property in the list */
290 struct hw
*owner
= property
->owner
;
291 struct hw_property_data
*entry
= owner
->properties_of_hw
;
292 while (entry
!= NULL
&& entry
->property
!= property
)
294 /* now return the following property */
295 ASSERT (entry
!= NULL
); /* must be a member! */
296 if (entry
->next
!= NULL
)
297 return entry
->next
->property
;
303 const struct hw_property
*
304 hw_find_property (struct hw
*me
,
305 const char *property
)
311 else if (property
== NULL
|| strcmp (property
, "") == 0)
313 if (me
->properties_of_hw
== NULL
)
316 return me
->properties_of_hw
->property
;
320 struct hw_property_data
*entry
= find_property_data (me
, property
);
322 return entry
->property
;
329 hw_add_array_property (struct hw
*me
,
330 const char *property
,
334 hw_add_property (me
, property
, array_property
,
335 array
, sizeof_array
, array
, sizeof_array
,
336 NULL
, permenant_object
);
340 hw_set_array_property (struct hw
*me
,
341 const char *property
,
345 hw_set_property (me
, property
, array_property
, array
, sizeof_array
);
348 const struct hw_property
*
349 hw_find_array_property (struct hw
*me
,
350 const char *property
)
352 const struct hw_property
*node
;
353 node
= hw_find_property (me
, property
);
355 hw_abort (me
, "property \"%s\" not found", property
);
356 if (node
->type
!= array_property
)
357 hw_abort (me
, "property \"%s\" of wrong type (array)", property
);
364 hw_add_boolean_property (struct hw
*me
,
365 const char *property
,
368 signed32 new_boolean
= (boolean
? -1 : 0);
369 hw_add_property (me
, property
, boolean_property
,
370 &new_boolean
, sizeof (new_boolean
),
371 &new_boolean
, sizeof (new_boolean
),
372 NULL
, permenant_object
);
376 hw_find_boolean_property (struct hw
*me
,
377 const char *property
)
379 const struct hw_property
*node
;
380 unsigned_cell boolean
;
381 node
= hw_find_property (me
, property
);
383 hw_abort (me
, "property \"%s\" not found", property
);
384 if (node
->type
!= boolean_property
)
385 hw_abort (me
, "property \"%s\" of wrong type (boolean)", property
);
386 ASSERT (sizeof (boolean
) == node
->sizeof_array
);
387 memcpy (&boolean
, node
->array
, sizeof (boolean
));
395 hw_add_ihandle_runtime_property (struct hw
*me
,
396 const char *property
,
397 const ihandle_runtime_property_spec
*ihandle
)
399 /* enter the full path as the init array */
400 hw_add_property (me
, property
, ihandle_property
,
401 ihandle
->full_path
, strlen (ihandle
->full_path
) + 1,
403 NULL
, permenant_object
);
409 hw_find_ihandle_runtime_property (struct hw
*me
,
410 const char *property
,
411 ihandle_runtime_property_spec
*ihandle
)
413 struct hw_property_data
*entry
= find_property_data (me
, property
);
415 hw_abort (me
, "property \"%s\" not found", property
);
416 if (entry
->property
->type
!= ihandle_property
417 || entry
->property
->disposition
!= permenant_object
)
418 hw_abort (me
, "property \"%s\" of wrong type", property
);
419 ASSERT (entry
->init_array
!= NULL
);
421 ihandle
->full_path
= entry
->init_array
;
429 hw_set_ihandle_property (struct hw
*me
,
430 const char *property
,
431 hw_instance
*ihandle
)
434 cells
= H2BE_cell (hw_instance_to_external (ihandle
));
435 hw_set_property (me
, property
, ihandle_property
,
436 &cells
, sizeof (cells
));
443 hw_find_ihandle_property (struct hw
*me
,
444 const char *property
)
446 const hw_property_data
*node
;
447 unsigned_cell ihandle
;
448 hw_instance
*instance
;
450 node
= hw_find_property (me
, property
);
452 hw_abort (me
, "property \"%s\" not found", property
);
453 if (node
->type
!= ihandle_property
)
454 hw_abort (me
, "property \"%s\" of wrong type (ihandle)", property
);
455 if (node
->array
== NULL
)
456 hw_abort (me
, "runtime property \"%s\" not yet initialized", property
);
458 ASSERT (sizeof (ihandle
) == node
->sizeof_array
);
459 memcpy (&ihandle
, node
->array
, sizeof (ihandle
));
460 instance
= external_to_hw_instance (me
, BE2H_cell (ihandle
));
461 ASSERT (instance
!= NULL
);
468 hw_add_integer_property (struct hw
*me
,
469 const char *property
,
473 hw_add_property (me
, property
, integer_property
,
474 &integer
, sizeof (integer
),
475 &integer
, sizeof (integer
),
476 NULL
, permenant_object
);
480 hw_find_integer_property (struct hw
*me
,
481 const char *property
)
483 const struct hw_property
*node
;
485 node
= hw_find_property (me
, property
);
487 hw_abort (me
, "property \"%s\" not found", property
);
488 if (node
->type
!= integer_property
)
489 hw_abort (me
, "property \"%s\" of wrong type (integer)", property
);
490 ASSERT (sizeof (integer
) == node
->sizeof_array
);
491 memcpy (&integer
, node
->array
, sizeof (integer
));
492 return BE2H_cell (integer
);
496 hw_find_integer_array_property (struct hw
*me
,
497 const char *property
,
499 signed_cell
*integer
)
501 const struct hw_property
*node
;
502 int sizeof_integer
= sizeof (*integer
);
505 /* check things sane */
506 node
= hw_find_property (me
, property
);
508 hw_abort (me
, "property \"%s\" not found", property
);
509 if (node
->type
!= integer_property
510 && node
->type
!= array_property
)
511 hw_abort (me
, "property \"%s\" of wrong type (integer or array)", property
);
512 if ((node
->sizeof_array
% sizeof_integer
) != 0)
513 hw_abort (me
, "property \"%s\" contains an incomplete number of cells", property
);
514 if (node
->sizeof_array
<= sizeof_integer
* index
)
517 /* Find and convert the value */
518 cell
= ((signed_cell
*)node
->array
) + index
;
519 *integer
= BE2H_cell (*cell
);
521 return node
->sizeof_array
/ sizeof_integer
;
525 static unsigned_cell
*
526 unit_address_to_cells (const hw_unit
*unit
,
531 ASSERT (nr_cells
== unit
->nr_cells
);
532 for (i
= 0; i
< unit
->nr_cells
; i
++)
534 *cell
= H2BE_cell (unit
->cells
[i
]);
541 static const unsigned_cell
*
542 cells_to_unit_address (const unsigned_cell
*cell
,
547 memset (unit
, 0, sizeof (*unit
));
548 unit
->nr_cells
= nr_cells
;
549 for (i
= 0; i
< unit
->nr_cells
; i
++)
551 unit
->cells
[i
] = BE2H_cell (*cell
);
559 nr_range_property_cells (struct hw
*me
,
562 return ((hw_unit_nr_address_cells (me
)
563 + hw_unit_nr_address_cells (hw_parent (me
))
564 + hw_unit_nr_size_cells (me
))
569 hw_add_range_array_property (struct hw
*me
,
570 const char *property
,
571 const range_property_spec
*ranges
,
574 unsigned sizeof_cells
= (nr_range_property_cells (me
, nr_ranges
)
575 * sizeof (unsigned_cell
));
576 unsigned_cell
*cells
= hw_zalloc (me
, sizeof_cells
);
580 /* copy the property elements over */
582 for (i
= 0; i
< nr_ranges
; i
++)
584 const range_property_spec
*range
= &ranges
[i
];
585 /* copy the child address */
586 cell
= unit_address_to_cells (&range
->child_address
, cell
,
587 hw_unit_nr_address_cells (me
));
588 /* copy the parent address */
589 cell
= unit_address_to_cells (&range
->parent_address
, cell
,
590 hw_unit_nr_address_cells (hw_parent (me
)));
592 cell
= unit_address_to_cells (&range
->size
, cell
,
593 hw_unit_nr_size_cells (me
));
595 ASSERT (cell
== &cells
[nr_range_property_cells (me
, nr_ranges
)]);
598 hw_add_property (me
, property
, range_array_property
,
601 NULL
, permenant_object
);
607 hw_find_range_array_property (struct hw
*me
,
608 const char *property
,
610 range_property_spec
*range
)
612 const struct hw_property
*node
;
613 unsigned sizeof_entry
= (nr_range_property_cells (me
, 1)
614 * sizeof (unsigned_cell
));
615 const unsigned_cell
*cells
;
617 /* locate the property */
618 node
= hw_find_property (me
, property
);
620 hw_abort (me
, "property \"%s\" not found", property
);
621 if (node
->type
!= range_array_property
)
622 hw_abort (me
, "property \"%s\" of wrong type (range array)", property
);
625 if ((node
->sizeof_array
% sizeof_entry
) != 0)
626 hw_abort (me
, "property \"%s\" contains an incomplete number of entries",
630 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
633 /* find the range of interest */
634 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
636 /* copy the child address out - converting as we go */
637 cells
= cells_to_unit_address (cells
, &range
->child_address
,
638 hw_unit_nr_address_cells (me
));
640 /* copy the parent address out - converting as we go */
641 cells
= cells_to_unit_address (cells
, &range
->parent_address
,
642 hw_unit_nr_address_cells (hw_parent (me
)));
644 /* copy the size - converting as we go */
645 cells
= cells_to_unit_address (cells
, &range
->size
,
646 hw_unit_nr_size_cells (me
));
648 return node
->sizeof_array
/ sizeof_entry
;
653 nr_reg_property_cells (struct hw
*me
,
656 return (hw_unit_nr_address_cells (hw_parent (me
))
657 + hw_unit_nr_size_cells (hw_parent (me
))
662 hw_add_reg_array_property (struct hw
*me
,
663 const char *property
,
664 const reg_property_spec
*regs
,
667 unsigned sizeof_cells
= (nr_reg_property_cells (me
, nr_regs
)
668 * sizeof (unsigned_cell
));
669 unsigned_cell
*cells
= hw_zalloc (me
, sizeof_cells
);
673 /* copy the property elements over */
675 for (i
= 0; i
< nr_regs
; i
++)
677 const reg_property_spec
*reg
= ®s
[i
];
678 /* copy the address */
679 cell
= unit_address_to_cells (®
->address
, cell
,
680 hw_unit_nr_address_cells (hw_parent (me
)));
682 cell
= unit_address_to_cells (®
->size
, cell
,
683 hw_unit_nr_size_cells (hw_parent (me
)));
685 ASSERT (cell
== &cells
[nr_reg_property_cells (me
, nr_regs
)]);
688 hw_add_property (me
, property
, reg_array_property
,
691 NULL
, permenant_object
);
697 hw_find_reg_array_property (struct hw
*me
,
698 const char *property
,
700 reg_property_spec
*reg
)
702 const struct hw_property
*node
;
703 unsigned sizeof_entry
= (nr_reg_property_cells (me
, 1)
704 * sizeof (unsigned_cell
));
705 const unsigned_cell
*cells
;
707 /* locate the property */
708 node
= hw_find_property (me
, property
);
710 hw_abort (me
, "property \"%s\" not found", property
);
711 if (node
->type
!= reg_array_property
)
712 hw_abort (me
, "property \"%s\" of wrong type (reg array)", property
);
715 if ((node
->sizeof_array
% sizeof_entry
) != 0)
716 hw_abort (me
, "property \"%s\" contains an incomplete number of entries",
720 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
723 /* find the range of interest */
724 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
726 /* copy the address out - converting as we go */
727 cells
= cells_to_unit_address (cells
, ®
->address
,
728 hw_unit_nr_address_cells (hw_parent (me
)));
730 /* copy the size out - converting as we go */
731 cells
= cells_to_unit_address (cells
, ®
->size
,
732 hw_unit_nr_size_cells (hw_parent (me
)));
734 return node
->sizeof_array
/ sizeof_entry
;
739 hw_add_string_property (struct hw
*me
,
740 const char *property
,
743 hw_add_property (me
, property
, string_property
,
744 string
, strlen (string
) + 1,
745 string
, strlen (string
) + 1,
746 NULL
, permenant_object
);
750 hw_find_string_property (struct hw
*me
,
751 const char *property
)
753 const struct hw_property
*node
;
755 node
= hw_find_property (me
, property
);
757 hw_abort (me
, "property \"%s\" not found", property
);
758 if (node
->type
!= string_property
)
759 hw_abort (me
, "property \"%s\" of wrong type (string)", property
);
760 string
= node
->array
;
761 ASSERT (strlen (string
) + 1 == node
->sizeof_array
);
766 hw_add_string_array_property (struct hw
*me
,
767 const char *property
,
768 const string_property_spec
*strings
,
776 hw_abort (me
, "property \"%s\" must be non-null", property
);
777 /* total up the size of the needed array */
778 for (sizeof_array
= 0, string_nr
= 0;
779 string_nr
< nr_strings
;
782 sizeof_array
+= strlen (strings
[string_nr
]) + 1;
784 /* create the array */
785 array
= (char*) hw_zalloc (me
, sizeof_array
);
788 string_nr
< nr_strings
;
791 strcpy (chp
, strings
[string_nr
]);
792 chp
+= strlen (chp
) + 1;
794 ASSERT (chp
== array
+ sizeof_array
);
796 hw_add_property (me
, property
, string_array_property
,
799 NULL
, permenant_object
);
803 hw_find_string_array_property (struct hw
*me
,
804 const char *property
,
806 string_property_spec
*string
)
808 const struct hw_property
*node
;
809 node
= hw_find_property (me
, property
);
811 hw_abort (me
, "property \"%s\" not found", property
);
815 hw_abort (me
, "property \"%s\" of wrong type", property
);
817 case string_property
:
820 *string
= node
->array
;
821 ASSERT (strlen (*string
) + 1 == node
->sizeof_array
);
826 if (node
->sizeof_array
== 0
827 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
828 hw_abort (me
, "property \"%s\" invalid for string array", property
);
830 case string_array_property
:
831 ASSERT (node
->sizeof_array
> 0);
832 ASSERT (((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
834 const char *chp
= node
->array
;
836 /* count the number of strings, keeping an eye out for the one
846 if (nr_entries
== index
)
853 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
854 if (index
< nr_entries
)
868 hw_add_duplicate_property (struct hw
*me
,
869 const char *property
,
870 const struct hw_property
*original
)
872 struct hw_property_data
*master
;
873 if (original
->disposition
!= permenant_object
)
874 hw_abort (me
, "Can only duplicate permenant objects");
875 /* find the original's master */
876 master
= original
->owner
->properties_of_hw
;
877 while (master
->property
!= original
)
879 master
= master
->next
;
880 ASSERT (master
!= NULL
);
882 /* now duplicate it */
883 hw_add_property (me
, property
,
885 master
->init_array
, master
->sizeof_init_array
,
886 original
->array
, original
->sizeof_array
,
887 original
, permenant_object
);