14e98e3e1Schristos /* The common simulator framework for GDB, the GNU Debugger. 24e98e3e1Schristos 3*0d3e0572Schristos Copyright 2002-2024 Free Software Foundation, Inc. 44e98e3e1Schristos 54e98e3e1Schristos Contributed by Andrew Cagney and Red Hat. 64e98e3e1Schristos 74e98e3e1Schristos This file is part of GDB. 84e98e3e1Schristos 94e98e3e1Schristos This program is free software; you can redistribute it and/or modify 104e98e3e1Schristos it under the terms of the GNU General Public License as published by 114e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 124e98e3e1Schristos (at your option) any later version. 134e98e3e1Schristos 144e98e3e1Schristos This program is distributed in the hope that it will be useful, 154e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 164e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 174e98e3e1Schristos GNU General Public License for more details. 184e98e3e1Schristos 194e98e3e1Schristos You should have received a copy of the GNU General Public License 204e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 214e98e3e1Schristos 224b169a6bSchristos /* This must come before any other includes. */ 234b169a6bSchristos #include "defs.h" 244e98e3e1Schristos 254e98e3e1Schristos #include "hw-main.h" 264e98e3e1Schristos #include "hw-base.h" 274e98e3e1Schristos 284e98e3e1Schristos #include "sim-io.h" 294e98e3e1Schristos #include "sim-assert.h" 304e98e3e1Schristos 314e98e3e1Schristos struct hw_instance_data 324e98e3e1Schristos { 334e98e3e1Schristos hw_finish_instance_method *to_finish; 344e98e3e1Schristos struct hw_instance *instances; 354e98e3e1Schristos }; 364e98e3e1Schristos 374e98e3e1Schristos static hw_finish_instance_method abort_hw_finish_instance; 384e98e3e1Schristos 394e98e3e1Schristos void 404e98e3e1Schristos create_hw_instance_data (struct hw *me) 414e98e3e1Schristos { 424e98e3e1Schristos me->instances_of_hw = HW_ZALLOC (me, struct hw_instance_data); 434e98e3e1Schristos set_hw_finish_instance (me, abort_hw_finish_instance); 444e98e3e1Schristos } 454e98e3e1Schristos 464e98e3e1Schristos void 474e98e3e1Schristos delete_hw_instance_data (struct hw *me) 484e98e3e1Schristos { 494e98e3e1Schristos /* NOP */ 504e98e3e1Schristos } 514e98e3e1Schristos 524e98e3e1Schristos 534e98e3e1Schristos static void 544e98e3e1Schristos abort_hw_finish_instance (struct hw *hw, 554e98e3e1Schristos struct hw_instance *instance) 564e98e3e1Schristos { 574e98e3e1Schristos hw_abort (hw, "no instance finish method"); 584e98e3e1Schristos } 594e98e3e1Schristos 604e98e3e1Schristos void 614e98e3e1Schristos set_hw_finish_instance (struct hw *me, 624e98e3e1Schristos hw_finish_instance_method *finish) 634e98e3e1Schristos { 644e98e3e1Schristos me->instances_of_hw->to_finish = finish; 654e98e3e1Schristos } 664e98e3e1Schristos 674e98e3e1Schristos 684e98e3e1Schristos #if 0 694e98e3e1Schristos void 704e98e3e1Schristos clean_hw_instances (struct hw *me) 714e98e3e1Schristos { 724e98e3e1Schristos struct hw_instance **instance = &me->instances; 734e98e3e1Schristos while (*instance != NULL) 744e98e3e1Schristos { 754e98e3e1Schristos struct hw_instance *old_instance = *instance; 764e98e3e1Schristos hw_instance_delete (old_instance); 774e98e3e1Schristos instance = &me->instances; 784e98e3e1Schristos } 794e98e3e1Schristos } 804e98e3e1Schristos #endif 814e98e3e1Schristos 824e98e3e1Schristos 834e98e3e1Schristos void 844e98e3e1Schristos hw_instance_delete (struct hw_instance *instance) 854e98e3e1Schristos { 864e98e3e1Schristos #if 1 874e98e3e1Schristos hw_abort (hw_instance_hw (instance), "not implemented"); 884e98e3e1Schristos #else 894e98e3e1Schristos struct hw *me = hw_instance_hw (instance); 904e98e3e1Schristos if (instance->to_instance_delete == NULL) 914e98e3e1Schristos hw_abort (me, "no delete method"); 924e98e3e1Schristos instance->method->delete (instance); 934e98e3e1Schristos if (instance->args != NULL) 944e98e3e1Schristos free (instance->args); 954e98e3e1Schristos if (instance->path != NULL) 964e98e3e1Schristos free (instance->path); 974e98e3e1Schristos if (instance->child == NULL) 984e98e3e1Schristos { 994e98e3e1Schristos /* only remove leaf nodes */ 1004e98e3e1Schristos struct hw_instance **curr = &me->instances; 1014e98e3e1Schristos while (*curr != instance) 1024e98e3e1Schristos { 1034e98e3e1Schristos ASSERT (*curr != NULL); 1044e98e3e1Schristos curr = &(*curr)->next; 1054e98e3e1Schristos } 1064e98e3e1Schristos *curr = instance->next; 1074e98e3e1Schristos } 1084e98e3e1Schristos else 1094e98e3e1Schristos { 1104e98e3e1Schristos /* check it isn't in the instance list */ 1114e98e3e1Schristos struct hw_instance *curr = me->instances; 1124e98e3e1Schristos while (curr != NULL) 1134e98e3e1Schristos { 1144e98e3e1Schristos ASSERT (curr != instance); 1154e98e3e1Schristos curr = curr->next; 1164e98e3e1Schristos } 1174e98e3e1Schristos /* unlink the child */ 1184e98e3e1Schristos ASSERT (instance->child->parent == instance); 1194e98e3e1Schristos instance->child->parent = NULL; 1204e98e3e1Schristos } 1214e98e3e1Schristos cap_remove (me->ihandles, instance); 1224e98e3e1Schristos free (instance); 1234e98e3e1Schristos #endif 1244e98e3e1Schristos } 1254e98e3e1Schristos 1264e98e3e1Schristos 1274e98e3e1Schristos static int 1284e98e3e1Schristos panic_hw_instance_read (struct hw_instance *instance, 1294e98e3e1Schristos void *addr, 1304e98e3e1Schristos unsigned_word len) 1314e98e3e1Schristos { 1324e98e3e1Schristos hw_abort (hw_instance_hw (instance), "no read method"); 1334e98e3e1Schristos return -1; 1344e98e3e1Schristos } 1354e98e3e1Schristos 1364e98e3e1Schristos 1374e98e3e1Schristos 1384e98e3e1Schristos static int 1394e98e3e1Schristos panic_hw_instance_write (struct hw_instance *instance, 1404e98e3e1Schristos const void *addr, 1414e98e3e1Schristos unsigned_word len) 1424e98e3e1Schristos { 1434e98e3e1Schristos hw_abort (hw_instance_hw (instance), "no write method"); 1444e98e3e1Schristos return -1; 1454e98e3e1Schristos } 1464e98e3e1Schristos 1474e98e3e1Schristos 1484e98e3e1Schristos static int 1494e98e3e1Schristos panic_hw_instance_seek (struct hw_instance *instance, 1504e98e3e1Schristos unsigned_word pos_hi, 1514e98e3e1Schristos unsigned_word pos_lo) 1524e98e3e1Schristos { 1534e98e3e1Schristos hw_abort (hw_instance_hw (instance), "no seek method"); 1544e98e3e1Schristos return -1; 1554e98e3e1Schristos } 1564e98e3e1Schristos 1574e98e3e1Schristos 1584e98e3e1Schristos int 1594e98e3e1Schristos hw_instance_call_method (struct hw_instance *instance, 1604e98e3e1Schristos const char *method_name, 1614e98e3e1Schristos int n_stack_args, 1624e98e3e1Schristos unsigned_cell stack_args[/*n_stack_args*/], 1634e98e3e1Schristos int n_stack_returns, 1644e98e3e1Schristos unsigned_cell stack_returns[/*n_stack_args*/]) 1654e98e3e1Schristos { 1664e98e3e1Schristos #if 1 1674e98e3e1Schristos hw_abort (hw_instance_hw (instance), "not implemented"); 1684e98e3e1Schristos return -1; 1694e98e3e1Schristos #else 1704e98e3e1Schristos struct hw *me = instance->owner; 1714e98e3e1Schristos const hw_instance_methods *method = instance->method->methods; 1724e98e3e1Schristos if (method == NULL) 1734e98e3e1Schristos { 1744e98e3e1Schristos hw_abort (me, "no methods (want %s)", method_name); 1754e98e3e1Schristos } 1764e98e3e1Schristos while (method->name != NULL) 1774e98e3e1Schristos { 1784e98e3e1Schristos if (strcmp (method->name, method_name) == 0) 1794e98e3e1Schristos { 1804e98e3e1Schristos return method->method (instance, 1814e98e3e1Schristos n_stack_args, stack_args, 1824e98e3e1Schristos n_stack_returns, stack_returns); 1834e98e3e1Schristos } 1844e98e3e1Schristos method++; 1854e98e3e1Schristos } 1864e98e3e1Schristos hw_abort (me, "no %s method", method_name); 1874e98e3e1Schristos return 0; 1884e98e3e1Schristos #endif 1894e98e3e1Schristos } 1904e98e3e1Schristos 1914e98e3e1Schristos 1924e98e3e1Schristos #define set_hw_instance_read(instance, method)\ 1934e98e3e1Schristos ((instance)->to_instance_read = (method)) 1944e98e3e1Schristos 1954e98e3e1Schristos #define set_hw_instance_write(instance, method)\ 1964e98e3e1Schristos ((instance)->to_instance_write = (method)) 1974e98e3e1Schristos 1984e98e3e1Schristos #define set_hw_instance_seek(instance, method)\ 1994e98e3e1Schristos ((instance)->to_instance_seek = (method)) 2004e98e3e1Schristos 2014e98e3e1Schristos 2024e98e3e1Schristos #if 0 2034e98e3e1Schristos static void 2044e98e3e1Schristos set_hw_instance_finish (struct hw *me, 2054e98e3e1Schristos hw_instance_finish_method *method) 2064e98e3e1Schristos { 2074e98e3e1Schristos if (me->instances_of_hw == NULL) 2084e98e3e1Schristos me->instances_of_hw = HW_ZALLOC (me, struct hw_instance_data); 2094e98e3e1Schristos me->instances_of_hw->to_finish = method; 2104e98e3e1Schristos } 2114e98e3e1Schristos #endif 2124e98e3e1Schristos 2134e98e3e1Schristos 2144e98e3e1Schristos struct hw_instance * 2154e98e3e1Schristos hw_instance_create (struct hw *me, 2164e98e3e1Schristos struct hw_instance *parent, 2174e98e3e1Schristos const char *path, 2184e98e3e1Schristos const char *args) 2194e98e3e1Schristos { 2204e98e3e1Schristos struct hw_instance *instance = ZALLOC (struct hw_instance); 2214e98e3e1Schristos /*instance->unit*/ 2224e98e3e1Schristos /* link this instance into the devices list */ 2234e98e3e1Schristos instance->hw_of_instance = me; 2244e98e3e1Schristos instance->parent_of_instance = NULL; 2254e98e3e1Schristos /* link this instance into the front of the devices instance list */ 2264e98e3e1Schristos instance->sibling_of_instance = me->instances_of_hw->instances; 2274e98e3e1Schristos me->instances_of_hw->instances = instance; 2284e98e3e1Schristos if (parent != NULL) 2294e98e3e1Schristos { 2304e98e3e1Schristos ASSERT (parent->child_of_instance == NULL); 2314e98e3e1Schristos parent->child_of_instance = instance; 2324e98e3e1Schristos instance->parent_of_instance = parent; 2334e98e3e1Schristos } 2344e98e3e1Schristos instance->args_of_instance = hw_strdup (me, args); 2354e98e3e1Schristos instance->path_of_instance = hw_strdup (me, path); 2364e98e3e1Schristos set_hw_instance_read (instance, panic_hw_instance_read); 2374e98e3e1Schristos set_hw_instance_write (instance, panic_hw_instance_write); 2384e98e3e1Schristos set_hw_instance_seek (instance, panic_hw_instance_seek); 2394e98e3e1Schristos hw_handle_add_ihandle (me, instance); 2404e98e3e1Schristos me->instances_of_hw->to_finish (me, instance); 2414e98e3e1Schristos return instance; 2424e98e3e1Schristos } 2434e98e3e1Schristos 2444e98e3e1Schristos 2454e98e3e1Schristos struct hw_instance * 2464e98e3e1Schristos hw_instance_interceed (struct hw_instance *parent, 2474e98e3e1Schristos const char *path, 2484e98e3e1Schristos const char *args) 2494e98e3e1Schristos { 2504e98e3e1Schristos #if 1 2514e98e3e1Schristos return NULL; 2524e98e3e1Schristos #else 2534e98e3e1Schristos struct hw_instance *instance = ZALLOC (struct hw_instance); 2544e98e3e1Schristos /*instance->unit*/ 2554e98e3e1Schristos /* link this instance into the devices list */ 2564e98e3e1Schristos if (me != NULL) 2574e98e3e1Schristos { 2584e98e3e1Schristos ASSERT (parent == NULL); 2594e98e3e1Schristos instance->hw_of_instance = me; 2604e98e3e1Schristos instance->parent_of_instance = NULL; 2614e98e3e1Schristos /* link this instance into the front of the devices instance list */ 2624e98e3e1Schristos instance->sibling_of_instance = me->instances_of_hw->instances; 2634e98e3e1Schristos me->instances_of_hw->instances = instance; 2644e98e3e1Schristos } 2654e98e3e1Schristos if (parent != NULL) 2664e98e3e1Schristos { 2674e98e3e1Schristos struct hw_instance **previous; 2684e98e3e1Schristos ASSERT (parent->child_of_instance == NULL); 2694e98e3e1Schristos parent->child_of_instance = instance; 2704e98e3e1Schristos instance->owner = parent->owner; 2714e98e3e1Schristos instance->parent_of_instance = parent; 2724e98e3e1Schristos /* in the devices instance list replace the parent instance with 2734e98e3e1Schristos this one */ 2744e98e3e1Schristos instance->next = parent->next; 2754e98e3e1Schristos /* replace parent with this new node */ 2764e98e3e1Schristos previous = &instance->owner->instances; 2774e98e3e1Schristos while (*previous != parent) 2784e98e3e1Schristos { 2794e98e3e1Schristos ASSERT (*previous != NULL); 2804e98e3e1Schristos previous = &(*previous)->next; 2814e98e3e1Schristos } 2824e98e3e1Schristos *previous = instance; 2834e98e3e1Schristos } 2844e98e3e1Schristos instance->data = data; 2854e98e3e1Schristos instance->args = (args == NULL ? NULL : (char *) strdup (args)); 2864e98e3e1Schristos instance->path = (path == NULL ? NULL : (char *) strdup (path)); 2874e98e3e1Schristos cap_add (instance->owner->ihandles, instance); 2884e98e3e1Schristos return instance; 2894e98e3e1Schristos #endif 2904e98e3e1Schristos } 291