]> git.sur5r.net Git - cc65/blob - src/sim65/chip.c
Improved cbm_dir routines by Thomas Giesel.
[cc65] / src / sim65 / chip.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                    chip.c                                 */
4 /*                                                                           */
5 /*                        Interface for the chip plugins                     */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <dlfcn.h>
38
39 /* common */
40 #include "coll.h"
41 #include "fname.h"
42 #include "print.h"
43 #include "xmalloc.h"
44
45 /* sim65 */
46 #include "cfgdata.h"
47 #include "chipdata.h"
48 #include "cpucore.h"
49 #include "error.h"
50 #include "chip.h"
51
52
53
54 /*****************************************************************************/
55 /*                                 Forwards                                  */
56 /*****************************************************************************/
57
58
59
60 static int GetCfgId (void* CfgInfo, const char* Name, char** Id);
61 /* Search CfgInfo for an attribute with the given name and type "id". If
62  * found, remove it from the configuration, pass a pointer to a dynamically
63  * allocated string containing the value to Id, and return true. If not
64  * found, return false. The memory passed in Id must be free by a call to
65  * Free();
66  */
67
68 static int GetCfgStr (void* CfgInfo, const char* Name, char** S);
69 /* Search CfgInfo for an attribute with the given name and type "id". If
70  * found, remove it from the configuration, pass a pointer to a dynamically
71  * allocated string containing the value to Id, and return true. If not
72  * found, return false. The memory passed in S must be free by a call to
73  * Free();
74  */
75
76 static int GetCfgNum (void* CfgInfo, const char* Name, long* Val);
77 /* Search CfgInfo for an attribute with the given name and type "number".
78  * If found, remove it from the configuration, copy it into Val and return
79  * true. If not found, return false.
80  */
81
82
83
84 /*****************************************************************************/
85 /*                                     Data                                  */
86 /*****************************************************************************/
87
88
89
90 /* Sorted list of all chip data structures */
91 static Collection Chips = STATIC_COLLECTION_INITIALIZER;
92
93 /* A collection containing all libraries */
94 static Collection ChipLibraries = STATIC_COLLECTION_INITIALIZER;
95
96 /* SimData instance */
97 static const SimData Sim65Data = {
98     1,                  /* MajorVersion */
99     1,                  /* MinorVersion */
100     xmalloc,
101     xfree,
102     Warning,
103     Error,
104     Internal,
105     GetCfgId,
106     GetCfgStr,
107     GetCfgNum,
108     Break,
109     IRQRequest,
110     NMIRequest,
111 };
112
113
114
115 /*****************************************************************************/
116 /*                               Helper functions                            */
117 /*****************************************************************************/
118
119
120
121 static int GetCfgId (void* CfgInfo, const char* Name, char** Id)
122 /* Search CfgInfo for an attribute with the given name and type "id". If
123  * found, remove it from the configuration, pass a pointer to a dynamically
124  * allocated string containing the value to Id, and return true. If not
125  * found, return false. The memory passed in Id must be free by a call to
126  * Free();
127  */
128 {
129     return CfgDataGetId (CfgInfo, Name, Id);
130 }
131
132
133
134 static int GetCfgStr (void* CfgInfo, const char* Name, char** S)
135 /* Search CfgInfo for an attribute with the given name and type "id". If
136  * found, remove it from the configuration, pass a pointer to a dynamically
137  * allocated string containing the value to Id, and return true. If not
138  * found, return false. The memory passed in S must be free by a call to
139  * Free();
140  */
141 {
142     return CfgDataGetStr (CfgInfo, Name, S);
143 }
144
145
146
147 static int GetCfgNum (void* CfgInfo, const char* Name, long* Val)
148 /* Search CfgInfo for an attribute with the given name and type "number".
149  * If found, remove it from the configuration, copy it into Val and return
150  * true. If not found, return false.
151  */
152 {
153     return CfgDataGetNum (CfgInfo, Name, Val);
154 }
155
156
157
158 static int CmpChips (void* Data attribute ((unused)),
159                      const void* lhs, const void* rhs)
160 /* Compare function for CollSort */
161 {
162     /* Cast the object pointers */
163     const Chip* Left  = (const Chip*) rhs;
164     const Chip* Right = (const Chip*) lhs;
165
166     /* Do the compare */
167     return strcmp (Left->Data->ChipName, Right->Data->ChipName);
168 }
169
170
171
172 static Chip* FindChip (const char* Name)
173 /* Find a chip by name. Returns the Chip data structure or NULL if the chip
174  * could not be found.
175  */
176 {
177     unsigned I;
178
179     /* ## We do a linear search for now */
180     for (I = 0; I < CollCount (&Chips); ++I) {
181
182         /* Get the chip at this position */
183         Chip* C = CollAt (&Chips, I);
184
185         /* Compare the name */
186         if (strcmp (Name, C->Data->ChipName) == 0) {
187             /* Found */
188             return C;
189         }
190     }
191
192     /* Not found */
193     return 0;
194 }
195
196
197
198 /*****************************************************************************/
199 /*                                   Code                                    */
200 /*****************************************************************************/
201
202
203
204 static ChipLibrary* NewChipLibrary (const char* PathName)
205 /* Create, initialize and return a new ChipLibrary structure */
206 {
207     /* Allocate memory */
208     ChipLibrary* L = xmalloc (sizeof (ChipLibrary));
209
210     /* Initialize the fields */
211     L->LibName   = xstrdup (FindName (PathName));
212     L->PathName  = xstrdup (PathName);
213     L->Handle    = 0;
214     L->Chips     = EmptyCollection;
215
216     /* Return the allocated structure */
217     return L;
218 }
219
220
221
222 static void FreeChipLibrary (ChipLibrary* L)
223 /* Free a ChipLibrary structure */
224 {
225     /* Free the names */
226     xfree (L->LibName);
227     xfree (L->PathName);
228
229     /* If the library is open, close it. Discard any errors. */
230     if (L->Handle) {
231         dlclose (L->Handle);
232         (void) dlerror ();
233     }
234
235     /* We may have to handle the Chip pointers, but currently the function
236      * is never called with a non empty Chips collection, so we don't care
237      * for now.
238      */
239     xfree (L);
240 }
241
242
243
244 static Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
245 /* Allocate a new chip structure, initialize and return it */
246 {
247     /* Allocate memory */
248     Chip* C = xmalloc (sizeof (Chip));
249
250     /* Initialize the fields */
251     C->Lib       = Library;
252     C->Data      = Data;
253     C->Instances = EmptyCollection;
254
255     /* Insert the new chip into the collection of all chips */
256     CollAppend (&Chips, C);
257
258     /* Return the structure */
259     return C;
260 }
261
262
263
264 ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
265                                unsigned Size, Collection* Attributes)
266 {
267     ChipInstance* CI;
268
269     /* Find the chip with the given name */
270     Chip* C = FindChip (ChipName);
271     if (C == 0) {
272         Error ("No chip `%s' found for address $%06X", ChipName, Addr);
273     }
274
275     /* Allocate a new ChipInstance structure */
276     CI = xmalloc (sizeof (*CI));
277
278     /* Initialize the fields */
279     CI->C    = C;
280     CI->AS   = 0;
281     CI->Addr = Addr;
282     CI->Size = Size;
283     CI->Data = C->Data->CreateInstance (Addr, Size, Attributes);
284
285     /* Assign the chip instance to the chip */
286     CollAppend (&C->Instances, CI);
287
288     /* Return the new instance struct */
289     return CI;
290 }
291
292
293
294 ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
295 /* Generate a chip instance mirror and return it. */
296 {
297     /* Allocate a new ChipInstance structure */
298     ChipInstance* CI = xmalloc (sizeof (*CI));
299
300     /* Initialize the fields */
301     CI->C    = Orig->C;
302     CI->Addr = Addr;
303     CI->Size = Orig->Size;
304     CI->Data = Orig->Data;
305
306     /* Assign the chip instance to the chip */
307     CollAppend (&CI->C->Instances, CI);
308
309     /* Return the new instance struct */
310     return CI;
311 }
312
313
314
315 void SortChips (void)
316 /* Sort all chips by name. Called after loading */
317 {
318     /* Last act: Sort the chips by name */
319     CollSort (&Chips, CmpChips, 0);
320 }
321
322
323
324 void LoadChipLibrary (const char* LibName)
325 /* Load a chip library. This includes loading the shared libary, allocating
326  * and initializing the data structure, and loading all chip data from the
327  * library.
328  */
329 {
330     const char* Msg;
331     int (*GetChipData) (const struct ChipData**, unsigned*);
332     int ErrorCode;
333     const ChipData* Data;       /* Pointer to chip data */
334     unsigned ChipCount;         /* Number of chips in this library */
335     unsigned I;
336
337
338     /* Allocate a new ChipLibrary structure */
339     ChipLibrary* L = NewChipLibrary (LibName);
340
341     /* Open the library */
342     L->Handle = dlopen (L->PathName, RTLD_GLOBAL | RTLD_LAZY);
343
344     /* Check for errors */
345     Msg = dlerror ();
346     if (Msg) {
347         Error ("Cannot open `%s': %s", L->PathName, Msg);
348         FreeChipLibrary (L);
349         return;
350     }
351
352     /* Locate the GetChipData function */
353     GetChipData = dlsym (L->Handle, "GetChipData");
354
355     /* Check the error message */
356     Msg = dlerror ();
357     if (Msg) {
358         /* We had an error */
359         Error ("Cannot find export `GetChipData' in `%s': %s", L->LibName, Msg);
360         FreeChipLibrary (L);
361         return;
362     }
363
364     /* Call the function to read the chip data */
365     ErrorCode = GetChipData (&Data, &ChipCount);
366     if (ErrorCode != 0) {
367         Error ("Function `GetChipData' in `%s' returned error %d", L->LibName, ErrorCode);
368         FreeChipLibrary (L);
369         return;
370     }
371
372     /* Remember the library */
373     CollAppend (&ChipLibraries, L);
374
375     /* Print some information */
376     Print (stderr, 1, "Opened chip library `%s'\n", L->PathName);
377
378     /* Create the chips */
379     for (I = 0; I < ChipCount; ++I) {
380
381         Chip* C;
382
383         /* Get a pointer to the chip data */
384         const ChipData* D = Data + I;
385
386         /* Check if the chip data has the correct version */
387         if (D->MajorVersion != CHIPDATA_VER_MAJOR) {
388             Warning ("Version mismatch for `%s' (%s), expected %u, got %u",
389                      D->ChipName, L->LibName,
390                      CHIPDATA_VER_MAJOR, D->MajorVersion);
391             /* Ignore this chip */
392             continue;
393         }
394
395         /* Initialize the chip passing the simulator data */
396         D->InitChip (&Sim65Data);
397
398         /* Generate a new chip */
399         C = NewChip (L, D);
400
401         /* Insert a reference to the chip into the library exporting it */
402         CollAppend (&L->Chips, C);
403
404         /* Output chip name and version to keep the user happy */
405         Print (stdout, 1,
406                "  Found %s `%s', version %u.%u in library `%s'\n",
407                (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu",
408                D->ChipName,
409                D->MajorVersion,
410                D->MinorVersion,
411                L->LibName);
412     }
413 }
414
415
416