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