PCem

view src/mem.c @ 154:d0d530adce12

Initial port to Linux (using Allegro). 64-bit fixes. Some changes to aid portability. A few other tweaks.
author TomW
date Thu Sep 04 21:07:24 2014 +0100
parents 4081a8dbce5b
children
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*sizeof(uintptr_t));
434 for (c=0;c<256;c++) readlookup[c]=0xFFFFFFFF;
435 readlnext=0;
436 memset(writelookup2,0xFF,1024*1024*sizeof(uintptr_t));
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] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(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] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(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 uint32_t a2=a;
726 if (cr0>>31)
727 {
728 pctrans=1;
729 a = mmutranslate_read(a);
730 pctrans=0;
732 if (a==0xFFFFFFFF) return ram;
733 }
734 a&=rammask;
736 if (isram[a>>16])
737 {
738 if ((a >> 16) != 0xF || shadowbios)
739 addreadlookup(a2, a);
740 return &ram[(uintptr_t)(a & 0xFFFFF000) - (uintptr_t)(a2 & ~0xFFF)];
741 }
743 if (_mem_exec[a >> 14])
744 {
745 return &_mem_exec[a >> 14][(uintptr_t)(a & 0x3000) - (uintptr_t)(a2 & ~0xFFF)];
746 }
748 fatal("Bad getpccache %08X\n", a);
749 }
750 #define printf pclog
752 static uint32_t mem_logical_addr;
753 uint8_t readmembl(uint32_t addr)
754 {
755 mem_logical_addr = addr;
756 if (cr0 >> 31)
757 {
758 addr = mmutranslate_read(addr);
759 if (addr == 0xFFFFFFFF) return 0xFF;
760 }
761 addr &= rammask;
763 if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
764 // pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc);
765 return 0xFF;
766 }
768 void writemembl(uint32_t addr, uint8_t val)
769 {
770 mem_logical_addr = addr;
772 if (cr0 >> 31)
773 {
774 addr = mmutranslate_write(addr);
775 if (addr == 0xFFFFFFFF) return;
776 }
777 addr &= rammask;
779 if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
780 // else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc);
781 }
783 uint8_t readmemb386l(uint32_t seg, uint32_t addr)
784 {
785 if (seg==-1)
786 {
787 x86gpf("NULL segment", 0);
788 printf("NULL segment! rb %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
789 return -1;
790 }
791 mem_logical_addr = addr = addr + seg;
792 /* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF)
793 {
794 return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)];
795 }*/
797 if (cr0 >> 31)
798 {
799 addr = mmutranslate_read(addr);
800 if (addr == 0xFFFFFFFF) return 0xFF;
801 }
803 addr &= rammask;
805 if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
806 // pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc);
807 return 0xFF;
808 }
810 void writememb386l(uint32_t seg, uint32_t addr, uint8_t val)
811 {
812 if (seg==-1)
813 {
814 x86gpf("NULL segment", 0);
815 printf("NULL segment! wb %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
816 return;
817 }
819 mem_logical_addr = addr = addr + seg;
820 if (cr0 >> 31)
821 {
822 addr = mmutranslate_write(addr);
823 if (addr == 0xFFFFFFFF) return;
824 }
826 addr &= rammask;
828 /* if (addr >= 0xa0000 && addr < 0xc0000)
829 pclog("writemembl %08X %02X\n", addr, val);*/
831 if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
832 // else pclog("Bad writememb386l %08X %02X %04X:%08X\n", addr, val, CS, pc);
833 }
835 uint16_t readmemwl(uint32_t seg, uint32_t addr)
836 {
837 uint32_t addr2 = mem_logical_addr = seg + addr;
838 if ((addr2&0xFFF)>0xFFE)
839 {
840 if (cr0>>31)
841 {
842 if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff;
843 if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff;
844 }
845 if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8);
846 else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8);
847 }
848 if (seg==-1)
849 {
850 x86gpf("NULL segment", 0);
851 printf("NULL segment! rw %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
852 return -1;
853 }
854 if (cr0>>31)
855 {
856 addr2 = mmutranslate_read(addr2);
857 if (addr2==0xFFFFFFFF) return 0xFFFF;
858 }
860 addr2 &= rammask;
862 if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
864 if (_mem_read_b[addr2 >> 14])
865 {
866 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);
867 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);
868 }
869 // pclog("Bad readmemwl %08X\n", addr2);
870 return 0xffff;
871 }
873 void writememwl(uint32_t seg, uint32_t addr, uint16_t val)
874 {
875 uint32_t addr2 = mem_logical_addr = seg + addr;
876 if ((addr2&0xFFF)>0xFFE)
877 {
878 if (cr0>>31)
879 {
880 if (mmutranslate_write(addr2) == 0xffffffff) return;
881 if (mmutranslate_write(addr2+1) == 0xffffffff) return;
882 }
883 if (is386)
884 {
885 writememb386l(seg,addr,val);
886 writememb386l(seg,addr+1,val>>8);
887 }
888 else
889 {
890 writemembl(seg+addr,val);
891 writemembl(seg+addr+1,val>>8);
892 }
893 return;
894 }
896 if (seg==-1)
897 {
898 x86gpf("NULL segment", 0);
899 printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
900 return;
901 }
902 if (cr0>>31)
903 {
904 addr2 = mmutranslate_write(addr2);
905 if (addr2==0xFFFFFFFF) return;
906 }
908 addr2 &= rammask;
910 /* if (addr2 >= 0xa0000 && addr2 < 0xc0000)
911 pclog("writememwl %08X %02X\n", addr2, val);*/
913 if (_mem_write_w[addr2 >> 14])
914 {
915 _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
916 return;
917 }
919 if (_mem_write_b[addr2 >> 14])
920 {
921 _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
922 _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
923 return;
924 }
925 // pclog("Bad writememwl %08X %04X\n", addr2, val);
926 }
928 uint32_t readmemll(uint32_t seg, uint32_t addr)
929 {
930 uint32_t addr2 = mem_logical_addr = seg + addr;
931 if ((addr2&0xFFF)>0xFFC)
932 {
933 if (cr0>>31)
934 {
935 if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff;
936 if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff;
937 }
938 return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
939 }
941 if (seg==-1)
942 {
943 x86gpf("NULL segment", 0);
944 printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
945 return -1;
946 }
948 if (cr0>>31)
949 {
950 addr2 = mmutranslate_read(addr2);
951 if (addr2==0xFFFFFFFF) return 0xFFFFFFFF;
952 }
954 addr2&=rammask;
956 if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
958 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);
960 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);
962 // pclog("Bad readmemll %08X\n", addr2);
963 return 0xffffffff;
964 }
966 void writememll(uint32_t seg, uint32_t addr, uint32_t val)
967 {
968 uint32_t addr2 = mem_logical_addr = seg + addr;
970 if ((addr2&0xFFF)>0xFFC)
971 {
972 if (cr0>>31)
973 {
974 if (mmutranslate_write(addr2) == 0xffffffff) return;
975 if (mmutranslate_write(addr2+3) == 0xffffffff) return;
976 }
977 writememwl(seg,addr,val);
978 writememwl(seg,addr+2,val>>16);
979 return;
980 }
981 if (seg==-1)
982 {
983 x86gpf("NULL segment", 0);
984 printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,pc,opcode,addr);
985 return;
986 }
987 if (cr0>>31)
988 {
989 addr2 = mmutranslate_write(addr2);
990 if (addr2==0xFFFFFFFF) return;
991 }
993 addr2&=rammask;
995 /* if (addr >= 0xa0000 && addr < 0xc0000)
996 pclog("writememll %08X %08X\n", addr, val);*/
998 if (_mem_write_l[addr2 >> 14])
999 {
1000 _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
1001 return;
1003 if (_mem_write_w[addr2 >> 14])
1005 _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
1006 _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
1007 return;
1009 if (_mem_write_b[addr2 >> 14])
1011 _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
1012 _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
1013 _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
1014 _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]);
1015 return;
1017 // pclog("Bad writememll %08X %08X\n", addr2, val);
1020 uint8_t mem_readb_phys(uint32_t addr)
1022 mem_logical_addr = 0xffffffff;
1024 if (_mem_read_b[addr >> 14])
1025 return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
1027 return 0xff;
1030 void mem_writeb_phys(uint32_t addr, uint8_t val)
1032 mem_logical_addr = 0xffffffff;
1034 if (_mem_write_b[addr >> 14])
1035 _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
1038 uint8_t mem_read_ram(uint32_t addr, void *priv)
1040 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMb %08X\n", addr);
1041 addreadlookup(mem_logical_addr, addr);
1042 return ram[addr];
1044 uint16_t mem_read_ramw(uint32_t addr, void *priv)
1046 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMw %08X\n", addr);
1047 addreadlookup(mem_logical_addr, addr);
1048 return *(uint16_t *)&ram[addr];
1050 uint32_t mem_read_raml(uint32_t addr, void *priv)
1052 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Read RAMl %08X\n", addr);
1053 addreadlookup(mem_logical_addr, addr);
1054 return *(uint32_t *)&ram[addr];
1057 void mem_write_ram(uint32_t addr, uint8_t val, void *priv)
1059 addwritelookup(mem_logical_addr, addr);
1060 ram[addr] = val;
1061 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMb %08X\n", addr);
1063 void mem_write_ramw(uint32_t addr, uint16_t val, void *priv)
1065 addwritelookup(mem_logical_addr, addr);
1066 *(uint16_t *)&ram[addr] = val;
1067 // 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);
1069 void mem_write_raml(uint32_t addr, uint32_t val, void *priv)
1071 addwritelookup(mem_logical_addr, addr);
1072 *(uint32_t *)&ram[addr] = val;
1073 // if (addr >= 0xc0000 && addr < 0x0c8000) pclog("Write RAMl %08X %04X:%04X %04X:%04X %04X:%04X\n", addr, CS, pc, DS,SI, ES,DI);
1076 uint8_t mem_read_bios(uint32_t addr, void *priv)
1078 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?*/
1080 // pclog("Read magic addr %04X(%06X):%04X\n",CS,cs,pc);
1081 // if (pc==0x547D) output=3;
1082 return 0x40;
1084 // pclog("Read BIOS %08X %02X %04X:%04X\n", addr, rom[addr & biosmask], CS, pc);
1085 return rom[addr & biosmask];
1087 uint16_t mem_read_biosw(uint32_t addr, void *priv)
1089 // pclog("Read BIOS %08X %04X %04X:%04X\n", addr, *(uint16_t *)&rom[addr & biosmask], CS, pc);
1090 return *(uint16_t *)&rom[addr & biosmask];
1092 uint32_t mem_read_biosl(uint32_t addr, void *priv)
1094 // pclog("Read BIOS %08X %02X %04X:%04X\n", addr, *(uint32_t *)&rom[addr & biosmask], CS, pc);
1095 return *(uint32_t *)&rom[addr & biosmask];
1098 uint8_t mem_read_romext(uint32_t addr, void *priv)
1100 return romext[addr & 0x7fff];
1102 uint16_t mem_read_romextw(uint32_t addr, void *priv)
1104 return *(uint16_t *)&romext[addr & 0x7fff];
1106 uint32_t mem_read_romextl(uint32_t addr, void *priv)
1108 return *(uint32_t *)&romext[addr & 0x7fff];
1111 void mem_write_null(uint32_t addr, uint8_t val, void *p)
1114 void mem_write_nullw(uint32_t addr, uint16_t val, void *p)
1117 void mem_write_nulll(uint32_t addr, uint32_t val, void *p)
1121 void mem_updatecache()
1123 flushmmucache();
1124 if (!is386)
1126 cachesize=256;
1127 memwaitstate=0;
1128 return;
1130 if (cpu_16bitbus)
1131 memwaitstate = 512 * cpu_multi;
1132 else
1133 memwaitstate = 384 * cpu_multi; //memspeed[cpuspeed];
1134 switch (cache)
1136 case 0: cachesize=32; break;
1137 case 1: cachesize=64; break;
1138 case 2: cachesize=128; break;
1139 case 3: cachesize=256; break;
1140 case 4: cachesize=256; memwaitstate=0; break;
1144 static inline int mem_mapping_read_allowed(uint32_t flags, int state)
1146 // pclog("mem_mapping_read_allowed: flags=%x state=%x\n", flags, state);
1147 switch (state & MEM_READ_MASK)
1149 case MEM_READ_ANY:
1150 return 1;
1151 case MEM_READ_EXTERNAL:
1152 return !(flags & MEM_MAPPING_INTERNAL);
1153 case MEM_READ_INTERNAL:
1154 return !(flags & MEM_MAPPING_EXTERNAL);
1155 default:
1156 fatal("mem_mapping_read_allowed : bad state %x\n", state);
1160 static inline int mem_mapping_write_allowed(uint32_t flags, int state)
1162 switch (state & MEM_WRITE_MASK)
1164 case MEM_WRITE_DISABLED:
1165 return 0;
1166 case MEM_WRITE_ANY:
1167 return 1;
1168 case MEM_WRITE_EXTERNAL:
1169 return !(flags & MEM_MAPPING_INTERNAL);
1170 case MEM_WRITE_INTERNAL:
1171 return !(flags & MEM_MAPPING_EXTERNAL);
1172 default:
1173 fatal("mem_mapping_write_allowed : bad state %x\n", state);
1177 static void mem_mapping_recalc(uint64_t base, uint64_t size)
1179 uint64_t c;
1180 mem_mapping_t *mapping = base_mapping.next;
1182 if (!size)
1183 return;
1184 /*Clear out old mappings*/
1185 for (c = base; c < base + size; c += 0x4000)
1187 _mem_read_b[c >> 14] = NULL;
1188 _mem_read_w[c >> 14] = NULL;
1189 _mem_read_l[c >> 14] = NULL;
1190 _mem_priv_r[c >> 14] = NULL;
1191 _mem_mapping_r[c >> 14] = NULL;
1192 _mem_write_b[c >> 14] = NULL;
1193 _mem_write_w[c >> 14] = NULL;
1194 _mem_write_l[c >> 14] = NULL;
1195 _mem_priv_w[c >> 14] = NULL;
1196 _mem_mapping_w[c >> 14] = NULL;
1199 /*Walk mapping list*/
1200 while (mapping != NULL)
1202 /*In range?*/
1203 if (mapping->enable && (uint64_t)mapping->base < ((uint64_t)base + (uint64_t)size) && ((uint64_t)mapping->base + (uint64_t)mapping->size) > (uint64_t)base)
1205 uint64_t start = (mapping->base < base) ? mapping->base : base;
1206 uint64_t end = (((uint64_t)mapping->base + (uint64_t)mapping->size) < (base + size)) ? ((uint64_t)mapping->base + (uint64_t)mapping->size) : (base + size);
1207 if (start < mapping->base)
1208 start = mapping->base;
1210 for (c = start; c < end; c += 0x4000)
1212 if ((mapping->read_b || mapping->read_w || mapping->read_l) &&
1213 mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14]))
1215 _mem_read_b[c >> 14] = mapping->read_b;
1216 _mem_read_w[c >> 14] = mapping->read_w;
1217 _mem_read_l[c >> 14] = mapping->read_l;
1218 _mem_exec[c >> 14] = mapping->exec + (c - mapping->base);
1219 _mem_priv_r[c >> 14] = mapping->p;
1220 _mem_mapping_r[c >> 14] = mapping;
1222 if ((mapping->write_b || mapping->write_w || mapping->write_l) &&
1223 mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14]))
1225 _mem_write_b[c >> 14] = mapping->write_b;
1226 _mem_write_w[c >> 14] = mapping->write_w;
1227 _mem_write_l[c >> 14] = mapping->write_l;
1228 _mem_priv_w[c >> 14] = mapping->p;
1229 _mem_mapping_w[c >> 14] = mapping;
1233 mapping = mapping->next;
1237 void mem_mapping_add(mem_mapping_t *mapping,
1238 uint32_t base,
1239 uint32_t size,
1240 uint8_t (*read_b)(uint32_t addr, void *p),
1241 uint16_t (*read_w)(uint32_t addr, void *p),
1242 uint32_t (*read_l)(uint32_t addr, void *p),
1243 void (*write_b)(uint32_t addr, uint8_t val, void *p),
1244 void (*write_w)(uint32_t addr, uint16_t val, void *p),
1245 void (*write_l)(uint32_t addr, uint32_t val, void *p),
1246 uint8_t *exec,
1247 uint32_t flags,
1248 void *p)
1250 mem_mapping_t *dest = &base_mapping;
1252 /*Add mapping to the end of the list*/
1253 while (dest->next)
1254 dest = dest->next;
1255 dest->next = mapping;
1257 if (size)
1258 mapping->enable = 1;
1259 else
1260 mapping->enable = 0;
1261 mapping->base = base;
1262 mapping->size = size;
1263 mapping->read_b = read_b;
1264 mapping->read_w = read_w;
1265 mapping->read_l = read_l;
1266 mapping->write_b = write_b;
1267 mapping->write_w = write_w;
1268 mapping->write_l = write_l;
1269 mapping->exec = exec;
1270 mapping->flags = flags;
1271 mapping->p = p;
1272 mapping->next = NULL;
1274 mem_mapping_recalc(mapping->base, mapping->size);
1277 void mem_mapping_set_handler(mem_mapping_t *mapping,
1278 uint8_t (*read_b)(uint32_t addr, void *p),
1279 uint16_t (*read_w)(uint32_t addr, void *p),
1280 uint32_t (*read_l)(uint32_t addr, void *p),
1281 void (*write_b)(uint32_t addr, uint8_t val, void *p),
1282 void (*write_w)(uint32_t addr, uint16_t val, void *p),
1283 void (*write_l)(uint32_t addr, uint32_t val, void *p))
1285 mapping->read_b = read_b;
1286 mapping->read_w = read_w;
1287 mapping->read_l = read_l;
1288 mapping->write_b = write_b;
1289 mapping->write_w = write_w;
1290 mapping->write_l = write_l;
1292 mem_mapping_recalc(mapping->base, mapping->size);
1295 void mem_mapping_set_addr(mem_mapping_t *mapping, uint32_t base, uint32_t size)
1297 /*Remove old mapping*/
1298 mapping->enable = 0;
1299 mem_mapping_recalc(mapping->base, mapping->size);
1301 /*Set new mapping*/
1302 mapping->enable = 1;
1303 mapping->base = base;
1304 mapping->size = size;
1306 mem_mapping_recalc(mapping->base, mapping->size);
1309 void mem_mapping_set_exec(mem_mapping_t *mapping, uint8_t *exec)
1311 mapping->exec = exec;
1313 mem_mapping_recalc(mapping->base, mapping->size);
1316 void mem_mapping_set_p(mem_mapping_t *mapping, void *p)
1318 mapping->p = p;
1321 void mem_mapping_disable(mem_mapping_t *mapping)
1323 mapping->enable = 0;
1325 mem_mapping_recalc(mapping->base, mapping->size);
1328 void mem_mapping_enable(mem_mapping_t *mapping)
1330 mapping->enable = 1;
1332 mem_mapping_recalc(mapping->base, mapping->size);
1335 void mem_set_mem_state(uint32_t base, uint32_t size, int state)
1337 uint32_t c;
1339 // pclog("mem_set_pci_enable: base=%08x size=%08x\n", base, size);
1340 for (c = 0; c < size; c += 0x4000)
1341 _mem_state[(c + base) >> 14] = state;
1343 mem_mapping_recalc(base, size);
1346 void mem_add_bios()
1348 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);
1349 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);
1350 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);
1351 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);
1352 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);
1353 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);
1354 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);
1355 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);
1357 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);
1358 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);
1359 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);
1360 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);
1361 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);
1362 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);
1363 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);
1364 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);
1367 void mem_init()
1369 int c;
1371 ram = malloc(mem_size * 1024 * 1024);
1372 rom = malloc(0x20000);
1373 vram = malloc(0x800000);
1374 readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t));
1375 writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t));
1376 cachelookup2 = malloc(1024 * 1024);
1377 biosmask = 0xffff;
1379 memset(ram, 0, mem_size * 1024 * 1024);
1381 memset(isram, 0, sizeof(isram));
1382 for (c = 0; c < (mem_size * 16); c++)
1384 isram[c] = 1;
1385 if (c >= 0xa && c <= 0xf)
1386 isram[c] = 0;
1389 memset(_mem_read_b, 0, sizeof(_mem_read_b));
1390 memset(_mem_read_w, 0, sizeof(_mem_read_w));
1391 memset(_mem_read_l, 0, sizeof(_mem_read_l));
1392 memset(_mem_write_b, 0, sizeof(_mem_write_b));
1393 memset(_mem_write_w, 0, sizeof(_mem_write_w));
1394 memset(_mem_write_l, 0, sizeof(_mem_write_l));
1396 memset(&base_mapping, 0, sizeof(base_mapping));
1398 memset(_mem_state, 0, sizeof(_mem_state));
1400 mem_set_mem_state(0x000000, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1401 mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
1402 mem_set_mem_state(0x100000, (mem_size - 1) * 1024 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1404 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);
1405 if (mem_size > 1)
1406 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);
1407 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);
1409 mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
1410 // pclog("Mem resize %i %i\n",mem_size,c);
1413 void mem_resize()
1415 int c;
1417 free(ram);
1418 ram = malloc(mem_size * 1024 * 1024);
1419 memset(ram, 0, mem_size * 1024 * 1024);
1421 memset(isram, 0, sizeof(isram));
1422 for (c = 0; c < (mem_size * 16); c++)
1424 isram[c] = 1;
1425 if (c >= 0xa && c <= 0xf)
1426 isram[c] = 0;
1429 memset(_mem_read_b, 0, sizeof(_mem_read_b));
1430 memset(_mem_read_w, 0, sizeof(_mem_read_w));
1431 memset(_mem_read_l, 0, sizeof(_mem_read_l));
1432 memset(_mem_write_b, 0, sizeof(_mem_write_b));
1433 memset(_mem_write_w, 0, sizeof(_mem_write_w));
1434 memset(_mem_write_l, 0, sizeof(_mem_write_l));
1436 memset(&base_mapping, 0, sizeof(base_mapping));
1438 memset(_mem_state, 0, sizeof(_mem_state));
1440 mem_set_mem_state(0x000000, 0xa0000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1441 mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
1442 mem_set_mem_state(0x100000, (mem_size - 1) * 1024 * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
1444 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);
1445 if (mem_size > 1)
1446 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);
1447 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);
1449 mem_add_bios();
1451 mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
1453 // pclog("Mem resize %i %i\n",mem_size,c);
1456 int mem_a20_key = 0, mem_a20_alt = 0;
1457 static int mem_a20_state = 0;
1459 void mem_a20_recalc()
1461 int state = mem_a20_key | mem_a20_alt;
1462 // pclog("A20 recalc %i %i\n", state, mem_a20_state);
1463 if (state && !mem_a20_state)
1465 rammask = 0xffffffff;
1466 flushmmucache();
1468 else if (!state && mem_a20_state)
1470 rammask = 0xffefffff;
1471 flushmmucache();
1473 // pclog("rammask now %08X\n", rammask);
1474 mem_a20_state = state;