1 /***************************************************************************
2
3 memory.c
4
5 Functions which handle the CPU memory and I/O port access.
6
7 Caveats:
8
9 * The install_mem/port_*_handler functions are only intended to be
10 called at driver init time. Do not call them after this time.
11
12 * If your driver executes an opcode which crosses a bank-switched
13 boundary, it will pull the wrong data out of memory. Although not
14 a common case, you may need to revert to memcpy to work around this.
15 See machine/tnzs.c for an example.
16
17 ***************************************************************************/
18
19 #include <stdint.h>
20 #include "driver.h"
21 #include "osd_cpu.h"
22
23
24 #define VERBOSE 0
25
26 /* #define MEM_DUMP */
27
28 #ifdef MEM_DUMP
29 static void mem_dump( void );
30 #endif
31
32 /* Convenience macros - not in cpuintrf.h because they shouldn't be used by everyone */
33 #define ADDRESS_BITS(index) (cpuintf[Machine->drv->cpu[index].cpu_type & ~CPU_FLAGS_MASK].address_bits)
34 #define ABITS1(index) (cpuintf[Machine->drv->cpu[index].cpu_type & ~CPU_FLAGS_MASK].abits1)
35 #define ABITS2(index) (cpuintf[Machine->drv->cpu[index].cpu_type & ~CPU_FLAGS_MASK].abits2)
36 #define ABITS3(index) (0)
37 #define ABITSMIN(index) (cpuintf[Machine->drv->cpu[index].cpu_type & ~CPU_FLAGS_MASK].abitsmin)
38
39 unsigned char *OP_RAM;
40 unsigned char *OP_ROM;
41
42 /* change bases preserving opcode/data shift for encrypted games */
43 #define SET_OP_RAMROM(base) \
44 OP_ROM = (base) + (OP_ROM - OP_RAM); \
45 OP_RAM = (base);
46
47
48 MHELE ophw; /* op-code hardware number */
49
50 struct ExtMemory ext_memory[MAX_EXT_MEMORY];
51
52 static unsigned char *ramptr[MAX_CPU],*romptr[MAX_CPU];
53
54 /* element shift bits, mask bits */
55 int mhshift[MAX_CPU][3], mhmask[MAX_CPU][3];
56
57 /* pointers to port structs */
58 /* ASG: port speedup */
59 static struct IOReadPort *readport[MAX_CPU];
60 static struct IOWritePort *writeport[MAX_CPU];
61 static int portmask[MAX_CPU];
62 static int readport_size[MAX_CPU];
63 static int writeport_size[MAX_CPU];
64 /* HJB 990210: removed 'static' for access by assembly CPU core memory handlers */
65 const struct IOReadPort *cur_readport;
66 const struct IOWritePort *cur_writeport;
67 int cur_portmask;
68
69 /* current hardware element map */
70 static MHELE *cur_mr_element[MAX_CPU];
71 static MHELE *cur_mw_element[MAX_CPU];
72
73 /* sub memory/port hardware element map */
74 /* HJB 990210: removed 'static' for access by assembly CPU core memory handlers */
75 MHELE readhardware[MH_ELEMAX << MH_SBITS]; /* mem/port read */
76 MHELE writehardware[MH_ELEMAX << MH_SBITS]; /* mem/port write */
77
78 /* memory hardware handler */
79 /* HJB 990210: removed 'static' for access by assembly CPU core memory handlers */
80 mem_read_handler memoryreadhandler[MH_HARDMAX];
81 int memoryreadoffset[MH_HARDMAX];
82 mem_write_handler memorywritehandler[MH_HARDMAX];
83 int memorywriteoffset[MH_HARDMAX];
84
85 /* bank ram base address; RAM is bank 0 */
86 unsigned char *cpu_bankbase[HT_BANKMAX + 1];
87 static int bankreadoffset[HT_BANKMAX + 1];
88 static int bankwriteoffset[HT_BANKMAX + 1];
89
90 /* override OP base handler */
91 static opbase_handler setOPbasefunc[MAX_CPU];
92 static opbase_handler OPbasefunc;
93
94 /* current cpu current hardware element map point */
95 MHELE *cur_mrhard;
96 MHELE *cur_mwhard;
97
98 /* empty port handler structures */
99 static struct IOReadPort empty_readport[] =
100 {
101 { -1 }
102 };
103
104 static struct IOWritePort empty_writeport[] =
105 {
106 { -1 }
107 };
108
109 static void *install_port_read_handler_common(int cpu, int start, int end, mem_read_handler handler, int install_at_beginning);
110 static void *install_port_write_handler_common(int cpu, int start, int end, mem_write_handler handler, int install_at_beginning);
111
112
113 /***************************************************************************
114
115 Memory read handling
116
117 ***************************************************************************/
118
READ_HANDLER(mrh_ram)119 READ_HANDLER(mrh_ram) { return cpu_bankbase[0][offset]; }
READ_HANDLER(mrh_bank1)120 READ_HANDLER(mrh_bank1) { return cpu_bankbase[1][offset]; }
READ_HANDLER(mrh_bank2)121 READ_HANDLER(mrh_bank2) { return cpu_bankbase[2][offset]; }
READ_HANDLER(mrh_bank3)122 READ_HANDLER(mrh_bank3) { return cpu_bankbase[3][offset]; }
READ_HANDLER(mrh_bank4)123 READ_HANDLER(mrh_bank4) { return cpu_bankbase[4][offset]; }
READ_HANDLER(mrh_bank5)124 READ_HANDLER(mrh_bank5) { return cpu_bankbase[5][offset]; }
READ_HANDLER(mrh_bank6)125 READ_HANDLER(mrh_bank6) { return cpu_bankbase[6][offset]; }
READ_HANDLER(mrh_bank7)126 READ_HANDLER(mrh_bank7) { return cpu_bankbase[7][offset]; }
READ_HANDLER(mrh_bank8)127 READ_HANDLER(mrh_bank8) { return cpu_bankbase[8][offset]; }
READ_HANDLER(mrh_bank9)128 READ_HANDLER(mrh_bank9) { return cpu_bankbase[9][offset]; }
READ_HANDLER(mrh_bank10)129 READ_HANDLER(mrh_bank10) { return cpu_bankbase[10][offset]; }
READ_HANDLER(mrh_bank11)130 READ_HANDLER(mrh_bank11) { return cpu_bankbase[11][offset]; }
READ_HANDLER(mrh_bank12)131 READ_HANDLER(mrh_bank12) { return cpu_bankbase[12][offset]; }
READ_HANDLER(mrh_bank13)132 READ_HANDLER(mrh_bank13) { return cpu_bankbase[13][offset]; }
READ_HANDLER(mrh_bank14)133 READ_HANDLER(mrh_bank14) { return cpu_bankbase[14][offset]; }
READ_HANDLER(mrh_bank15)134 READ_HANDLER(mrh_bank15) { return cpu_bankbase[15][offset]; }
READ_HANDLER(mrh_bank16)135 READ_HANDLER(mrh_bank16) { return cpu_bankbase[16][offset]; }
136 static mem_read_handler bank_read_handler[] =
137 {
138 mrh_ram, mrh_bank1, mrh_bank2, mrh_bank3, mrh_bank4, mrh_bank5, mrh_bank6, mrh_bank7,
139 mrh_bank8, mrh_bank9, mrh_bank10, mrh_bank11, mrh_bank12, mrh_bank13, mrh_bank14, mrh_bank15,
140 mrh_bank16
141 };
142
READ_HANDLER(mrh_error)143 READ_HANDLER(mrh_error)
144 {
145 logerror("CPU #%d PC %04x: warning - read %02x from unmapped memory address %04x\n",cpu_getactivecpu(),cpu_get_pc(),cpu_bankbase[0][offset],offset);
146 return cpu_bankbase[0][offset];
147 }
148
READ_HANDLER(mrh_error_sparse)149 READ_HANDLER(mrh_error_sparse)
150 {
151 logerror("CPU #%d PC %08x: warning - read unmapped memory address %08x\n",cpu_getactivecpu(),cpu_get_pc(),offset);
152 return 0;
153 }
154
READ_HANDLER(mrh_error_sparse_bit)155 READ_HANDLER(mrh_error_sparse_bit)
156 {
157 logerror("CPU #%d PC %08x: warning - read unmapped memory bit addr %08x (byte addr %08x)\n",cpu_getactivecpu(),cpu_get_pc(),offset<<3, offset);
158 return 0;
159 }
160
READ_HANDLER(mrh_nop)161 READ_HANDLER(mrh_nop)
162 {
163 return 0;
164 }
165
166
167 /***************************************************************************
168
169 Memory write handling
170
171 ***************************************************************************/
172
WRITE_HANDLER(mwh_ram)173 WRITE_HANDLER(mwh_ram) { cpu_bankbase[0][offset] = data;}
WRITE_HANDLER(mwh_bank1)174 WRITE_HANDLER(mwh_bank1) { cpu_bankbase[1][offset] = data; }
WRITE_HANDLER(mwh_bank2)175 WRITE_HANDLER(mwh_bank2) { cpu_bankbase[2][offset] = data; }
WRITE_HANDLER(mwh_bank3)176 WRITE_HANDLER(mwh_bank3) { cpu_bankbase[3][offset] = data; }
WRITE_HANDLER(mwh_bank4)177 WRITE_HANDLER(mwh_bank4) { cpu_bankbase[4][offset] = data; }
WRITE_HANDLER(mwh_bank5)178 WRITE_HANDLER(mwh_bank5) { cpu_bankbase[5][offset] = data; }
WRITE_HANDLER(mwh_bank6)179 WRITE_HANDLER(mwh_bank6) { cpu_bankbase[6][offset] = data; }
WRITE_HANDLER(mwh_bank7)180 WRITE_HANDLER(mwh_bank7) { cpu_bankbase[7][offset] = data; }
WRITE_HANDLER(mwh_bank8)181 WRITE_HANDLER(mwh_bank8) { cpu_bankbase[8][offset] = data; }
WRITE_HANDLER(mwh_bank9)182 WRITE_HANDLER(mwh_bank9) { cpu_bankbase[9][offset] = data; }
WRITE_HANDLER(mwh_bank10)183 WRITE_HANDLER(mwh_bank10) { cpu_bankbase[10][offset] = data; }
WRITE_HANDLER(mwh_bank11)184 WRITE_HANDLER(mwh_bank11) { cpu_bankbase[11][offset] = data; }
WRITE_HANDLER(mwh_bank12)185 WRITE_HANDLER(mwh_bank12) { cpu_bankbase[12][offset] = data; }
WRITE_HANDLER(mwh_bank13)186 WRITE_HANDLER(mwh_bank13) { cpu_bankbase[13][offset] = data; }
WRITE_HANDLER(mwh_bank14)187 WRITE_HANDLER(mwh_bank14) { cpu_bankbase[14][offset] = data; }
WRITE_HANDLER(mwh_bank15)188 WRITE_HANDLER(mwh_bank15) { cpu_bankbase[15][offset] = data; }
WRITE_HANDLER(mwh_bank16)189 WRITE_HANDLER(mwh_bank16) { cpu_bankbase[16][offset] = data; }
190 static mem_write_handler bank_write_handler[] =
191 {
192 mwh_ram, mwh_bank1, mwh_bank2, mwh_bank3, mwh_bank4, mwh_bank5, mwh_bank6, mwh_bank7,
193 mwh_bank8, mwh_bank9, mwh_bank10, mwh_bank11, mwh_bank12, mwh_bank13, mwh_bank14, mwh_bank15,
194 mwh_bank16
195 };
196
WRITE_HANDLER(mwh_error)197 WRITE_HANDLER(mwh_error)
198 {
199 logerror("CPU #%d PC %04x: warning - write %02x to unmapped memory address %04x\n",cpu_getactivecpu(),cpu_get_pc(),data,offset);
200 cpu_bankbase[0][offset] = data;
201 }
202
WRITE_HANDLER(mwh_error_sparse)203 WRITE_HANDLER(mwh_error_sparse)
204 {
205 logerror("CPU #%d PC %08x: warning - write %02x to unmapped memory address %08x\n",cpu_getactivecpu(),cpu_get_pc(),data,offset);
206 }
207
WRITE_HANDLER(mwh_error_sparse_bit)208 WRITE_HANDLER(mwh_error_sparse_bit)
209 {
210 logerror("CPU #%d PC %08x: warning - write %02x to unmapped memory bit addr %08x\n",cpu_getactivecpu(),cpu_get_pc(),data,offset<<3);
211 }
212
WRITE_HANDLER(mwh_rom)213 WRITE_HANDLER(mwh_rom)
214 {
215 logerror("CPU #%d PC %04x: warning - write %02x to ROM address %04x\n",cpu_getactivecpu(),cpu_get_pc(),data,offset);
216 }
217
WRITE_HANDLER(mwh_ramrom)218 WRITE_HANDLER(mwh_ramrom)
219 {
220 cpu_bankbase[0][offset] = cpu_bankbase[0][offset + (OP_ROM - OP_RAM)] = data;
221 }
222
WRITE_HANDLER(mwh_nop)223 WRITE_HANDLER(mwh_nop)
224 {
225 }
226
227
228 /***************************************************************************
229
230 Memory structure building
231
232 ***************************************************************************/
233
234 /* return element offset */
get_element(MHELE * element,int ad,int elemask,MHELE * subelement,int * ele_max)235 static MHELE *get_element( MHELE *element , int ad , int elemask ,
236 MHELE *subelement , int *ele_max )
237 {
238 MHELE hw = element[ad];
239 int i,ele;
240 int banks = ( elemask / (1<<MH_SBITS) ) + 1;
241
242 if( hw >= MH_HARDMAX ) return &subelement[(hw-MH_HARDMAX)<<MH_SBITS];
243
244 /* create new element block */
245 if( (*ele_max)+banks > MH_ELEMAX )
246 {
247 logerror("memory element size overflow\n");
248 return 0;
249 }
250 /* get new element nunber */
251 ele = *ele_max;
252 (*ele_max)+=banks;
253 #ifdef MEM_DUMP
254 logerror("create element %2d(%2d)\n",ele,banks);
255 #endif
256 /* set link mark to current element */
257 element[ad] = ele + MH_HARDMAX;
258 /* get next subelement top */
259 subelement = &subelement[ele<<MH_SBITS];
260 /* initialize new block */
261 for( i = 0 ; i < (1<<MH_SBITS) ; i++ )
262 subelement[i] = hw;
263
264 return subelement;
265 }
266
set_element(int cpu,MHELE * celement,int sp,int ep,MHELE type,MHELE * subelement,int * ele_max)267 static void set_element( int cpu , MHELE *celement , int sp , int ep , MHELE type , MHELE *subelement , int *ele_max )
268 {
269 int i;
270 int edepth = 0;
271 int shift,mask;
272 MHELE *eele = celement;
273 MHELE *sele = celement;
274 MHELE *ele;
275 int ss,sb,eb,ee;
276
277 #ifdef MEM_DUMP
278 logerror("set_element %8X-%8X = %2X\n",sp,ep,type);
279 #endif
280 if( (unsigned int) sp > (unsigned int) ep ) return;
281 do{
282 mask = mhmask[cpu][edepth];
283 shift = mhshift[cpu][edepth];
284
285 /* center element */
286 ss = (unsigned int) sp >> shift;
287 sb = (unsigned int) sp ? ((unsigned int) (sp-1) >> shift) + 1 : 0;
288 eb = ((unsigned int) (ep+1) >> shift) - 1;
289 ee = (unsigned int) ep >> shift;
290
291 if( sb <= eb )
292 {
293 if( (sb|mask)==(eb|mask) )
294 {
295 /* same reason */
296 ele = (sele ? sele : eele);
297 for( i = sb ; i <= eb ; i++ ){
298 ele[i & mask] = type;
299 }
300 }
301 else
302 {
303 if( sele ) for( i = sb ; i <= (sb|mask) ; i++ )
304 sele[i & mask] = type;
305 if( eele ) for( i = eb&(~mask) ; i <= eb ; i++ )
306 eele[i & mask] = type;
307 }
308 }
309
310 edepth++;
311
312 if( ss == sb ) sele = 0;
313 else sele = get_element( sele , ss & mask , mhmask[cpu][edepth] ,
314 subelement , ele_max );
315 if( ee == eb ) eele = 0;
316 else eele = get_element( eele , ee & mask , mhmask[cpu][edepth] ,
317 subelement , ele_max );
318
319 }while( sele || eele );
320 }
321
322
323 /* ASG 980121 -- allocate all the external memory */
memory_allocate_ext(void)324 static int memory_allocate_ext (void)
325 {
326 struct ExtMemory *ext = ext_memory;
327 int cpu;
328
329 /* a change for MESS */
330 if (Machine->gamedrv->rom == 0) return 1;
331
332 /* loop over all CPUs */
333 for (cpu = 0; cpu < cpu_gettotalcpu (); cpu++)
334 {
335 const struct MemoryReadAddress *mra;
336 const struct MemoryWriteAddress *mwa;
337
338 int region = REGION_CPU1+cpu;
339 int size = memory_region_length(region);
340
341 /* now it's time to loop */
342 while (1)
343 {
344 int lowest = 0x7fffffff, end, lastend;
345
346 /* find the base of the lowest memory region that extends past the end */
347 for (mra = Machine->drv->cpu[cpu].memory_read; mra->start != -1; mra++)
348 if (mra->end >= size && mra->start < lowest) lowest = mra->start;
349 for (mwa = Machine->drv->cpu[cpu].memory_write; mwa->start != -1; mwa++)
350 if (mwa->end >= size && mwa->start < lowest) lowest = mwa->start;
351
352 /* done if nothing found */
353 if (lowest == 0x7fffffff)
354 break;
355
356 /* now loop until we find the end of this contiguous block of memory */
357 lastend = -1;
358 end = lowest;
359 while (end != lastend)
360 {
361 lastend = end;
362
363 /* find the base of the lowest memory region that extends past the end */
364 for (mra = Machine->drv->cpu[cpu].memory_read; mra->start != -1; mra++)
365 if (mra->start <= end && mra->end > end) end = mra->end + 1;
366 for (mwa = Machine->drv->cpu[cpu].memory_write; mwa->start != -1; mwa++)
367 if (mwa->start <= end && mwa->end > end) end = mwa->end + 1;
368 }
369
370 /* time to allocate */
371 ext->start = lowest;
372 ext->end = end - 1;
373 ext->region = region;
374 ext->data = (unsigned char *) malloc(end - lowest);
375
376 /* if that fails, we're through */
377 if (!ext->data)
378 return 0;
379
380 /* reset the memory */
381 memset (ext->data, 0, end - lowest);
382 size = ext->end + 1;
383 ext++;
384 }
385 }
386
387 return 1;
388 }
389
390
findmemorychunk(int cpu,int offset,int * chunkstart,int * chunkend)391 unsigned char *findmemorychunk(int cpu, int offset, int *chunkstart, int *chunkend)
392 {
393 int region = REGION_CPU1+cpu;
394 struct ExtMemory *ext;
395
396 /* look in external memory first */
397 for (ext = ext_memory; ext->data; ext++)
398 if (ext->region == region && ext->start <= offset && ext->end >= offset)
399 {
400 *chunkstart = ext->start;
401 *chunkend = ext->end;
402 return ext->data;
403 }
404
405 /* return RAM */
406 *chunkstart = 0;
407 *chunkend = memory_region_length(region) - 1;
408 return ramptr[cpu];
409 }
410
411
memory_find_base(int cpu,int offset)412 unsigned char *memory_find_base (int cpu, int offset)
413 {
414 int region = REGION_CPU1+cpu;
415 struct ExtMemory *ext;
416
417 /* look in external memory first */
418 for (ext = ext_memory; ext->data; ext++)
419 if (ext->region == region && ext->start <= offset && ext->end >= offset)
420 return ext->data + (offset - ext->start);
421
422 return ramptr[cpu] + offset;
423 }
424
425 /* make these static so they can be used in a callback by game drivers */
426
427 static int rdelement_max = 0;
428 static int wrelement_max = 0;
429 static int rdhard_max = HT_USER;
430 static int wrhard_max = HT_USER;
431
432 /* return = FALSE:can't allocate element memory */
memory_init(void)433 int memory_init(void)
434 {
435 int i, cpu;
436 const struct MemoryReadAddress *memoryread;
437 const struct MemoryWriteAddress *memorywrite;
438 const struct MemoryReadAddress *mra;
439 const struct MemoryWriteAddress *mwa;
440 const struct IOReadPort *ioread;
441 const struct IOWritePort *iowrite;
442 int abits1,abits2,abits3,abitsmin;
443 rdelement_max = 0;
444 wrelement_max = 0;
445 rdhard_max = HT_USER;
446 wrhard_max = HT_USER;
447
448 for( cpu = 0 ; cpu < MAX_CPU ; cpu++ )
449 cur_mr_element[cpu] = cur_mw_element[cpu] = 0;
450
451 ophw = 0xff;
452
453 /* ASG 980121 -- allocate external memory */
454 if (!memory_allocate_ext ())
455 return 0;
456
457 for( cpu = 0 ; cpu < cpu_gettotalcpu() ; cpu++ )
458 {
459 const struct MemoryReadAddress *_mra;
460 const struct MemoryWriteAddress *_mwa;
461
462 setOPbasefunc[cpu] = NULL;
463
464 ramptr[cpu] = romptr[cpu] = memory_region(REGION_CPU1+cpu);
465
466 /* initialize the memory base pointers for memory hooks */
467 _mra = Machine->drv->cpu[cpu].memory_read;
468 if (_mra)
469 {
470 while (_mra->start != -1)
471 {
472 // if (_mra->base) *_mra->base = memory_find_base (cpu, _mra->start);
473 // if (_mra->size) *_mra->size = _mra->end - _mra->start + 1;
474 _mra++;
475 }
476 }
477 _mwa = Machine->drv->cpu[cpu].memory_write;
478 if (_mwa)
479 {
480 while (_mwa->start != -1)
481 {
482 if (_mwa->base) *_mwa->base = memory_find_base (cpu, _mwa->start);
483 if (_mwa->size) *_mwa->size = _mwa->end - _mwa->start + 1;
484 _mwa++;
485 }
486 }
487
488 /* initialize port structures */
489 readport_size[cpu] = 0;
490 writeport_size[cpu] = 0;
491 readport[cpu] = 0;
492 writeport[cpu] = 0;
493
494 /* install port handlers - at least an empty one */
495 ioread = Machine->drv->cpu[cpu].port_read;
496 if (ioread == 0) ioread = empty_readport;
497
498 while (1)
499 {
500 if (install_port_read_handler_common(cpu, ioread->start, ioread->end, ioread->handler, 0) == 0)
501 {
502 memory_shutdown();
503 return 0;
504 }
505
506 if (ioread->start == -1) break;
507
508 ioread++;
509 }
510
511
512 iowrite = Machine->drv->cpu[cpu].port_write;
513 if (iowrite == 0) iowrite = empty_writeport;
514
515 while (1)
516 {
517 if (install_port_write_handler_common(cpu, iowrite->start, iowrite->end, iowrite->handler, 0) == 0)
518 {
519 memory_shutdown();
520 return 0;
521 }
522
523 if (iowrite->start == -1) break;
524
525 iowrite++;
526 }
527
528 portmask[cpu] = 0xffff;
529 #if (HAS_Z80)
530 if ((Machine->drv->cpu[cpu].cpu_type & ~CPU_FLAGS_MASK) == CPU_Z80 &&
531 (Machine->drv->cpu[cpu].cpu_type & CPU_16BIT_PORT) == 0)
532 portmask[cpu] = 0xff;
533 #endif
534 #if (HAS_DRZ80)
535 if ((Machine->drv->cpu[cpu].cpu_type & ~CPU_FLAGS_MASK) == CPU_DRZ80 &&
536 (Machine->drv->cpu[cpu].cpu_type & CPU_16BIT_PORT) == 0)
537 portmask[cpu] = 0xff;
538 #endif
539 }
540
541 /* initialize global handler */
542 for( i = 0 ; i < MH_HARDMAX ; i++ ){
543 memoryreadoffset[i] = 0;
544 memorywriteoffset[i] = 0;
545 }
546 /* bank memory */
547 for (i = 1; i <= MAX_BANKS; i++)
548 {
549 memoryreadhandler[i] = bank_read_handler[i];
550 memorywritehandler[i] = bank_write_handler[i];
551 }
552 /* non map memory */
553 memoryreadhandler[HT_NON] = mrh_error;
554 memorywritehandler[HT_NON] = mwh_error;
555 /* NOP memory */
556 memoryreadhandler[HT_NOP] = mrh_nop;
557 memorywritehandler[HT_NOP] = mwh_nop;
558 /* RAMROM memory */
559 memorywritehandler[HT_RAMROM] = mwh_ramrom;
560 /* ROM memory */
561 memorywritehandler[HT_ROM] = mwh_rom;
562
563 /* if any CPU is 21-bit or more, we change the error handlers to be more benign */
564 for (cpu = 0; cpu < cpu_gettotalcpu(); cpu++)
565 if (ADDRESS_BITS (cpu) >= 21)
566 {
567 memoryreadhandler[HT_NON] = mrh_error_sparse;
568 memorywritehandler[HT_NON] = mwh_error_sparse;
569 #if (HAS_TMS34010)
570 if ((Machine->drv->cpu[cpu].cpu_type & ~CPU_FLAGS_MASK)==CPU_TMS34010)
571 {
572 memoryreadhandler[HT_NON] = mrh_error_sparse_bit;
573 memorywritehandler[HT_NON] = mwh_error_sparse_bit;
574 }
575 #endif
576 }
577
578 for( cpu = 0 ; cpu < cpu_gettotalcpu() ; cpu++ )
579 {
580 /* cpu selection */
581 abits1 = ABITS1 (cpu);
582 abits2 = ABITS2 (cpu);
583 abits3 = ABITS3 (cpu);
584 abitsmin = ABITSMIN (cpu);
585
586 /* element shifter , mask set */
587 mhshift[cpu][0] = (abits2+abits3);
588 mhshift[cpu][1] = abits3; /* 2nd */
589 mhshift[cpu][2] = 0; /* 3rd (used by set_element)*/
590 mhmask[cpu][0] = MHMASK(abits1); /*1st(used by set_element)*/
591 mhmask[cpu][1] = MHMASK(abits2); /*2nd*/
592 mhmask[cpu][2] = MHMASK(abits3); /*3rd*/
593
594 /* allocate current element */
595 if( (cur_mr_element[cpu] = (MHELE *)malloc(sizeof(MHELE)<<abits1)) == 0 )
596 {
597 memory_shutdown();
598 return 0;
599 }
600 if( (cur_mw_element[cpu] = (MHELE *)malloc(sizeof(MHELE)<<abits1)) == 0 )
601 {
602 memory_shutdown();
603 return 0;
604 }
605
606 /* initialize current element table */
607 for( i = 0 ; i < (1<<abits1) ; i++ )
608 {
609 cur_mr_element[cpu][i] = HT_NON; /* no map memory */
610 cur_mw_element[cpu][i] = HT_NON; /* no map memory */
611 }
612
613 memoryread = Machine->drv->cpu[cpu].memory_read;
614 memorywrite = Machine->drv->cpu[cpu].memory_write;
615
616 /* memory read handler build */
617 if (memoryread)
618 {
619 mra = memoryread;
620 while (mra->start != -1) mra++;
621 mra--;
622
623 while (mra >= memoryread)
624 {
625 install_mem_read_handler (cpu, mra->start, mra->end, mra->handler);
626 mra--;
627 }
628 }
629
630 /* memory write handler build */
631 if (memorywrite)
632 {
633 mwa = memorywrite;
634 while (mwa->start != -1) mwa++;
635 mwa--;
636
637 while (mwa >= memorywrite)
638 {
639 install_mem_write_handler (cpu, mwa->start, mwa->end, mwa->handler);
640 mwa--;
641 }
642 }
643 }
644
645 logerror("used read elements %d/%d , functions %d/%d\n"
646 ,rdelement_max,MH_ELEMAX , rdhard_max,MH_HARDMAX );
647 logerror("used write elements %d/%d , functions %d/%d\n"
648 ,wrelement_max,MH_ELEMAX , wrhard_max,MH_HARDMAX );
649
650 #ifdef MEM_DUMP
651 mem_dump();
652 #endif
653 return 1; /* ok */
654 }
655
memory_set_opcode_base(int cpu,unsigned char * base)656 void memory_set_opcode_base(int cpu,unsigned char *base)
657 {
658 romptr[cpu] = base;
659 }
660
661
memorycontextswap(int activecpu)662 void memorycontextswap(int activecpu)
663 {
664 cpu_bankbase[0] = ramptr[activecpu];
665
666 cur_mrhard = cur_mr_element[activecpu];
667 cur_mwhard = cur_mw_element[activecpu];
668
669 /* ASG: port speedup */
670 cur_readport = readport[activecpu];
671 cur_writeport = writeport[activecpu];
672 cur_portmask = portmask[activecpu];
673
674 OPbasefunc = setOPbasefunc[activecpu];
675
676 /* op code memory pointer */
677 ophw = HT_RAM;
678 OP_RAM = cpu_bankbase[0];
679 OP_ROM = romptr[activecpu];
680 }
681
memory_shutdown(void)682 void memory_shutdown(void)
683 {
684 struct ExtMemory *ext;
685 int cpu;
686
687 for( cpu = 0 ; cpu < MAX_CPU ; cpu++ )
688 {
689 if( cur_mr_element[cpu] != 0 )
690 {
691 free( cur_mr_element[cpu] );
692 cur_mr_element[cpu] = 0;
693 }
694 if( cur_mw_element[cpu] != 0 )
695 {
696 free( cur_mw_element[cpu] );
697 cur_mw_element[cpu] = 0;
698 }
699
700 if (readport[cpu] != 0)
701 {
702 free(readport[cpu]);
703 readport[cpu] = 0;
704 }
705
706 if (writeport[cpu] != 0)
707 {
708 free(writeport[cpu]);
709 writeport[cpu] = 0;
710 }
711 }
712
713 /* ASG 980121 -- free all the external memory */
714 for (ext = ext_memory; ext->data; ext++)
715 free(ext->data);
716 memset (ext_memory, 0, sizeof (ext_memory));
717 }
718
719
720
721 /***************************************************************************
722
723 Perform a memory read. This function is called by the CPU emulation.
724
725 ***************************************************************************/
726
727 /* use these constants to define which type of memory handler to build */
728 #define TYPE_8BIT 0 /* 8-bit aligned */
729 #define TYPE_16BIT_BE 1 /* 16-bit aligned, big-endian */
730 #define TYPE_16BIT_LE 2 /* 16-bit aligned, little-endian */
731
732 #define CAN_BE_MISALIGNED 0 /* word/dwords can be read on non-16-bit boundaries */
733 #define ALWAYS_ALIGNED 1 /* word/dwords are always read on 16-bit boundaries */
734
735 #ifndef MAME_MEMINLINE
736 #include "memory_read.h"
737 #endif
738
739 /***************************************************************************
740
741 Perform a memory write. This function is called by the CPU emulation.
742
743 ***************************************************************************/
744
745 #ifndef MAME_MEMINLINE
746 #include "memory_write.h"
747 #endif
748
749 /***************************************************************************
750
751 Opcode base changers. This function is called by the CPU emulation.
752
753 ***************************************************************************/
754
755 /* generic opcode base changer */
756 #define SETOPBASE(name,abits,shift) \
757 void name(int pc) \
758 { \
759 MHELE hw; \
760 \
761 pc = (UINT32)pc >> shift; \
762 \
763 /* allow overrides */ \
764 if (OPbasefunc) \
765 { \
766 pc = OPbasefunc(pc); \
767 if (pc == -1) \
768 return; \
769 } \
770 \
771 /* perform the lookup */ \
772 hw = cur_mrhard[(UINT32)pc >> (ABITS2_##abits + ABITS_MIN_##abits)]; \
773 if (hw >= MH_HARDMAX) \
774 { \
775 hw -= MH_HARDMAX; \
776 hw = readhardware[(hw << MH_SBITS) + (((UINT32)pc >> ABITS_MIN_##abits) & MHMASK(ABITS2_##abits))]; \
777 } \
778 ophw = hw; \
779 \
780 /* RAM or banked memory */ \
781 if (hw <= HT_BANKMAX) \
782 { \
783 SET_OP_RAMROM(cpu_bankbase[hw] - memoryreadoffset[hw]) \
784 return; \
785 } \
786 \
787 /* do not support on callback memory region */ \
788 logerror("CPU #%d PC %04x: warning - op-code execute on mapped i/o\n", \
789 cpu_getactivecpu(),cpu_get_pc()); \
790 }
791
792
793 /* the handlers we need to generate */
794 SETOPBASE(cpu_setOPbase16, 16, 0)
795 SETOPBASE(cpu_setOPbase16bew, 16BEW, 0)
796 SETOPBASE(cpu_setOPbase16lew, 16LEW, 0)
797 SETOPBASE(cpu_setOPbase20, 20, 0)
798 SETOPBASE(cpu_setOPbase21, 21, 0)
799 SETOPBASE(cpu_setOPbase24, 24, 0)
800 SETOPBASE(cpu_setOPbase24bew, 24BEW, 0)
801 SETOPBASE(cpu_setOPbase29, 29, 3)
802 SETOPBASE(cpu_setOPbase32, 32, 0)
803 SETOPBASE(cpu_setOPbase32lew, 32LEW, 0)
804
805
806 /***************************************************************************
807
808 Perform an I/O port read. This function is called by the CPU emulation.
809
810 ***************************************************************************/
cpu_readport(int port)811 int cpu_readport(int port)
812 {
813 const struct IOReadPort *iorp = cur_readport;
814
815 port &= cur_portmask;
816
817 /* search the handlers. The order is as follows: first the dynamically installed
818 handlers are searched, followed by the static ones in whatever order they were
819 specified in the driver */
820 while (iorp->start != -1)
821 {
822 if (port >= iorp->start && port <= iorp->end)
823 {
824 mem_read_handler handler = iorp->handler;
825
826
827 if (handler == IORP_NOP) return 0;
828 else return (*handler)(port - iorp->start);
829 }
830
831 iorp++;
832 }
833
834 logerror("CPU #%d PC %04x: warning - read unmapped I/O port %02x\n",cpu_getactivecpu(),cpu_get_pc(),port);
835 return 0;
836 }
837
838
839 /***************************************************************************
840
841 Perform an I/O port write. This function is called by the CPU emulation.
842
843 ***************************************************************************/
cpu_writeport(int port,int value)844 void cpu_writeport(int port, int value)
845 {
846 const struct IOWritePort *iowp = cur_writeport;
847
848 port &= cur_portmask;
849
850 /* search the handlers. The order is as follows: first the dynamically installed
851 handlers are searched, followed by the static ones in whatever order they were
852 specified in the driver */
853 while (iowp->start != -1)
854 {
855 if (port >= iowp->start && port <= iowp->end)
856 {
857 mem_write_handler handler = iowp->handler;
858
859
860 if (handler == IOWP_NOP) return;
861 else (*handler)(port - iowp->start,value);
862
863 return;
864 }
865
866 iowp++;
867 }
868
869 logerror("CPU #%d PC %04x: warning - write %02x to unmapped I/O port %02x\n",cpu_getactivecpu(),cpu_get_pc(),value,port);
870 }
871
872
873 /* set readmemory handler for bank memory */
cpu_setbankhandler_r(int bank,mem_read_handler handler)874 void cpu_setbankhandler_r(int bank, mem_read_handler handler)
875 {
876 int offset = 0;
877 MHELE hardware;
878
879 if ((((FPTR)handler)== ((FPTR)MRA_RAM)) || (((FPTR)handler)==((FPTR)MRA_ROM)))
880 {
881 handler = mrh_ram;
882 }
883 else if ((((FPTR)handler)==((FPTR)MRA_BANK1)) || (((FPTR)handler)==((FPTR)MRA_BANK2)) ||
884 (((FPTR)handler)==((FPTR)MRA_BANK3)) || (((FPTR)handler)==((FPTR)MRA_BANK4)) ||
885 (((FPTR)handler)==((FPTR)MRA_BANK5)) || (((FPTR)handler)==((FPTR)MRA_BANK6)) ||
886 (((FPTR)handler)==((FPTR)MRA_BANK7)) || (((FPTR)handler)==((FPTR)MRA_BANK8)) ||
887 (((FPTR)handler)==((FPTR)MRA_BANK9)) || (((FPTR)handler)==((FPTR)MRA_BANK10)) ||
888 (((FPTR)handler)==((FPTR)MRA_BANK11)) || (((FPTR)handler)==((FPTR)MRA_BANK12)) ||
889 (((FPTR)handler)==((FPTR)MRA_BANK13)) || (((FPTR)handler)==((FPTR)MRA_BANK14)) ||
890 (((FPTR)handler)==((FPTR)MRA_BANK15)) || (((FPTR)handler)==((FPTR)MRA_BANK16)))
891 {
892 hardware = (intptr_t)MWA_BANK1 - (intptr_t)handler + 1;
893 handler = bank_read_handler[hardware];
894 offset = bankreadoffset[hardware];
895 }
896 else if (((FPTR)handler)==((FPTR)MRA_NOP))
897 {
898 handler = mrh_nop;
899 }
900 else
901 {
902 offset = bankreadoffset[bank];
903 }
904 memoryreadoffset[bank] = offset;
905 memoryreadhandler[bank] = handler;
906 }
907
908 /* set writememory handler for bank memory */
cpu_setbankhandler_w(int bank,mem_write_handler handler)909 void cpu_setbankhandler_w(int bank, mem_write_handler handler)
910 {
911 int offset = 0;
912 MHELE hardware;
913
914 if (((FPTR)handler)==((FPTR)MWA_RAM))
915 {
916 handler = mwh_ram;
917 }
918 else if ((((FPTR)handler)==((FPTR)MWA_BANK1)) || (((FPTR)handler)==((FPTR)MWA_BANK2)) ||
919 (((FPTR)handler)==((FPTR)MWA_BANK3)) || (((FPTR)handler)==((FPTR)MWA_BANK4)) ||
920 (((FPTR)handler)==((FPTR)MWA_BANK5)) || (((FPTR)handler)==((FPTR)MWA_BANK6)) ||
921 (((FPTR)handler)==((FPTR)MWA_BANK7)) || (((FPTR)handler)==((FPTR)MWA_BANK8)) ||
922 (((FPTR)handler)==((FPTR)MWA_BANK9)) || (((FPTR)handler)==((FPTR)MWA_BANK10)) ||
923 (((FPTR)handler)==((FPTR)MWA_BANK11)) || (((FPTR)handler)==((FPTR)MWA_BANK12)) ||
924 (((FPTR)handler)==((FPTR)MWA_BANK13)) || (((FPTR)handler)==((FPTR)MWA_BANK14)) ||
925 (((FPTR)handler)==((FPTR)MWA_BANK15)) || (((FPTR)handler)==((FPTR)MWA_BANK16)))
926 {
927 hardware = (intptr_t)MWA_BANK1 - (intptr_t)handler + 1;
928 handler = bank_write_handler[hardware];
929 offset = bankwriteoffset[hardware];
930 }
931 else if (((FPTR)handler)==((FPTR)MWA_NOP))
932 {
933 handler = mwh_nop;
934 }
935 else if (((FPTR)handler)==((FPTR)(FPTR)MWA_RAMROM))
936 {
937 handler = mwh_ramrom;
938 }
939 else if (((FPTR)handler)==((FPTR)MWA_ROM))
940 {
941 handler = mwh_rom;
942 }
943 else
944 {
945 offset = bankwriteoffset[bank];
946 }
947 memorywriteoffset[bank] = offset;
948 memorywritehandler[bank] = handler;
949 }
950
951 /* cpu change op-code memory base */
cpu_setOPbaseoverride(int cpu,opbase_handler function)952 void cpu_setOPbaseoverride (int cpu,opbase_handler function)
953 {
954 setOPbasefunc[cpu] = function;
955 if (cpu == cpu_getactivecpu())
956 OPbasefunc = function;
957 }
958
959
install_mem_read_handler(int cpu,int start,int end,mem_read_handler handler)960 void *install_mem_read_handler(int cpu, int start, int end, mem_read_handler handler)
961 {
962 MHELE hardware = 0;
963 int abitsmin;
964 int i, hw_set;
965 #if VERBOSE
966 logerror("Install new memory read handler:\n");
967 logerror(" cpu: %d\n", cpu);
968 logerror(" start: 0x%08x\n", start);
969 logerror(" end: 0x%08x\n", end);
970 #ifdef __LP64__
971 logerror(" handler address: 0x%016lx\n", (unsigned long) handler);
972 #else
973 logerror(" handler address: 0x%08x\n", (unsigned int) handler);
974 #endif
975 #endif
976 abitsmin = ABITSMIN (cpu);
977
978 /* see if this function is already registered */
979 hw_set = 0;
980 for ( i = 0 ; i < MH_HARDMAX ; i++)
981 {
982 /* record it if it matches */
983 if (( memoryreadhandler[i] == handler ) &&
984 ( memoryreadoffset[i] == start))
985 {
986 #if VERBOSE
987 logerror("handler match - use old one\n");
988 #endif
989 hardware = i;
990 hw_set = 1;
991 }
992 }
993 if ((((FPTR)handler)==((FPTR)MRA_RAM)) || (((FPTR)handler)==((FPTR)MRA_ROM)))
994 {
995 hardware = HT_RAM; /* special case ram read */
996 hw_set = 1;
997 }
998 if ((((FPTR)handler)==((FPTR)MRA_BANK1)) || (((FPTR)handler)==((FPTR)MRA_BANK2)) ||
999 (((FPTR)handler)==((FPTR)MRA_BANK3)) || (((FPTR)handler)==((FPTR)MRA_BANK4)) ||
1000 (((FPTR)handler)==((FPTR)MRA_BANK5)) || (((FPTR)handler)==((FPTR)MRA_BANK6)) ||
1001 (((FPTR)handler)==((FPTR)MRA_BANK7)) || (((FPTR)handler)==((FPTR)MRA_BANK8)) ||
1002 (((FPTR)handler)==((FPTR)MRA_BANK9)) || (((FPTR)handler)==((FPTR)MRA_BANK10)) ||
1003 (((FPTR)handler)==((FPTR)MRA_BANK11)) || (((FPTR)handler)==((FPTR)MRA_BANK12)) ||
1004 (((FPTR)handler)==((FPTR)MRA_BANK13)) || (((FPTR)handler)==((FPTR)MRA_BANK14)) ||
1005 (((FPTR)handler)==((FPTR)MRA_BANK15)) || (((FPTR)handler)==((FPTR)MRA_BANK16)))
1006 {
1007 hardware = (intptr_t)MRA_BANK1 - (intptr_t)handler + 1;
1008 memoryreadoffset[hardware] = bankreadoffset[hardware] = start;
1009 cpu_bankbase[hardware] = memory_find_base(cpu, start);
1010 hw_set = 1;
1011 }
1012 else if (((FPTR)handler)==((FPTR)MRA_NOP))
1013 {
1014 hardware = HT_NOP;
1015 hw_set = 1;
1016 }
1017 if (!hw_set) /* no match */
1018 {
1019 /* create newer hardware handler */
1020 if( rdhard_max == MH_HARDMAX )
1021 {
1022 logerror("read memory hardware pattern over !\n");
1023 logerror("Failed to install new memory handler.\n");
1024 return memory_find_base(cpu, start);
1025 }
1026 else
1027 {
1028 /* register hardware function */
1029 hardware = rdhard_max++;
1030 memoryreadhandler[hardware] = handler;
1031 memoryreadoffset[hardware] = start;
1032 }
1033 }
1034 /* set hardware element table entry */
1035 set_element( cpu , cur_mr_element[cpu] ,
1036 (((unsigned int) start) >> abitsmin) ,
1037 (((unsigned int) end) >> abitsmin) ,
1038 hardware , readhardware , &rdelement_max );
1039 #if VERBOSE
1040 logerror("Done installing new memory handler.\n");
1041 logerror("used read elements %d/%d , functions %d/%d\n"
1042 ,rdelement_max,MH_ELEMAX , rdhard_max,MH_HARDMAX );
1043 #endif
1044 return memory_find_base(cpu, start);
1045 }
1046
install_mem_write_handler(int cpu,int start,int end,mem_write_handler handler)1047 void *install_mem_write_handler(int cpu, int start, int end, mem_write_handler handler)
1048 {
1049 MHELE hardware = 0;
1050 int abitsmin;
1051 int i, hw_set;
1052 #if VERBOSE
1053 logerror("Install new memory write handler:\n");
1054 logerror(" cpu: %d\n", cpu);
1055 logerror(" start: 0x%08x\n", start);
1056 logerror(" end: 0x%08x\n", end);
1057 #ifdef __LP64__
1058 logerror(" handler address: 0x%016lx\n", (unsigned long) handler);
1059 #else
1060 logerror(" handler address: 0x%08x\n", (unsigned int) handler);
1061 #endif
1062 #endif
1063 abitsmin = ABITSMIN (cpu);
1064
1065 /* see if this function is already registered */
1066 hw_set = 0;
1067 for ( i = 0 ; i < MH_HARDMAX ; i++)
1068 {
1069 /* record it if it matches */
1070 if (( memorywritehandler[i] == handler ) &&
1071 ( memorywriteoffset[i] == start))
1072 {
1073 #if VERBOSE
1074 logerror("handler match - use old one\n");
1075 #endif
1076 hardware = i;
1077 hw_set = 1;
1078 }
1079 }
1080
1081 if (((FPTR)handler)==((FPTR)MWA_RAM))
1082 {
1083 hardware = HT_RAM; /* special case ram write */
1084 hw_set = 1;
1085 }
1086 else if ((((FPTR)handler)==((FPTR)MWA_BANK1)) || (((FPTR)handler)==((FPTR)MWA_BANK2)) ||
1087 (((FPTR)handler)==((FPTR)MWA_BANK3)) || (((FPTR)handler)==((FPTR)MWA_BANK4)) ||
1088 (((FPTR)handler)==((FPTR)MWA_BANK5)) || (((FPTR)handler)==((FPTR)MWA_BANK6)) ||
1089 (((FPTR)handler)==((FPTR)MWA_BANK7)) || (((FPTR)handler)==((FPTR)MWA_BANK8)) ||
1090 (((FPTR)handler)==((FPTR)MWA_BANK9)) || (((FPTR)handler)==((FPTR)MWA_BANK10)) ||
1091 (((FPTR)handler)==((FPTR)MWA_BANK11)) || (((FPTR)handler)==((FPTR)MWA_BANK12)) ||
1092 (((FPTR)handler)==((FPTR)MWA_BANK13)) || (((FPTR)handler)==((FPTR)MWA_BANK14)) ||
1093 (((FPTR)handler)==((FPTR)MWA_BANK15)) || (((FPTR)handler)==((FPTR)MWA_BANK16)))
1094 {
1095 hardware = (intptr_t)MWA_BANK1 - (intptr_t)handler + 1;
1096 memorywriteoffset[hardware] = bankwriteoffset[hardware] = start;
1097 cpu_bankbase[hardware] = memory_find_base(cpu, start);
1098 hw_set = 1;
1099 }
1100 else if (((FPTR)handler)==((FPTR)MWA_NOP))
1101 {
1102 hardware = HT_NOP;
1103 hw_set = 1;
1104 }
1105 else if (((FPTR)handler)==((FPTR)MWA_RAMROM))
1106 {
1107 hardware = HT_RAMROM;
1108 hw_set = 1;
1109 }
1110 else if (((FPTR)handler)==((FPTR)MWA_ROM))
1111 {
1112 hardware = HT_ROM;
1113 hw_set = 1;
1114 }
1115 if (!hw_set) /* no match */
1116 {
1117 /* create newer hardware handler */
1118 if( wrhard_max == MH_HARDMAX )
1119 {
1120 logerror("write memory hardware pattern over !\n");
1121 logerror("Failed to install new memory handler.\n");
1122
1123 return memory_find_base(cpu, start);
1124 }
1125 else
1126 {
1127 /* register hardware function */
1128 hardware = wrhard_max++;
1129 memorywritehandler[hardware] = handler;
1130 memorywriteoffset[hardware] = start;
1131 }
1132 }
1133 /* set hardware element table entry */
1134 set_element( cpu , cur_mw_element[cpu] ,
1135 (((unsigned int) start) >> abitsmin) ,
1136 (((unsigned int) end) >> abitsmin) ,
1137 hardware , writehardware , &wrelement_max );
1138 #if VERBOSE
1139 logerror("Done installing new memory handler.\n");
1140 logerror("used write elements %d/%d , functions %d/%d\n"
1141 ,wrelement_max,MH_ELEMAX , wrhard_max,MH_HARDMAX );
1142 #endif
1143 return memory_find_base(cpu, start);
1144 }
1145
install_port_read_handler(int cpu,int start,int end,mem_read_handler handler)1146 void *install_port_read_handler(int cpu, int start, int end, mem_read_handler handler)
1147 {
1148 return install_port_read_handler_common(cpu, start, end, handler, 1);
1149 }
1150
install_port_write_handler(int cpu,int start,int end,mem_write_handler handler)1151 void *install_port_write_handler(int cpu, int start, int end, mem_write_handler handler)
1152 {
1153 return install_port_write_handler_common(cpu, start, end, handler, 1);
1154 }
1155
install_port_read_handler_common(int cpu,int start,int end,mem_read_handler handler,int install_at_beginning)1156 static void *install_port_read_handler_common(int cpu, int start, int end,
1157 mem_read_handler handler, int install_at_beginning)
1158 {
1159 int i, oldsize;
1160
1161 oldsize = readport_size[cpu];
1162 readport_size[cpu] += sizeof(struct IOReadPort);
1163
1164 if (readport[cpu] == 0)
1165 {
1166 readport[cpu] = malloc(readport_size[cpu]);
1167 }
1168 else
1169 {
1170 readport[cpu] = realloc(readport[cpu], readport_size[cpu]);
1171 }
1172
1173 if (readport[cpu] == 0) return 0;
1174
1175 if (install_at_beginning)
1176 {
1177 /* can't do a single memcpy because it doesn't handle overlapping regions correctly??? */
1178 for (i = oldsize / sizeof(struct IOReadPort); i >= 1; i--)
1179 {
1180 memcpy(&readport[cpu][i], &readport[cpu][i - 1], sizeof(struct IOReadPort));
1181 }
1182
1183 i = 0;
1184 }
1185 else
1186 {
1187 i = oldsize / sizeof(struct IOReadPort);
1188 }
1189
1190 #ifdef MEM_DUMP
1191 logerror("Installing port read handler: cpu %d slot %X start %X end %X\n", cpu, i, start, end);
1192 #endif
1193
1194 readport[cpu][i].start = start;
1195 readport[cpu][i].end = end;
1196 readport[cpu][i].handler = handler;
1197
1198 return readport[cpu];
1199 }
1200
install_port_write_handler_common(int cpu,int start,int end,mem_write_handler handler,int install_at_beginning)1201 static void *install_port_write_handler_common(int cpu, int start, int end,
1202 mem_write_handler handler, int install_at_beginning)
1203 {
1204 int i, oldsize;
1205
1206 oldsize = writeport_size[cpu];
1207 writeport_size[cpu] += sizeof(struct IOWritePort);
1208
1209 if (writeport[cpu] == 0)
1210 {
1211 writeport[cpu] = malloc(writeport_size[cpu]);
1212 }
1213 else
1214 {
1215 writeport[cpu] = realloc(writeport[cpu], writeport_size[cpu]);
1216 }
1217
1218 if (writeport[cpu] == 0) return 0;
1219
1220 if (install_at_beginning)
1221 {
1222 /* can't do a single memcpy because it doesn't handle overlapping regions correctly??? */
1223 for (i = oldsize / sizeof(struct IOWritePort); i >= 1; i--)
1224 {
1225 memcpy(&writeport[cpu][i], &writeport[cpu][i - 1], sizeof(struct IOWritePort));
1226 }
1227
1228 i = 0;
1229 }
1230 else
1231 {
1232 i = oldsize / sizeof(struct IOWritePort);
1233 }
1234
1235 #ifdef MEM_DUMP
1236 logerror("Installing port write handler: cpu %d slot %X start %X end %X\n", cpu, i, start, end);
1237 #endif
1238
1239 writeport[cpu][i].start = start;
1240 writeport[cpu][i].end = end;
1241 writeport[cpu][i].handler = handler;
1242
1243 return writeport[cpu];
1244 }
1245
1246 #ifdef MEM_DUMP
mem_dump(void)1247 static void mem_dump( void )
1248 {
1249 extern int totalcpu;
1250 int cpu;
1251 int naddr,addr;
1252 MHELE nhw,hw;
1253
1254 FILE *temp = fopen ("memdump.log", "w");
1255
1256 if (!temp) return;
1257
1258 for( cpu = 0 ; cpu < 1 ; cpu++ )
1259 {
1260 fprintf(temp,"cpu %d read memory \n",cpu);
1261 addr = 0;
1262 naddr = 0;
1263 nhw = 0xff;
1264 while( (addr >> mhshift[cpu][0]) <= mhmask[cpu][0] ){
1265 hw = cur_mr_element[cpu][addr >> mhshift[cpu][0]];
1266 if( hw >= MH_HARDMAX )
1267 { /* 2nd element link */
1268 hw = readhardware[((hw-MH_HARDMAX)<<MH_SBITS) + ((addr>>mhshift[cpu][1]) & mhmask[cpu][1])];
1269 if( hw >= MH_HARDMAX )
1270 hw = readhardware[((hw-MH_HARDMAX)<<MH_SBITS) + (addr & mhmask[cpu][2])];
1271 }
1272 if( nhw != hw )
1273 {
1274 if( addr )
1275 fprintf(temp," %08x(%08x) - %08x = %02x\n",naddr,memoryreadoffset[nhw],addr-1,nhw);
1276 nhw = hw;
1277 naddr = addr;
1278 }
1279 addr++;
1280 }
1281 fprintf(temp," %08x(%08x) - %08x = %02x\n",naddr,memoryreadoffset[nhw],addr-1,nhw);
1282
1283 fprintf(temp,"cpu %d write memory \n",cpu);
1284 naddr = 0;
1285 addr = 0;
1286 nhw = 0xff;
1287 while( (addr >> mhshift[cpu][0]) <= mhmask[cpu][0] ){
1288 hw = cur_mw_element[cpu][addr >> mhshift[cpu][0]];
1289 if( hw >= MH_HARDMAX )
1290 { /* 2nd element link */
1291 hw = writehardware[((hw-MH_HARDMAX)<<MH_SBITS) + ((addr>>mhshift[cpu][1]) & mhmask[cpu][1])];
1292 if( hw >= MH_HARDMAX )
1293 hw = writehardware[((hw-MH_HARDMAX)<<MH_SBITS) + (addr & mhmask[cpu][2])];
1294 }
1295 if( nhw != hw )
1296 {
1297 if( addr )
1298 fprintf(temp," %08x(%08x) - %08x = %02x\n",naddr,memorywriteoffset[nhw],addr-1,nhw);
1299 nhw = hw;
1300 naddr = addr;
1301 }
1302 addr++;
1303 }
1304 fprintf(temp," %08x(%08x) - %08x = %02x\n",naddr,memorywriteoffset[nhw],addr-1,nhw);
1305 }
1306 fclose(temp);
1307 }
1308 #endif
1309
1310