1 /* The common simulator framework for GDB, the GNU Debugger.
3 Copyright 2002 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 2 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, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
28 #include "sim-assert.h"
40 /* property entries */
42 struct hw_property_data
{
43 struct hw_property_data
*next
;
44 struct hw_property
*property
;
45 const void *init_array
;
46 unsigned sizeof_init_array
;
50 create_hw_property_data (struct hw
*me
)
55 delete_hw_property_data (struct hw
*me
)
60 /* Device Properties: */
62 static struct hw_property_data
*
63 find_property_data (struct hw
*me
,
66 struct hw_property_data
*entry
;
67 ASSERT (property
!= NULL
);
68 entry
= me
->properties_of_hw
;
71 if (strcmp (entry
->property
->name
, property
) == 0)
80 hw_add_property (struct hw
*me
,
82 hw_property_type type
,
83 const void *init_array
,
84 unsigned sizeof_init_array
,
86 unsigned sizeof_array
,
87 const struct hw_property
*original
,
88 object_disposition disposition
)
90 struct hw_property_data
*new_entry
= NULL
;
91 struct hw_property
*new_value
= NULL
;
93 /* find the list end */
94 struct hw_property_data
**insertion_point
= &me
->properties_of_hw
;
95 while (*insertion_point
!= NULL
)
97 if (strcmp ((*insertion_point
)->property
->name
, property
) == 0)
99 insertion_point
= &(*insertion_point
)->next
;
102 /* create a new value */
103 new_value
= HW_ZALLOC (me
, struct hw_property
);
104 new_value
->name
= (char *) strdup (property
);
105 new_value
->type
= type
;
106 if (sizeof_array
> 0)
108 void *new_array
= hw_zalloc (me
, sizeof_array
);
109 memcpy (new_array
, array
, sizeof_array
);
110 new_value
->array
= new_array
;
111 new_value
->sizeof_array
= sizeof_array
;
113 new_value
->owner
= me
;
114 new_value
->original
= original
;
115 new_value
->disposition
= disposition
;
117 /* insert the value into the list */
118 new_entry
= HW_ZALLOC (me
, struct hw_property_data
);
119 *insertion_point
= new_entry
;
120 if (sizeof_init_array
> 0)
122 void *new_init_array
= hw_zalloc (me
, sizeof_init_array
);
123 memcpy (new_init_array
, init_array
, sizeof_init_array
);
124 new_entry
->init_array
= new_init_array
;
125 new_entry
->sizeof_init_array
= sizeof_init_array
;
127 new_entry
->property
= new_value
;
132 hw_set_property (struct hw
*me
,
133 const char *property
,
134 hw_property_type type
,
138 /* find the property */
139 struct hw_property_data
*entry
= find_property_data (me
, property
);
142 /* existing property - update it */
144 struct hw_property
*value
= entry
->property
;
145 /* check the type matches */
146 if (value
->type
!= type
)
147 hw_abort (me
, "conflict between type of new and old value for property %s", property
);
148 /* replace its value */
149 if (value
->array
!= NULL
)
150 hw_free (me
, (void*)value
->array
);
151 new_array
= (sizeof_array
> 0
152 ? hw_zalloc (me
, sizeof_array
)
154 value
->array
= new_array
;
155 value
->sizeof_array
= sizeof_array
;
156 if (sizeof_array
> 0)
157 memcpy (new_array
, array
, sizeof_array
);
162 /* new property - create it */
163 hw_add_property (me
, property
, type
,
164 NULL
, 0, array
, sizeof_array
,
165 NULL
, temporary_object
);
172 clean_hw_properties (struct hw
*me
)
174 struct hw_property_data
**delete_point
= &me
->properties_of_hw
;
175 while (*delete_point
!= NULL
)
177 struct hw_property_data
*current
= *delete_point
;
178 switch (current
->property
->disposition
)
180 case permenant_object
:
181 /* zap the current value, will be initialized later */
182 ASSERT (current
->init_array
!= NULL
);
183 if (current
->property
->array
!= NULL
)
185 hw_free (me
, (void*)current
->property
->array
);
186 current
->property
->array
= NULL
;
188 delete_point
= &(*delete_point
)->next
;
190 case temporary_object
:
191 /* zap the actual property, was created during simulation run */
192 ASSERT (current
->init_array
== NULL
);
193 *delete_point
= current
->next
;
194 if (current
->property
->array
!= NULL
)
195 hw_free (me
, (void*)current
->property
->array
);
196 hw_free (me
, current
->property
);
197 hw_free (me
, current
);
206 hw_init_static_properties (SIM_DESC sd
,
210 struct hw_property_data
*property
;
211 for (property
= me
->properties_of_hw
;
213 property
= property
->next
)
215 ASSERT (property
->init_array
!= NULL
);
216 ASSERT (property
->property
->array
== NULL
);
217 ASSERT(property
->property
->disposition
== permenant_object
);
218 switch (property
->property
->type
)
221 case boolean_property
:
222 case range_array_property
:
223 case reg_array_property
:
224 case string_property
:
225 case string_array_property
:
226 case integer_property
:
227 /* delete the property, and replace it with the original */
228 hw_set_property (me
, property
->property
->name
,
229 property
->property
->type
,
230 property
->init_array
,
231 property
->sizeof_init_array
);
234 case ihandle_property
:
245 hw_init_runtime_properties (SIM_DESC sd
,
249 struct hw_property_data
*property
;
250 for (property
= me
->properties_of_hw
;
252 property
= property
->next
)
254 switch (property
->property
->disposition
)
256 case permenant_object
:
257 switch (property
->property
->type
)
260 case ihandle_property
:
262 struct hw_instance
*ihandle
;
263 ihandle_runtime_property_spec spec
;
264 ASSERT (property
->init_array
!= NULL
);
265 ASSERT (property
->property
->array
== NULL
);
266 hw_find_ihandle_runtime_property (me
, property
->property
->name
, &spec
);
267 ihandle
= tree_instance (me
, spec
.full_path
);
268 hw_set_ihandle_property (me
, property
->property
->name
, ihandle
);
273 case boolean_property
:
274 case range_array_property
:
275 case integer_property
:
276 case reg_array_property
:
277 case string_property
:
278 case string_array_property
:
279 ASSERT (property
->init_array
!= NULL
);
280 ASSERT (property
->property
->array
!= NULL
);
284 case temporary_object
:
285 ASSERT (property
->init_array
== NULL
);
286 ASSERT (property
->property
->array
!= NULL
);
295 const struct hw_property
*
296 hw_next_property (const struct hw_property
*property
)
298 /* find the property in the list */
299 struct hw
*owner
= property
->owner
;
300 struct hw_property_data
*entry
= owner
->properties_of_hw
;
301 while (entry
!= NULL
&& entry
->property
!= property
)
303 /* now return the following property */
304 ASSERT (entry
!= NULL
); /* must be a member! */
305 if (entry
->next
!= NULL
)
306 return entry
->next
->property
;
312 const struct hw_property
*
313 hw_find_property (struct hw
*me
,
314 const char *property
)
320 else if (property
== NULL
|| strcmp (property
, "") == 0)
322 if (me
->properties_of_hw
== NULL
)
325 return me
->properties_of_hw
->property
;
329 struct hw_property_data
*entry
= find_property_data (me
, property
);
331 return entry
->property
;
338 hw_add_array_property (struct hw
*me
,
339 const char *property
,
343 hw_add_property (me
, property
, array_property
,
344 array
, sizeof_array
, array
, sizeof_array
,
345 NULL
, permenant_object
);
349 hw_set_array_property (struct hw
*me
,
350 const char *property
,
354 hw_set_property (me
, property
, array_property
, array
, sizeof_array
);
357 const struct hw_property
*
358 hw_find_array_property (struct hw
*me
,
359 const char *property
)
361 const struct hw_property
*node
;
362 node
= hw_find_property (me
, property
);
364 hw_abort (me
, "property \"%s\" not found", property
);
365 if (node
->type
!= array_property
)
366 hw_abort (me
, "property \"%s\" of wrong type (array)", property
);
373 hw_add_boolean_property (struct hw
*me
,
374 const char *property
,
377 signed32 new_boolean
= (boolean
? -1 : 0);
378 hw_add_property (me
, property
, boolean_property
,
379 &new_boolean
, sizeof(new_boolean
),
380 &new_boolean
, sizeof(new_boolean
),
381 NULL
, permenant_object
);
385 hw_find_boolean_property (struct hw
*me
,
386 const char *property
)
388 const struct hw_property
*node
;
389 unsigned_cell boolean
;
390 node
= hw_find_property (me
, property
);
392 hw_abort (me
, "property \"%s\" not found", property
);
393 if (node
->type
!= boolean_property
)
394 hw_abort (me
, "property \"%s\" of wrong type (boolean)", property
);
395 ASSERT (sizeof (boolean
) == node
->sizeof_array
);
396 memcpy (&boolean
, node
->array
, sizeof (boolean
));
404 hw_add_ihandle_runtime_property (struct hw
*me
,
405 const char *property
,
406 const ihandle_runtime_property_spec
*ihandle
)
408 /* enter the full path as the init array */
409 hw_add_property (me
, property
, ihandle_property
,
410 ihandle
->full_path
, strlen(ihandle
->full_path
) + 1,
412 NULL
, permenant_object
);
418 hw_find_ihandle_runtime_property (struct hw
*me
,
419 const char *property
,
420 ihandle_runtime_property_spec
*ihandle
)
422 struct hw_property_data
*entry
= find_property_data (me
, property
);
423 TRACE (trace_devices
,
424 ("hw_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
425 (long)me
, property
));
427 hw_abort (me
, "property \"%s\" not found", property
);
428 if (entry
->property
->type
!= ihandle_property
429 || entry
->property
->disposition
!= permenant_object
)
430 hw_abort (me
, "property \"%s\" of wrong type", property
);
431 ASSERT (entry
->init_array
!= NULL
);
433 ihandle
->full_path
= entry
->init_array
;
441 hw_set_ihandle_property (struct hw
*me
,
442 const char *property
,
443 hw_instance
*ihandle
)
446 cells
= H2BE_cell (hw_instance_to_external (ihandle
));
447 hw_set_property (me
, property
, ihandle_property
,
448 &cells
, sizeof (cells
));
455 hw_find_ihandle_property (struct hw
*me
,
456 const char *property
)
458 const hw_property_data
*node
;
459 unsigned_cell ihandle
;
460 hw_instance
*instance
;
462 node
= hw_find_property (me
, property
);
464 hw_abort (me
, "property \"%s\" not found", property
);
465 if (node
->type
!= ihandle_property
)
466 hw_abort(me
, "property \"%s\" of wrong type (ihandle)", property
);
467 if (node
->array
== NULL
)
468 hw_abort(me
, "runtime property \"%s\" not yet initialized", property
);
470 ASSERT (sizeof(ihandle
) == node
->sizeof_array
);
471 memcpy (&ihandle
, node
->array
, sizeof(ihandle
));
472 instance
= external_to_hw_instance (me
, BE2H_cell(ihandle
));
473 ASSERT (instance
!= NULL
);
480 hw_add_integer_property (struct hw
*me
,
481 const char *property
,
485 hw_add_property (me
, property
, integer_property
,
486 &integer
, sizeof(integer
),
487 &integer
, sizeof(integer
),
488 NULL
, permenant_object
);
492 hw_find_integer_property (struct hw
*me
,
493 const char *property
)
495 const struct hw_property
*node
;
497 TRACE (trace_devices
,
498 ("hw_find_integer(me=0x%lx, property=%s)\n",
499 (long)me
, property
));
500 node
= hw_find_property (me
, property
);
502 hw_abort (me
, "property \"%s\" not found", property
);
503 if (node
->type
!= integer_property
)
504 hw_abort (me
, "property \"%s\" of wrong type (integer)", property
);
505 ASSERT (sizeof(integer
) == node
->sizeof_array
);
506 memcpy (&integer
, node
->array
, sizeof (integer
));
507 return BE2H_cell (integer
);
511 hw_find_integer_array_property (struct hw
*me
,
512 const char *property
,
514 signed_cell
*integer
)
516 const struct hw_property
*node
;
517 int sizeof_integer
= sizeof (*integer
);
519 TRACE (trace_devices
,
520 ("hw_find_integer(me=0x%lx, property=%s)\n",
521 (long)me
, property
));
523 /* check things sane */
524 node
= hw_find_property (me
, property
);
526 hw_abort (me
, "property \"%s\" not found", property
);
527 if (node
->type
!= integer_property
528 && node
->type
!= array_property
)
529 hw_abort (me
, "property \"%s\" of wrong type (integer or array)", property
);
530 if ((node
->sizeof_array
% sizeof_integer
) != 0)
531 hw_abort (me
, "property \"%s\" contains an incomplete number of cells", property
);
532 if (node
->sizeof_array
<= sizeof_integer
* index
)
535 /* Find and convert the value */
536 cell
= ((signed_cell
*)node
->array
) + index
;
537 *integer
= BE2H_cell (*cell
);
539 return node
->sizeof_array
/ sizeof_integer
;
543 static unsigned_cell
*
544 unit_address_to_cells (const hw_unit
*unit
,
549 ASSERT(nr_cells
== unit
->nr_cells
);
550 for (i
= 0; i
< unit
->nr_cells
; i
++)
552 *cell
= H2BE_cell (unit
->cells
[i
]);
559 static const unsigned_cell
*
560 cells_to_unit_address (const unsigned_cell
*cell
,
565 memset(unit
, 0, sizeof(*unit
));
566 unit
->nr_cells
= nr_cells
;
567 for (i
= 0; i
< unit
->nr_cells
; i
++)
569 unit
->cells
[i
] = BE2H_cell (*cell
);
577 nr_range_property_cells (struct hw
*me
,
580 return ((hw_unit_nr_address_cells (me
)
581 + hw_unit_nr_address_cells (hw_parent (me
))
582 + hw_unit_nr_size_cells (me
))
587 hw_add_range_array_property (struct hw
*me
,
588 const char *property
,
589 const range_property_spec
*ranges
,
592 unsigned sizeof_cells
= (nr_range_property_cells (me
, nr_ranges
)
593 * sizeof (unsigned_cell
));
594 unsigned_cell
*cells
= hw_zalloc (me
, sizeof_cells
);
598 /* copy the property elements over */
600 for (i
= 0; i
< nr_ranges
; i
++)
602 const range_property_spec
*range
= &ranges
[i
];
603 /* copy the child address */
604 cell
= unit_address_to_cells (&range
->child_address
, cell
,
605 hw_unit_nr_address_cells (me
));
606 /* copy the parent address */
607 cell
= unit_address_to_cells (&range
->parent_address
, cell
,
608 hw_unit_nr_address_cells (hw_parent (me
)));
610 cell
= unit_address_to_cells (&range
->size
, cell
,
611 hw_unit_nr_size_cells (me
));
613 ASSERT (cell
== &cells
[nr_range_property_cells (me
, nr_ranges
)]);
616 hw_add_property (me
, property
, range_array_property
,
619 NULL
, permenant_object
);
625 hw_find_range_array_property (struct hw
*me
,
626 const char *property
,
628 range_property_spec
*range
)
630 const struct hw_property
*node
;
631 unsigned sizeof_entry
= (nr_range_property_cells (me
, 1)
632 * sizeof (unsigned_cell
));
633 const unsigned_cell
*cells
;
635 /* locate the property */
636 node
= hw_find_property (me
, property
);
638 hw_abort (me
, "property \"%s\" not found", property
);
639 if (node
->type
!= range_array_property
)
640 hw_abort (me
, "property \"%s\" of wrong type (range array)", property
);
643 if ((node
->sizeof_array
% sizeof_entry
) != 0)
644 hw_abort (me
, "property \"%s\" contains an incomplete number of entries",
648 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
651 /* find the range of interest */
652 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
654 /* copy the child address out - converting as we go */
655 cells
= cells_to_unit_address (cells
, &range
->child_address
,
656 hw_unit_nr_address_cells (me
));
658 /* copy the parent address out - converting as we go */
659 cells
= cells_to_unit_address (cells
, &range
->parent_address
,
660 hw_unit_nr_address_cells (hw_parent (me
)));
662 /* copy the size - converting as we go */
663 cells
= cells_to_unit_address (cells
, &range
->size
,
664 hw_unit_nr_size_cells (me
));
666 return node
->sizeof_array
/ sizeof_entry
;
671 nr_reg_property_cells (struct hw
*me
,
674 return (hw_unit_nr_address_cells (hw_parent(me
))
675 + hw_unit_nr_size_cells (hw_parent(me
))
680 hw_add_reg_array_property (struct hw
*me
,
681 const char *property
,
682 const reg_property_spec
*regs
,
685 unsigned sizeof_cells
= (nr_reg_property_cells (me
, nr_regs
)
686 * sizeof (unsigned_cell
));
687 unsigned_cell
*cells
= hw_zalloc (me
, sizeof_cells
);
691 /* copy the property elements over */
693 for (i
= 0; i
< nr_regs
; i
++)
695 const reg_property_spec
*reg
= ®s
[i
];
696 /* copy the address */
697 cell
= unit_address_to_cells (®
->address
, cell
,
698 hw_unit_nr_address_cells (hw_parent (me
)));
700 cell
= unit_address_to_cells (®
->size
, cell
,
701 hw_unit_nr_size_cells (hw_parent (me
)));
703 ASSERT (cell
== &cells
[nr_reg_property_cells (me
, nr_regs
)]);
706 hw_add_property (me
, property
, reg_array_property
,
709 NULL
, permenant_object
);
715 hw_find_reg_array_property (struct hw
*me
,
716 const char *property
,
718 reg_property_spec
*reg
)
720 const struct hw_property
*node
;
721 unsigned sizeof_entry
= (nr_reg_property_cells (me
, 1)
722 * sizeof (unsigned_cell
));
723 const unsigned_cell
*cells
;
725 /* locate the property */
726 node
= hw_find_property (me
, property
);
728 hw_abort (me
, "property \"%s\" not found", property
);
729 if (node
->type
!= reg_array_property
)
730 hw_abort (me
, "property \"%s\" of wrong type (reg array)", property
);
733 if ((node
->sizeof_array
% sizeof_entry
) != 0)
734 hw_abort (me
, "property \"%s\" contains an incomplete number of entries",
738 if (node
->sizeof_array
< sizeof_entry
* (index
+ 1))
741 /* find the range of interest */
742 cells
= (unsigned_cell
*)((char*)node
->array
+ sizeof_entry
* index
);
744 /* copy the address out - converting as we go */
745 cells
= cells_to_unit_address (cells
, ®
->address
,
746 hw_unit_nr_address_cells (hw_parent (me
)));
748 /* copy the size out - converting as we go */
749 cells
= cells_to_unit_address (cells
, ®
->size
,
750 hw_unit_nr_size_cells (hw_parent (me
)));
752 return node
->sizeof_array
/ sizeof_entry
;
757 hw_add_string_property (struct hw
*me
,
758 const char *property
,
761 hw_add_property (me
, property
, string_property
,
762 string
, strlen(string
) + 1,
763 string
, strlen(string
) + 1,
764 NULL
, permenant_object
);
768 hw_find_string_property (struct hw
*me
,
769 const char *property
)
771 const struct hw_property
*node
;
773 node
= hw_find_property (me
, property
);
775 hw_abort (me
, "property \"%s\" not found", property
);
776 if (node
->type
!= string_property
)
777 hw_abort (me
, "property \"%s\" of wrong type (string)", property
);
778 string
= node
->array
;
779 ASSERT (strlen(string
) + 1 == node
->sizeof_array
);
784 hw_add_string_array_property (struct hw
*me
,
785 const char *property
,
786 const string_property_spec
*strings
,
794 hw_abort (me
, "property \"%s\" must be non-null", property
);
795 /* total up the size of the needed array */
796 for (sizeof_array
= 0, string_nr
= 0;
797 string_nr
< nr_strings
;
800 sizeof_array
+= strlen (strings
[string_nr
]) + 1;
802 /* create the array */
803 array
= (char*) hw_zalloc (me
, sizeof_array
);
806 string_nr
< nr_strings
;
809 strcpy (chp
, strings
[string_nr
]);
810 chp
+= strlen (chp
) + 1;
812 ASSERT (chp
== array
+ sizeof_array
);
814 hw_add_property (me
, property
, string_array_property
,
817 NULL
, permenant_object
);
821 hw_find_string_array_property (struct hw
*me
,
822 const char *property
,
824 string_property_spec
*string
)
826 const struct hw_property
*node
;
827 node
= hw_find_property (me
, property
);
829 hw_abort (me
, "property \"%s\" not found", property
);
833 hw_abort (me
, "property \"%s\" of wrong type", property
);
835 case string_property
:
838 *string
= node
->array
;
839 ASSERT (strlen(*string
) + 1 == node
->sizeof_array
);
844 if (node
->sizeof_array
== 0
845 || ((char*)node
->array
)[node
->sizeof_array
- 1] != '\0')
846 hw_abort (me
, "property \"%s\" invalid for string array", property
);
848 case string_array_property
:
849 ASSERT (node
->sizeof_array
> 0);
850 ASSERT (((char*)node
->array
)[node
->sizeof_array
- 1] == '\0');
852 const char *chp
= node
->array
;
854 /* count the number of strings, keeping an eye out for the one
864 if (nr_entries
== index
)
871 } while (chp
< (char*)node
->array
+ node
->sizeof_array
);
872 if (index
< nr_entries
)
886 hw_add_duplicate_property (struct hw
*me
,
887 const char *property
,
888 const struct hw_property
*original
)
890 struct hw_property_data
*master
;
891 TRACE (trace_devices
,
892 ("hw_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
893 (long)me
, property
));
894 if (original
->disposition
!= permenant_object
)
895 hw_abort (me
, "Can only duplicate permenant objects");
896 /* find the original's master */
897 master
= original
->owner
->properties_of_hw
;
898 while (master
->property
!= original
)
900 master
= master
->next
;
901 ASSERT(master
!= NULL
);
903 /* now duplicate it */
904 hw_add_property (me
, property
,
906 master
->init_array
, master
->sizeof_init_array
,
907 original
->array
, original
->sizeof_array
,
908 original
, permenant_object
);