PCem

view src/mem.c @ 116:4081a8dbce5b

Switched IBM AT to more recent BIOS. Added 8 MHz option. Patch from SA1988.
author TomW
date Tue Jul 08 20:35:39 2014 +0100
parents eb624a751863
children d0d530adce12
line source
1 /*MESS ROM notes :
3 - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM)
4 - pc2386 video BIOS is underdumped (16k instead of 24k)
5 - c386sx16 BIOS fails checksum
6 */
8 #include <stdlib.h>
9 #include <string.h>
10 #include "ibm.h"
12 #include "config.h"
13 #include "mem.h"
14 #include "video.h"
15 #include "x86.h"
16 #include "cpu.h"
17 #include "rom.h"
19 static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv);
20 static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv);
21 static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv);
22 static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv);
23 static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv);
24 static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv);
25 static uint8_t *_mem_exec[0x40000];
26 static void *_mem_priv_r[0x40000];
27 static void *_mem_priv_w[0x40000];
28 static mem_mapping_t *_mem_mapping_r[0x40000];
29 static mem_mapping_t *_mem_mapping_w[0x40000];
30 static int _mem_state[0x40000];
32 static mem_mapping_t base_mapping;
33 static mem_mapping_t ram_low_mapping;
34 static mem_mapping_t ram_high_mapping;
35 static mem_mapping_t ram_mid_mapping;
36 static mem_mapping_t bios_mapping[8];
37 static mem_mapping_t bios_high_mapping[8];
38 static mem_mapping_t romext_mapping;
40 int shadowbios,shadowbios_write;
42 static unsigned char isram[0x10000];
44 int mem_size;
45 int cache=4;
46 uint32_t biosmask;
47 int readlnum=0,writelnum=0;
48 int cachesize=256;
50 uint8_t *ram,*rom,*vram;
51 uint8_t romext[32768];
53 static void mem_load_xtide_bios()
54 {
55 FILE *f;
56 f=romfopen("roms/ide_xt.bin","rb");
58 // is486=0;
59 if (f)
60 {
61 fread(romext,16384,1,f);
62 fclose(f);
63 }
64 }
66 static void mem_load_atide_bios()
67 {
68 FILE *f;
69 f=romfopen("roms/ide_at.bin","rb");
71 // is486=0;
72 if (f)
73 {
74 fread(romext,16384,1,f);
75 fclose(f);
76 }
77 }
79 int loadbios()
80 {
81 FILE *f=NULL,*ff=NULL;
82 int c;
84 loadfont("mda.rom", 0);
86 biosmask = 0xffff;
88 memset(romext,0x63,0x4000);
90 pclog("Starting with romset %i\n", romset);
92 switch (romset)
93 {
94 case ROM_PC1512:
95 f=romfopen("roms/pc1512/40043.v1","rb");
96 ff=romfopen("roms/pc1512/40044.v1","rb");
97 if (!f || !ff) break;
98 for (c=0xC000;c<0x10000;c+=2)
99 {
100 rom[c]=getc(f);
101 rom[c+1]=getc(ff);
102 }
103 fclose(ff);
104 fclose(f);
105 mem_load_xtide_bios();
106 loadfont("roms/pc1512/40078.ic127", 2);
107 return 1;
108 case ROM_PC1640:
109 f=romfopen("roms/pc1640/40044.v3","rb");
110 ff=romfopen("roms/pc1640/40043.v3","rb");
111 if (!f || !ff) break;
112 for (c=0xC000;c<0x10000;c+=2)
113 {
114 rom[c]=getc(f);
115 rom[c+1]=getc(ff);
116 }
117 fclose(ff);
118 fclose(f);
119 f=romfopen("roms/pc1640/40100","rb");
120 if (!f) break;
121 fclose(f);
122 mem_load_xtide_bios();
123 return 1;
124 case ROM_PC200:
125 f=romfopen("roms/pc200/pc20v2.1","rb");
126 ff=romfopen("roms/pc200/pc20v2.0","rb");
127 if (!f || !ff) break;
128 for (c=0xC000;c<0x10000;c+=2)
129 {
130 rom[c]=getc(f);
131 rom[c+1]=getc(ff);
132 }
133 fclose(ff);
134 fclose(f);
135 mem_load_xtide_bios();
136 loadfont("roms/pc200/40109.bin", 1);
137 return 1;
138 case ROM_TANDY:
139 f=romfopen("roms/tandy/tandy1t1.020","rb");
140 if (!f) break;
141 fread(rom,65536,1,f);
142 fclose(f);
143 mem_load_xtide_bios();
144 return 1;
145 /* case ROM_IBMPCJR:
146 f=fopen("pcjr/bios.rom","rb");
147 fread(rom+0xE000,8192,1,f);
148 fclose(f);
149 f=fopen("pcjr/basic.rom","rb");
150 fread(rom+0x6000,32768,1,f);
151 fclose(f);
152 break;*/
153 case ROM_IBMXT:
154 f=romfopen("roms/ibmxt/xt.rom","rb");
155 if (!f)
156 {
157 f = romfopen("roms/ibmxt/5000027.u19", "rb");
158 ff = romfopen("roms/ibmxt/1501512.u18","rb");
159 if (!f || !ff) break;
160 fread(rom, 0x8000, 1, f);
161 fread(rom + 0x8000, 0x8000, 1, ff);
162 fclose(ff);
163 fclose(f);
164 mem_load_xtide_bios();
165 return 1;
166 }
167 else
168 {
169 fread(rom,65536,1,f);
170 fclose(f);
171 mem_load_xtide_bios();
172 return 1;
173 }
174 break;
176 case ROM_IBMPCJR:
177 f = romfopen("roms/ibmpcjr/bios.rom","rb");
178 if (!f) break;
179 fread(rom, 0x10000, 1, f);
180 fclose(f);
181 return 1;
183 case ROM_GENXT:
184 f=romfopen("roms/genxt/pcxt.rom","rb");
185 if (!f) break;
186 fread(rom+0xE000,8192,1,f);
187 fclose(f);
188 mem_load_xtide_bios();
189 return 1;
190 case ROM_DTKXT:
191 f=romfopen("roms/dtk/DTK_ERSO_2.42_2764.bin","rb");
192 if (!f) break;
193 fread(rom+0xE000,8192,1,f);
194 fclose(f);
195 mem_load_xtide_bios();
196 return 1;
197 case ROM_OLIM24:
198 f = romfopen("roms/olivetti_m24/olivetti_m24_version_1.43_low.bin" ,"rb");
199 ff = romfopen("roms/olivetti_m24/olivetti_m24_version_1.43_high.bin","rb");
200 if (!f || !ff) break;
201 for (c = 0x0000; c < 0x4000; c += 2)
202 {
203 rom[c + 0xc000] = getc(f);
204 rom[c + 0xc001] = getc(ff);
205 }
206 fclose(ff);
207 fclose(f);
208 mem_load_xtide_bios();
209 return 1;
211 case ROM_PC2086:
212 f = romfopen("roms/pc2086/40179.ic129" ,"rb");
213 ff = romfopen("roms/pc2086/40180.ic132","rb");
214 if (!f || !ff) break;
215 pclog("Loading BIOS\n");
216 for (c = 0x0000; c < 0x4000; c += 2)
217 {
218 rom[c + 0x0000] = getc(f);
219 rom[c + 0x0001] = getc(ff);
220 }
221 pclog("%02X %02X %02X\n", rom[0xfff0], rom[0xfff1], rom[0xfff2]);
222 fclose(ff);
223 fclose(f);
224 f = romfopen("roms/pc2086/40186.ic171", "rb");
225 if (!f) break;
226 fclose(f);
227 mem_load_xtide_bios();
228 biosmask = 0x3fff;
229 return 1;
231 case ROM_PC3086:
232 f = romfopen("roms/pc3086/fc00.bin" ,"rb");
233 if (!f) break;
234 fread(rom, 0x4000, 1, f);
235 fclose(f);
236 f = romfopen("roms/pc3086/c000.bin", "rb");
237 if (!f) break;
238 fclose(f);
239 mem_load_xtide_bios();
240 biosmask = 0x3fff;
241 return 1;
243 case ROM_IBMAT:
244 /* f=romfopen("roms/AMIC206.BIN","rb");
245 if (!f) break;
246 fread(rom,65536,1,f);
247 fclose(f);
248 return 1;*/
249 case ROM_IBMAT386:
250 f = romfopen("roms/ibmat/62x0820.u27", "rb");
251 ff =romfopen("roms/ibmat/62x0821.u47", "rb");
252 if (!f || !ff) break;
253 for (c=0x0000;c<0x10000;c+=2)
254 {
255 rom[c]=getc(f);
256 rom[c+1]=getc(ff);
257 }
258 fclose(ff);
259 fclose(f);
260 mem_load_atide_bios();
261 return 1;
262 case ROM_CMDPC30:
263 f = romfopen("roms/cmdpc30/commodore pc 30 iii even.bin", "rb");
264 ff = romfopen("roms/cmdpc30/commodore pc 30 iii odd.bin", "rb");
265 if (!f || !ff) break;
266 for (c = 0x0000; c < 0x8000; c += 2)
267 {
268 rom[c] = getc(f);
269 rom[c + 1] = getc(ff);
270 }
271 fclose(ff);
272 fclose(f);
273 biosmask = 0x7fff;
274 mem_load_atide_bios();
275 return 1;
276 case ROM_DELL200:
277 f=romfopen("roms/dells200/dell0.bin","rb");
278 ff=romfopen("roms/dells200/dell1.bin","rb");
279 if (!f || !ff) break;
280 for (c=0x0000;c<0x10000;c+=2)
281 {
282 rom[c]=getc(f);
283 rom[c+1]=getc(ff);
284 }
285 fclose(ff);
286 fclose(f);
287 return 1;
288 /* case ROM_IBMAT386:
289 f=romfopen("roms/at386/at386.bin","rb");
290 if (!f) break;
291 fread(rom,65536,1,f);
292 fclose(f);
293 return 1;*/
294 case ROM_AMI386: /*This uses the OPTi 82C495 chipset*/
295 // f=romfopen("roms/at386/at386.bin","rb");
296 f=romfopen("roms/ami386/ami386.bin","rb");
297 if (!f) break;
298 fread(rom,65536,1,f);
299 fclose(f);
300 return 1;
303 case ROM_ACER386:
304 f=romfopen("roms/acer386/acer386.bin","rb");
305 if (!f) break;
306 fread(rom,65536,1,f);
307 fclose(f);
308 rom[0xB0]=0xB0-0x51;
309 rom[0x40d4]=0x51; /*PUSH CX*/
310 f=romfopen("roms/acer386/oti067.bin","rb");
311 if (!f) break;
312 fclose(f);
313 return 1;
315 case ROM_AMI286:
316 f=romfopen("roms/ami286/amic206.bin","rb");
317 if (!f) break;
318 fread(rom,65536,1,f);
319 fclose(f);
320 // memset(romext,0x63,0x8000);
321 return 1;
323 case ROM_EUROPC:
324 // return 0;
325 f=romfopen("roms/europc/50145","rb");
326 if (!f) break;
327 fread(rom+0x8000,32768,1,f);
328 fclose(f);
329 // memset(romext,0x63,0x8000);
330 return 1;
332 case ROM_IBMPC:
333 f=romfopen("roms/ibmpc/pc102782.bin","rb");
334 if (!f) break;
335 // f=fopen("pc081682.bin","rb");
336 fread(rom+0xE000,8192,1,f);
337 fclose(f);
338 f=romfopen("roms/ibmpc/basicc11.f6","rb");
339 if (!f) return 1; /*I don't really care if BASIC is there or not*/
340 fread(rom+0x6000,8192,1,f);
341 fclose(f);
342 f=romfopen("roms/ibmpc/basicc11.f8","rb");
343 if (!f) break; /*But if some of it is there, then all of it must be*/
344 fread(rom+0x8000,8192,1,f);
345 fclose(f);
346 f=romfopen("roms/ibmpc/basicc11.fa","rb");
347 if (!f) break;
348 fread(rom+0xA000,8192,1,f);
349 fclose(f);
350 f=romfopen("roms/ibmpc/basicc11.fc","rb");
351 if (!f) break;
352 fread(rom+0xC000,8192,1,f);
353 fclose(f);
354 mem_load_xtide_bios();
355 return 1;
357 case ROM_MEGAPC:
358 f = romfopen("roms/megapc/41651-bios lo.u18", "rb");
359 ff = romfopen("roms/megapc/211253-bios hi.u19", "rb");
360 if (!f || !ff) break;
361 fseek(f, 0x8000, SEEK_SET);
362 fseek(ff, 0x8000, SEEK_SET);
363 for (c = 0x0000; c < 0x10000; c+=2)
364 {
365 rom[c]=getc(f);
366 rom[c+1]=getc(ff);
367 }
368 fclose(ff);
369 fclose(f);
370 return 1;
372 case ROM_AMI486:
373 f=romfopen("roms/ami486/ami486.BIN","rb");
374 if (!f) break;
375 fread(rom,65536,1,f);
376 fclose(f);
377 //is486=1;
378 return 1;
380 case ROM_WIN486:
381 // f=romfopen("roms/win486/win486.bin","rb");
382 f=romfopen("roms/win486/ALI1429G.AMW","rb");
383 if (!f) break;
384 fread(rom,65536,1,f);
385 fclose(f);
386 //is486=1;
387 return 1;
389 case ROM_PCI486:
390 f=romfopen("roms/hot-433/hot-433.ami","rb");
391 if (!f) break;
392 fread(rom, 0x20000, 1, f);
393 fclose(f);
394 biosmask = 0x1ffff;
395 //is486=1;
396 return 1;
398 case ROM_SIS496:
399 f = romfopen("roms/sis496/SIS496-1.AWA", "rb");
400 if (!f) break;
401 fread(rom, 0x20000, 1, f);
402 fclose(f);
403 biosmask = 0x1ffff;
404 pclog("Load SIS496 %x %x\n", rom[0x1fff0], rom[0xfff0]);
405 return 1;
407 case ROM_430VX:
408 // f = romfopen("roms/430vx/Ga586atv.bin", "rb");
409 // f = fopen("roms/430vx/vx29.BIN", "rb");
410 f = romfopen("roms/430vx/55XWUQ0E.BIN", "rb");
411 // f=romfopen("roms/430vx/430vx","rb");
412 if (!f) break;
413 fread(rom, 0x20000, 1, f);
414 fclose(f);
415 biosmask = 0x1ffff;
416 //is486=1;
417 return 1;
418 }
419 printf("Failed to load ROM!\n");
420 if (f) fclose(f);
421 if (ff) fclose(ff);
422 return 0;
423 }
427 int abrt=0;
429 void resetreadlookup()
430 {
431 int c;
432 // /*if (output) */pclog("resetreadlookup\n");
433 memset(readlookup2,0xFF,1024*1024*4);
434 for (c=0;c<256;c++) readlookup[c]=0xFFFFFFFF;
435 readlnext=0;
436 memset(writelookup2,0xFF,1024*1024*4);
437 for (c=0;c<256;c++) writelookup[c]=0xFFFFFFFF;
438 writelnext=0;
439 pccache=0xFFFFFFFF;
440 // readlnum=writelnum=0;
442 }
444 int mmuflush=0;
445 int mmu_perm=4;
447 void flushmmucache()
448 {
449 int c;
450 // /*if (output) */pclog("flushmmucache\n");
451 /* for (c=0;c<16;c++)
452 {
453 if ( readlookup2[0xE0+c]!=0xFFFFFFFF) pclog("RL2 %02X = %08X\n",0xE0+c, readlookup2[0xE0+c]);
454 if (writelookup2[0xE0+c]!=0xFFFFFFFF) pclog("WL2 %02X = %08X\n",0xE0+c,writelookup2[0xE0+c]);
455 }*/
456 for (c=0;c<256;c++)
457 {
458 if (readlookup[c]!=0xFFFFFFFF)
459 {
460 readlookup2[readlookup[c]]=0xFFFFFFFF;
461 readlookup[c]=0xFFFFFFFF;
462 }
463 if (writelookup[c]!=0xFFFFFFFF)
464 {
465 writelookup2[writelookup[c]]=0xFFFFFFFF;
466 writelookup[c]=0xFFFFFFFF;
467 }
468 }
469 mmuflush++;
470 // readlnum=writelnum=0;
471 pccache=(uint32_t)0xFFFFFFFF;
472 pccache2=(uint8_t *)0xFFFFFFFF;
474 // memset(readlookup,0xFF,sizeof(readlookup));
475 // memset(readlookup2,0xFF,1024*1024*4);
476 // memset(writelookup,0xFF,sizeof(writelookup));
477 // memset(writelookup2,0xFF,1024*1024*4);
478 /* if (!(cr0>>31)) return;*/
480 /* for (c = 0; c < 1024*1024; c++)
481 {
482 if (readlookup2[c] != 0xFFFFFFFF)
483 {
484 pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
485 dumpregs();
486 exit(-1);
487 }
488 if (writelookup2[c] != 0xFFFFFFFF)
489 {
490 pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
491 dumpregs();
492 exit(-1);
493 }
494 }*/
495 }
497 void flushmmucache_nopc()
498 {
499 int c;
500 for (c=0;c<256;c++)
501 {
502 if (readlookup[c]!=0xFFFFFFFF)
503 {
504 readlookup2[readlookup[c]]=0xFFFFFFFF;
505 readlookup[c]=0xFFFFFFFF;
506 }
507 if (writelookup[c]!=0xFFFFFFFF)
508 {
509 writelookup2[writelookup[c]]=0xFFFFFFFF;
510 writelookup[c]=0xFFFFFFFF;
511 }
512 }
513 }
515 void flushmmucache_cr3()
516 {
517 int c;
518 // /*if (output) */pclog("flushmmucache_cr3\n");
519 for (c=0;c<256;c++)
520 {
521 if (readlookup[c]!=0xFFFFFFFF)// && !readlookupp[c])
522 {
523 readlookup2[readlookup[c]]=0xFFFFFFFF;
524 readlookup[c]=0xFFFFFFFF;
525 }
526 if (writelookup[c]!=0xFFFFFFFF)// && !writelookupp[c])
527 {
528 writelookup2[writelookup[c]]=0xFFFFFFFF;
529 writelookup[c]=0xFFFFFFFF;
530 }
531 }
532 /* for (c = 0; c < 1024*1024; c++)
533 {
534 if (readlookup2[c] != 0xFFFFFFFF)
535 {
536 pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
537 dumpregs();
538 exit(-1);
539 }
540 if (writelookup2[c] != 0xFFFFFFFF)
541 {
542 pclog("Readlookup inconsistency - %05X %08X\n", c, readlookup2[c]);
543 dumpregs();
544 exit(-1);
545 }
546 }*/
547 }
549 extern int output;
551 #define mmutranslate_read(addr) mmutranslatereal(addr,0)
552 #define mmutranslate_write(addr) mmutranslatereal(addr,1)
554 int pctrans=0;
556 extern uint32_t testr[9];
558 uint32_t mmutranslatereal(uint32_t addr, int rw)
559 {
560 uint32_t addr2;
561 uint32_t temp,temp2,temp3;
563 if (abrt)
564 {
565 // pclog("Translate recursive abort\n");
566 return -1;
567 }
568 /* if ((addr&~0xFFFFF)==0x77f00000) pclog("Do translate %08X %i %08X %08X\n",addr,rw,EAX,pc);
569 if (addr==0x77f61000) output = 3;
570 if (addr==0x77f62000) { dumpregs(); exit(-1); }
571 if (addr==0x77f9a000) { dumpregs(); exit(-1); }*/
572 addr2=(cr3+((addr>>20)&0xFFC));
573 temp=temp2=((uint32_t *)ram)[addr2>>2];
574 // if (output == 3) pclog("Do translate %08X %i %08X\n", addr, rw, temp);
575 if (!(temp&1))// || (CPL==3 && !(temp&4) && !cpl_override) || (rw && !(temp&2) && (CPL==3 || cr0&WP_FLAG)))
576 {
577 // if (!nopageerrors) pclog("Section not present! %08X %08X %02X %04X:%08X %i %i\n",addr,temp,opcode,CS,pc,CPL,rw);
579 cr2=addr;
580 temp&=1;
581 if (CPL==3) temp|=4;
582 if (rw) temp|=2;
583 abrt = ABRT_PF;
584 abrt_error = temp;
585 /* if (addr == 0x70046D)
586 {
587 dumpregs();
588 exit(-1);
589 }*/
590 return -1;
591 }
592 temp=((uint32_t *)ram)[((temp&~0xFFF)+((addr>>10)&0xFFC))>>2];
593 temp3=temp&temp2;
594 // if (output == 3) pclog("Do translate %08X %08X\n", temp, temp3);
595 if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && (CPL==3 || cr0&WP_FLAG)))
596 {
597 // if (!nopageerrors) pclog("Page not present! %08X %08X %02X %02X %i %08X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,frame,rmdat32, CS,pc,SS,ESP,ins,CPL,rw);
599 // dumpregs();
600 // exit(-1);
601 // if (addr == 0x815F6E90) output = 3;
602 /* if (addr == 0x10ADE020) output = 3;*/
603 /* if (addr == 0x10150010 && !nopageerrors)
604 {
605 dumpregs();
606 exit(-1);
607 }*/
609 cr2=addr;
610 temp&=1;
611 if (CPL==3) temp|=4;
612 if (rw) temp|=2;
613 abrt = ABRT_PF;
614 abrt_error = temp;
615 // pclog("%04X\n",abrt);
616 return -1;
617 }
618 mmu_perm=temp&4;
619 ((uint32_t *)ram)[addr2>>2]|=0x20;
620 ((uint32_t *)ram)[((temp2&~0xFFF)+((addr>>10)&0xFFC))>>2]|=(rw?0x60:0x20);
621 // /*if (output) */pclog("Translate %08X %08X %08X %08X:%08X %08X\n",addr,(temp&~0xFFF)+(addr&0xFFF),temp,cs,pc,EDI);
623 return (temp&~0xFFF)+(addr&0xFFF);
624 }
626 void mmu_invalidate(uint32_t addr)
627 {
628 // readlookup2[addr >> 12] = writelookup2[addr >> 12] = 0xFFFFFFFF;
629 flushmmucache_cr3();
630 }
632 int memspeed[11]={256,320,384,512,640,768,1024,1152,1280,1536,1920};
633 int memwaitstate;
635 static int cachelookup[256];
636 static uint8_t *cachelookup2;
637 static int cachelnext;
639 void addreadlookup(uint32_t virt, uint32_t phys)
640 {
641 // return;
642 // printf("Addreadlookup %08X %08X %08X %08X %08X %08X %02X %08X\n",virt,phys,cs,ds,es,ss,opcode,pc);
643 if (virt == 0xffffffff)
644 return;
646 if (readlookup2[virt>>12]!=0xFFFFFFFF)
647 {
648 /* if (readlookup2[virt>>12] != phys&~0xfff)
649 {
650 pclog("addreadlookup mismatch - %05X000 %05X000\n", readlookup[readlnext], virt >> 12);
651 dumpregs();
652 exit(-1);
653 }*/
654 return;
655 }
658 if (!cachelookup2[phys >> 12])
659 {
660 readlnum++;
661 cycles-=memwaitstate;
662 if (cachelookup[cachelnext] != 0xffffffff)
663 cachelookup2[cachelookup[cachelnext]] = 0;
664 cachelookup[cachelnext] = phys >> 12;
665 cachelookup2[phys >> 12] = 1;
666 cachelnext = (cachelnext + 1) & (cachesize - 1);
667 }
669 if (readlookup[readlnext]!=0xFFFFFFFF)
670 {
671 readlookup2[readlookup[readlnext]]=0xFFFFFFFF;
672 // readlnum--;
673 }
674 readlookup2[virt>>12] = (uint32_t)&ram[(phys & ~0xFFF) - (virt & ~0xfff)];
675 readlookupp[readlnext]=mmu_perm;
676 readlookup[readlnext++]=virt>>12;
677 readlnext&=(cachesize-1);
678 }
680 void addwritelookup(uint32_t virt, uint32_t phys)
681 {
682 // return;
683 // printf("Addwritelookup %08X %08X\n",virt,phys);
684 if (virt == 0xffffffff)
685 return;
687 if (writelookup2[virt>>12]!=0xFFFFFFFF)
688 {
689 /* if (writelookup2[virt>>12] != phys&~0xfff)
690 {
691 pclog("addwritelookup mismatch - %05X000 %05X000\n", readlookup[readlnext], virt >> 12);
692 dumpregs();
693 exit(-1);
694 }*/
695 return;
696 }
698 if (!cachelookup2[phys >> 12])
699 {
700 writelnum++;
701 cycles-=memwaitstate;
702 if (cachelookup[cachelnext] != 0xffffffff)
703 cachelookup2[cachelookup[cachelnext]] = 0;
704 cachelookup[cachelnext] = phys >> 12;
705 cachelookup2[phys >> 12] = 1;
706 cachelnext = (cachelnext + 1) & (cachesize - 1);
707 }
709 cycles-=memwaitstate;
710 if (writelookup[writelnext]!=0xFFFFFFFF)
711 {
712 writelookup2[writelookup[writelnext]]=0xFFFFFFFF;
713 // writelnum--;
714 }
715 writelookup2[virt>>12] = (uint32_t)&ram[(phys & ~0xFFF) - (virt & ~0xfff)];
716 writelookupp[writelnext]=mmu_perm;
717 writelookup[writelnext++]=virt>>12;
718 writelnext&=(cachesize-1);
719 }
721 #undef printf
722 uint8_t *getpccache(uint32_t a)
723 {
724 // int logit=(a>0xFFFFF);
725 uint32_t a2=a;
726 //if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[(uint8_t *)readlookup2[a>>12] - (uint8_t *)(a&~0xFFF)];
727 if (cr0>>31)
728 {
729 // if (output==3) pclog("Translate GetPCCache %08X\n",a);
730 pctrans=1;
731 a = mmutranslate_read(a);
732 pctrans=0;
733 // if (output==3) pclog("GetPCCache output %08X\n",a);
734 if (a==0xFFFFFFFF) return ram;
735 /* {
736 printf("Bad getpccache %08X\n",a);
737 dumpregs();
738 exit(-1);
739 }*/
740 }
741 a&=rammask;
742 //if (output==3) pclog("Getpccache %08X %i\n",a,shadowbios);
743 if (isram[a>>16])
744 {
745 //if (readlookup2[a>>12]!=0xFFFFFFFF) return &ram[readlookup2[a>>12]];
746 if ((a>>16)!=0xF || shadowbios)
747 addreadlookup(a2,a);
748 // if (a > 0xc0000000)
749 // printf("%016X %016X %016X\n", ((long)a&0xFFFFF000), ((long)a2&~0xFFF), (uint8_t *)(a&0xFFFFF000) - (uint8_t *)(a2&~0xFFF));
750 // pclog("getpccache: virt=%08x phys=%08x RAM\n", a2, a);
751 return &ram[(uint8_t *)(a&0xFFFFF000) - (uint8_t *)(a2&~0xFFF)];
752 }
753 // if (logit) printf("PCCACHE - %08X -> %08X\n",a2,a);
754 if (_mem_exec[a >> 14])
755 {
756 // pclog("getpccache: %p %p %p\n", ram, rom, &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)]);
757 // pclog("getpccache: virt=%08x phys=%08x %08x %08x %08x %08x\n", a2, a, _mem_exec[a >> 14], &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)], &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)] + 0xf0000, rom);
758 return &_mem_exec[a >> 14][(a & 0x3000) - (a2 & ~0xFFF)];
759 }
760 /* switch (a>>16)
761 {
762 case 0xC: if (a&0x8000) return &romext[(uint8_t *)(a&0x7000) - (uint8_t *)(a2&~0xFFF)];
763 return &vrom[(uint8_t *)(a&0x7000) - (uint8_t *)(a2&~0xFFF)];
764 case 0xE: if (shadowbios) return &ram[(uint8_t *)(a&0xFFF000) - (uint8_t *)(a2&~0xFFF)];
765 return &rom[(uint8_t *)((a & biosmask) & ~ 0xfff) - (uint8_t *)(a2 & ~0xFFF)];
766 case 0xF: if (shadowbios) return &ram[(uint8_t *)(a&0xFFF000) - (uint8_t *)(a2&~0xFFF)];
767 return &rom[(uint8_t *)((a & biosmask) & ~ 0xfff) - (uint8_t *)(a2 & ~0xFFF)];
768 }
769 return &rom[(long)(a&0xF000) - (long)(a2&~0xFFF)];*/
770 fatal("Bad getpccache %08X\n", a);
771 /*printf("Bad getpccache %08X\n",a);
772 dumpregs();
773 exit(-1);*/
774 }
775 #define printf pclog
777 static uint32_t mem_logical_addr;
778 uint8_t readmembl(uint32_t addr)
779 {
780 mem_logical_addr = addr;
781 if (cr0 >> 31)
782 {
783 addr = mmutranslate_read(addr);
784 if (addr == 0xFFFFFFFF) return 0xFF;
785 }
786 addr &= rammask;
788 if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
789 // pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc);
790 return 0xFF;
791 }
793 void writemembl(uint32_t addr, uint8_t val)
794 {
795 mem_logical_addr = addr;
797 if (cr0 >> 31)
798 {
799 addr = mmutranslate_write(addr);
800 if (addr == 0xFFFFFFFF) return;
801 }
802 addr &= rammask;
804 if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
805 // else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc);
806 }
808 uint8_t readmemb386l(uint32_t seg, uint32_t addr)
809 {
810 if (seg==-1)
811 {
812 x86gpf("NULL segment", 0);
813 printf("NULL segment! rb %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
814 return -1;
815 }
816 mem_logical_addr = addr = addr + seg;
817 /* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF)
818 {
819 return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)];
820 }*/
822 if (cr0 >> 31)
823 {
824 addr = mmutranslate_read(addr);
825 if (addr == 0xFFFFFFFF) return 0xFF;
826 }
828 addr &= rammask;
830 if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
831 // pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc);
832 return 0xFF;
833 }
835 void writememb386l(uint32_t seg, uint32_t addr, uint8_t val)
836 {
837 if (seg==-1)
838 {
839 x86gpf("NULL segment", 0);
840 printf("NULL segment! wb %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
841 return;
842 }
844 mem_logical_addr = addr = addr + seg;
845 if (cr0 >> 31)
846 {
847 addr = mmutranslate_write(addr);
848 if (addr == 0xFFFFFFFF) return;
849 }
851 addr &= rammask;
853 /* if (addr >= 0xa0000 && addr < 0xc0000)
854 pclog("writemembl %08X %02X\n", addr, val);*/
856 if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
857 // else pclog("Bad writememb386l %08X %02X %04X:%08X\n", addr, val, CS, pc);
858 }
860 uint16_t readmemwl(uint32_t seg, uint32_t addr)
861 {
862 uint32_t addr2 = mem_logical_addr = seg + addr;
863 if ((addr2&0xFFF)>0xFFE)
864 {
865 if (cr0>>31)
866 {
867 if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff;
868 if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff;
869 }
870 if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8);
871 else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8);
872 }
873 if (seg==-1)
874 {
875 x86gpf("NULL segment", 0);
876 printf("NULL segment! rw %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
877 return -1;
878 }
879 if (cr0>>31)
880 {
881 addr2 = mmutranslate_read(addr2);
882 if (addr2==0xFFFFFFFF) return 0xFFFF;
883 }
885 addr2 &= rammask;
887 if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
889 if (_mem_read_b[addr2 >> 14])
890 {
891 if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8);
892 else return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8);
893 }
894 // pclog("Bad readmemwl %08X\n", addr2);
895 return 0xffff;
896 }
898 void writememwl(uint32_t seg, uint32_t addr, uint16_t val)
899 {
900 uint32_t addr2 = mem_logical_addr = seg + addr;
901 if ((addr2&0xFFF)>0xFFE)
902 {
903 if (cr0>>31)
904 {
905 if (mmutranslate_write(addr2) == 0xffffffff) return;
906 if (mmutranslate_write(addr2+1) == 0xffffffff) return;
907 }
908 if (is386)
909 {
910 writememb386l(seg,addr,val);
911 writememb386l(seg,addr+1,val>>8);
912 }
913 else
914 {
915 writemembl(seg+addr,val);
916 writemembl(seg+addr+1,val>>8);
917 }
918 return;
919 }
921 if (seg==-1)
922 {
923 x86gpf("NULL segment", 0);
924 printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
925 return;
926 }
927 if (cr0>>31)
928 {
929 addr2 = mmutranslate_write(addr2);
930 if (addr2==0xFFFFFFFF) return;
931 }
933 addr2 &= rammask;
935 /* if (addr2 >= 0xa0000 && addr2 < 0xc0000)
936 pclog("writememwl %08X %02X\n", addr2, val);*/
938 if (_mem_write_w[addr2 >> 14])
939 {
940 _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
941 return;
942 }
944 if (_mem_write_b[addr2 >> 14])
945 {
946 _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
947 _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
948 return;
949 }
950 // pclog("Bad writememwl %08X %04X\n", addr2, val);
951 }
953 uint32_t readmemll(uint32_t seg, uint32_t addr)
954 {
955 uint32_t addr2 = mem_logical_addr = seg + addr;
956 if ((addr2&0xFFF)>0xFFC)
957 {
958 if (cr0>>31)
959 {
960 if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff;
961 if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff;
962 }
963 return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
964 }
966 if (seg==-1)
967 {
968 x86gpf("NULL segment", 0);
969 printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
970 return -1;
971 }
973 if (cr0>>31)
974 {
975 addr2 = mmutranslate_read(addr2);
976 if (addr2==0xFFFFFFFF) return 0xFFFFFFFF;
977 }
979 addr2&=rammask;
981 if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
983 if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16);
985 if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24);
987 // pclog("Bad readmemll %08X\n", addr2);
988 return 0xffffffff;
989 }
991 void writememll(uint32_t seg, uint32_t addr, uint32_t val)
992 {
993 uint32_t addr2 = mem_logical_addr = seg + addr;
995 if ((addr2&0xFFF)>0xFFC)
996 {
997 if (cr0>>31)
998 {
999 if (mmutranslate_write(addr2) == 0xffffffff) return;
1000 if (mmutranslate_write(addr2+3) == 0xffffffff) return;
1002 writememwl(seg,addr,val);
1003 writememwl(seg,addr+2,val>>16);
1004 return;
1006 if (seg==-1)
1008 x86gpf("NULL segment", 0);
1009 printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
1010 return;
1012 if (cr0>>31)
1014 addr2 = mmutranslate_write(addr2);
1015 if (addr2==0xFFFFFFFF) return;
1018 addr2&=rammask;
1020 /* if (addr >= 0xa0000 && addr < 0xc0000)
1021 pclog("writememll %08X %08X\n", addr, val);*/
1023 if (_mem_write_l[addr2 >> 14])
1025 _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
1026 return;
1028 if (_mem_write_w[addr2 >> 14])
1030 _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
1031 _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
1032 return;
1034 if (_mem_write_b[addr2 >> 14])
1036 _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
1037 _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
1038 _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
1039 _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]);
1040 return;
1042 // pclog("Bad writememll %08X %08X\n", addr2, val);
1045 uint8_t mem_readb_phys(uint32_t addr)
1047 mem_logical_addr = 0xffffffff;
1049 if (_mem_read_b[addr >> 14])
1050 return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
1052 return 0xff;
1055 void mem_writeb_phys(uint32_t addr, uint8_t val)
1057 mem_logical_addr = 0xffffffff;
1059 if (_mem_write_b[addr >> 14])
1060 _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
1063 uint8_t mem_read_ram(uint32_t addr, void *priv)
1065 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMb %08X\n", addr);
1066 addreadlookup(mem_logical_addr, addr);
1067 return ram[addr];
1069 uint16_t mem_read_ramw(uint32_t addr, void *priv)
1071 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMw %08X\n", addr);
1072 addreadlookup(mem_logical_addr, addr);
1073 return *(uint16_t *)&ram[addr];
1075 uint32_t mem_read_raml(uint32_t addr, void *priv)
1077 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMl %08X\n", addr);
1078 addreadlookup(mem_logical_addr, addr);
1079 return *(uint32_t *)&ram[addr];
1082 void mem_write_ram(uint32_t addr, uint8_t val, void *priv)
1084 addwritelookup(mem_logical_addr, addr);
1085 ram[addr] = val;
1086 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMb %08X\n", addr);
1088 void mem_write_ramw(uint32_t addr, uint16_t val, void *priv)
1090 addwritelookup(mem_logical_addr, addr);
1091 *(uint16_t *)&ram[addr] = val;
1092 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMw %08X %04X:%04X %i %04X %04X:%04X %04X:%04X\n", addr, CS, pc, ins, val, DS,SI, ES,DI);
1094 void mem_write_raml(uint32_t addr, uint32_t val, void *priv)
1096 addwritelookup(mem_logical_addr, addr);
1097 *(uint32_t *)&ram[addr] = val;
1098 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMl %08X %04X:%04X %04X:%04X %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI);
1101 uint8_t mem_read_bios(uint32_t addr, void *priv)
1103 if (AMIBIOS && (addr&0xFFFFF)==0xF8281) /*This is read constantly during AMIBIOS POST, but is never written to. It's clearly a status register of some kind, but for what?*/
1105 // pclog("Read magic addr %04X(%06X):%04X\n",CS,cs,pc);
1106 // if (pc==0x547D) output=3;
1107 return 0x40;
1109 // pclog("Read BIOS %08X %02X %04X:%04X\n", addr, rom[addr & biosmask], CS, pc);
1110 return rom[addr & biosmask];
1112 uint16_t mem_read_biosw(uint32_t addr, void *priv)
1114 // pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc);
1115 return *(uint16_t *)&rom[addr & biosmask];
1117 uint32_t mem_read_biosl(uint32_t addr, void *priv)
1119 // pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc);
1120 return *(uint32_t *)&rom[addr & biosmask];
1123 uint8_t mem_read_romext(uint32_t addr, void *priv)
1125 return romext[addr & 0x7fff];
1127 uint16_t mem_read_romextw(uint32_t addr, void *priv)
1129 return *(uint16_t *)&romext[addr & 0x7fff];
1131 uint32_t mem_read_romextl(uint32_t addr, void *priv)
1133 return *(uint32_t *)&romext[addr & 0x7fff];
1136 void mem_write_null(uint32_t addr, uint8_t val, void *p)
1139 void mem_write_nullw(uint32_t addr, uint16_t val, void *p)
1142 void mem_write_nulll(uint32_t addr, uint32_t val, void *p)
1146 void mem_updatecache()
1148 flushmmucache();
1149 if (!is386)
1151 cachesize=256;
1152 memwaitstate=0;
1153 return;
1155 if (cpu_16bitbus)
1156 memwaitstate = 512 * cpu_multi;
1157 else
1158 memwaitstate = 384 * cpu_multi; //memspeed[cpuspeed];
1159 switch (cache)
1161 case 0: cachesize=32; break;
1162 case 1: cachesize=64; break;
1163 case 2: cachesize=128; break;
1164 case 3: cachesize=256; break;
1165 case 4: cachesize=256; memwaitstate=0; break;
1169 static inline int mem_mapping_read_allowed(uint32_t flags, int state)
1171 // pclog("mem_mapping_read_allowed: flags=%x state=%x\n", flags, state);
1172 switch (state & MEM_READ_MASK)
1174 case MEM_READ_ANY:
1175 return 1;
1176 case MEM_READ_EXTERNAL:
1177 return !(flags & MEM_MAPPING_INTERNAL);
1178 case MEM_READ_INTERNAL:
1179 return !(flags & MEM_MAPPING_EXTERNAL);
1180 default:
1181 fatal("mem_mapping_read_allowed : bad state %x\n", state);
1185 static inline int mem_mapping_write_allowed(uint32_t flags, int state)
1187 switch (state & MEM_WRITE_MASK)
1189 case MEM_WRITE_DISABLED:
1190 return 0;
1191 case MEM_WRITE_ANY:
1192 return 1;
1193 case MEM_WRITE_EXTERNAL:
1194 return !(flags & MEM_MAPPING_INTERNAL);
1195 case MEM_WRITE_INTERNAL:
1196 return !(flags & MEM_MAPPING_EXTERNAL);
1197 default:
1198 fatal("mem_mapping_write_allowed : bad state %x\n", state);
1202 static void mem_mapping_recalc(uint64_t base, uint64_t size)
1204 uint64_t c;
1205 mem_mapping_t *mapping = base_mapping.next;
1207 if (!size)
1208 return;
1209 /*Clear out old mappings*/
1210 for (c = base; c < base + size; c += 0x4000)
1212 _mem_read_b[c >> 14] = NULL;
1213 _mem_read_w[c >> 14] = NULL;
1214 _mem_read_l[c >> 14] = NULL;
1215 _mem_priv_r[c >> 14] = NULL;
1216 _mem_mapping_r[c >> 14] = NULL;
1217 _mem_write_b[c >> 14] = NULL;
1218 _mem_write_w[c >> 14] = NULL;
1219 _mem_write_l[c >> 14] = NULL;
1220 _mem_priv_w[c >> 14] = NULL;
1221 _mem_mapping_w[c >> 14] = NULL;
1224 /*Walk mapping list*/
1225 while (mapping != NULL)
1227 /*In range?*/
1228 if (mapping->enable && (uint64_t)mapping->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)mapping->base + (uint64_t)mapping->size) > (uint64_t)base)
1230 uint64_t start = (mapping->base < base) ? mapping->base : base;
1231 uint64_t end = (((uint64_t)mapping->base + (uint64_t)mapping->size) < (base + size)) ? ((uint64_t)mapping->base + (uint64_t)mapping->size) : (base + size);
1232 if (start < mapping->base)
1233 start = mapping->base;
1235 for (c = start; c < end; c += 0x4000)
1237 if ((mapping->read_b || mapping->read_w || mapping->read_l) &&
1238 mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14]))
1240 _mem_read_b[c >> 14] = mapping->read_b;
1241 _mem_read_w[c >> 14] = mapping->read_w;
1242 _mem_read_l[c >> 14] = mapping->read_l;
1243 _mem_exec[c >> 14] = mapping->exec + (c - mapping->base);
1244 _mem_priv_r[c >> 14] = mapping->p;
1245 _mem_mapping_r[c >> 14] = mapping;
1247 if ((mapping->write_b || mapping->write_w || mapping->write_l) &&
1248 mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14]))
1250 _mem_write_b[c >> 14] = mapping->write_b;
1251 _mem_write_w[c >> 14] = mapping->write_w;
1252 _mem_write_l[c >> 14] = mapping->write_l;
1253 _mem_priv_w[c >> 14] = mapping->p;
1254 _mem_mapping_w[c >> 14] = mapping;
1258 mapping = mapping->next;
1262 void mem_mapping_add(mem_mapping_t *mapping,
1263 uint32_t base,
1264 uint32_t size,
1265 uint8_t (*read_b)(uint32_t addr, void *p),
1266 uint16_t (*read_w)(uint32_t addr, void *p),
1267 uint32_t (*read_l)(uint32_t addr, void *p),
1268 void (*write_b)(uint32_t addr, uint8_t val, void *p),
1269 void (*write_w)(uint32_t addr, uint16_t val, void *p),
1270 void (*write_l)(uint32_t addr, uint32_t val, void *p),
1271 uint8_t *exec,
1272 uint32_t flags,
1273 void *p)
1275 mem_mapping_t *dest = &base_mapping;
1277 /*Add mapping to the end of the list*/
1278 while (dest->next)
1279 dest = dest->next;
1280 dest->next = mapping;
1282 if (size)
1283 mapping->enable = 1;
1284 else
1285 mapping->enable = 0;
1286 mapping->base = base;
1287 mapping->size = size;
1288 mapping->read_b = read_b;
1289 mapping->read_w = read_w;
1290 mapping->read_l = read_l;
1291 mapping->write_b = write_b;
1292 mapping->write_w = write_w;
1293 mapping->write_l = write_l;
1294 mapping->exec = exec;
1295 mapping->flags = flags;
1296 mapping->p = p;
1297 mapping->next = NULL;
1299 mem_mapping_recalc(mapping->base, mapping->size);
1302 void mem_mapping_set_handler(mem_mapping_t *mapping,
1303 uint8_t (*read_b)(uint32_t addr, void *p),
1304 uint16_t (*read_w)(uint32_t addr, void *p),
1305 uint32_t (*read_l)(uint32_t addr, void *p),
1306 void (*write_b)(uint32_t addr, uint8_t val, void *p),
1307 void (*write_w)(uint32_t addr, uint16_t val, void *p),
1308 void (*write_l)(uint32_t addr, uint32_t val, void *p))
1310 mapping->read_b = read_b;
1311 mapping->read_w = read_w;
1312 mapping->read_l = read_l;
1313 mapping->write_b = write_b;
1314 mapping->write_w = write_w;
1315 mapping->write_l = write_l;
1317 mem_mapping_recalc(mapping->base, mapping->size);
1320 void mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size)
1322 /*Remove old mapping*/
1323 mapping->enable = 0;
1324 mem_mapping_recalc(mapping->base, mapping->size);
1326 /*Set new mapping*/
1327 mapping->enable = 1;
1328 mapping->base = base;
1329 mapping->size = size;
1331 mem_mapping_recalc(mapping->base, mapping->size);
1334 void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec)
1336 mapping->exec = exec;
1338 mem_mapping_recalc(mapping->base, mapping->size);
1341 void mem_mapping_set_p(mem_mapping_t *mapping, void *p)
1343 mapping->p = p;
1346 void mem_mapping_disable(mem_mapping_t *mapping)
1348 mapping->enable = 0;
1350 mem_mapping_recalc(mapping->base, mapping->size);
1353 void mem_mapping_enable(mem_mapping_t *mapping)
1355 mapping->enable = 1;
1357 mem_mapping_recalc(mapping->base, mapping->size);
1360 void mem_set_mem_state(uint32_t base, uint32_t size, int state)
1362 uint32_t c;
1364 // pclog("mem_set_pci_enable: base=%08x size=%08x\n", base, size);
1365 for (c = 0; c < size; c += 0x4000)
1366 _mem_state[(c + base) >> 14] = state;
1368 mem_mapping_recalc(base, size);
1371 void mem_add_bios()
1373 mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_EXTERNAL, 0);
1374 mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1375 mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1376 mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1377 mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1378 mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1379 mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1380 mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_EXTERNAL, 0);
1382 mem_mapping_add(&bios_high_mapping[0], 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, 0, 0);
1383 mem_mapping_add(&bios_high_mapping[1], 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), 0, 0);
1384 mem_mapping_add(&bios_high_mapping[2], 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), 0, 0);
1385 mem_mapping_add(&bios_high_mapping[3], 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), 0, 0);
1386 mem_mapping_add(&bios_high_mapping[4], 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), 0, 0);
1387 mem_mapping_add(&bios_high_mapping[5], 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), 0, 0);
1388 mem_mapping_add(&bios_high_mapping[6], 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), 0, 0);
1389 mem_mapping_add(&bios_high_mapping[7], 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), 0, 0);
1392 void mem_init()
1394 int c;
1396 ram = malloc(mem_size * 1024 * 1024);
1397 rom = malloc(0x20000);
1398 vram = malloc(0x800000);
1399 readlookup2 = malloc(1024 * 1024 * 4);
1400 writelookup2 = malloc(1024 * 1024 * 4);
1401 cachelookup2 = malloc(1024 * 1024);
1402 biosmask = 0xffff;
1404 memset(ram, 0, mem_size * 1024 * 1024);
1406 memset(isram, 0, sizeof(isram));
1407 for (c = 0; c < (mem_size * 16); c++)
1409 isram[c] = 1;
1410 if (c >= 0xa && c <= 0xf)
1411 isram[c] = 0;
1414 memset(_mem_read_b, 0, sizeof(_mem_read_b));
1415 memset(_mem_read_w, 0, sizeof(_mem_read_w));
1416 memset(_mem_read_l, 0, sizeof(_mem_read_l));
1417 memset(_mem_write_b, 0, sizeof(_mem_write_b));
1418 memset(_mem_write_w, 0, sizeof(_mem_write_w));
1419 memset(_mem_write_l, 0, sizeof(_mem_write_l));
1421 memset(&base_mapping, 0, sizeof(base_mapping));
1423 memset(_mem_state, 0, sizeof(_mem_state));
1425 mem_set_mem_state(0x000000, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1426 mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
1427 mem_set_mem_state(0x100000, (mem_size - 1) * 1024 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1429 mem_mapping_add(&ram_low_mapping, 0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL);
1430 if (mem_size > 1)
1431 mem_mapping_add(&ram_high_mapping, 0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
1432 mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL);
1434 mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
1435 // pclog("Mem resize %i %i\n",mem_size,c);
1438 void mem_resize()
1440 int c;
1442 free(ram);
1443 ram = malloc(mem_size * 1024 * 1024);
1444 memset(ram, 0, mem_size * 1024 * 1024);
1446 memset(isram, 0, sizeof(isram));
1447 for (c = 0; c < (mem_size * 16); c++)
1449 isram[c] = 1;
1450 if (c >= 0xa && c <= 0xf)
1451 isram[c] = 0;
1454 memset(_mem_read_b, 0, sizeof(_mem_read_b));
1455 memset(_mem_read_w, 0, sizeof(_mem_read_w));
1456 memset(_mem_read_l, 0, sizeof(_mem_read_l));
1457 memset(_mem_write_b, 0, sizeof(_mem_write_b));
1458 memset(_mem_write_w, 0, sizeof(_mem_write_w));
1459 memset(_mem_write_l, 0, sizeof(_mem_write_l));
1461 memset(&base_mapping, 0, sizeof(base_mapping));
1463 memset(_mem_state, 0, sizeof(_mem_state));
1465 mem_set_mem_state(0x000000, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1466 mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
1467 mem_set_mem_state(0x100000, (mem_size - 1) * 1024 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1469 mem_mapping_add(&ram_low_mapping, 0x00000, 0xa0000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL);
1470 if (mem_size > 1)
1471 mem_mapping_add(&ram_high_mapping, 0x100000, (mem_size - 1) * 1024 * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
1472 mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL);
1474 mem_add_bios();
1476 mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
1478 // pclog("Mem resize %i %i\n",mem_size,c);
1481 int mem_a20_key = 0, mem_a20_alt = 0;
1482 static int mem_a20_state = 0;
1484 void mem_a20_recalc()
1486 int state = mem_a20_key | mem_a20_alt;
1487 // pclog("A20 recalc %i %i\n", state, mem_a20_state);
1488 if (state && !mem_a20_state)
1490 rammask = 0xffffffff;
1491 flushmmucache();
1493 else if (!state && mem_a20_state)
1495 rammask = 0xffefffff;
1496 flushmmucache();
1498 // pclog("rammask now %08X\n", rammask);
1499 mem_a20_state = state;