OSDN Git Service

[VM][PC9801][MEMBUS] Split update_bios() to functions.
[csp-qt/common_source_project-fm7.git] / source / src / vm / memory.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2010.09.16-
6
7         [ memory ]
8 */
9
10 #include "memory.h"
11
12 #define ADDR_MASK (addr_max - 1)
13 #define BANK_MASK (bank_size - 1)
14
15 void MEMORY::initialize()
16 {
17         // allocate tables here to support multiple instances with different address range
18         if(rd_table == NULL) {
19                 int64_t bank_num = addr_max / bank_size;
20                 
21                 rd_dummy = (uint8_t *)malloc(bank_size);
22                 wr_dummy = (uint8_t *)malloc(bank_size);
23                 
24                 rd_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
25                 wr_table = (bank_t *)calloc(bank_num, sizeof(bank_t));
26                 
27                 for(int i = 0; i < bank_num; i++) {
28                         rd_table[i].dev = NULL;
29                         rd_table[i].memory = rd_dummy;
30                         rd_table[i].wait = 0;
31                         
32                         wr_table[i].dev = NULL;
33                         wr_table[i].memory = wr_dummy;
34                         rd_table[i].wait = 0;
35                 }
36                 for(int i = 0;; i++) {
37                         if(bank_size == (int64_t)(1 << i)) {
38                                 addr_shift = i;
39                                 break;
40                         }
41                 }
42                 memset(rd_dummy, 0xff, bank_size);
43         }
44 }
45
46 void MEMORY::release()
47 {
48         free(rd_table);
49         free(wr_table);
50         free(rd_dummy);
51         free(wr_dummy);
52 }
53
54 uint32_t MEMORY::read_data8(uint32_t addr)
55 {
56         int bank = (addr & ADDR_MASK) >> addr_shift;
57         
58         if(rd_table[bank].dev != NULL) {
59                 return rd_table[bank].dev->read_memory_mapped_io8(addr);
60         } else {
61                 return rd_table[bank].memory[addr & BANK_MASK];
62         }
63 }
64
65 void MEMORY::write_data8(uint32_t addr, uint32_t data)
66 {
67         int bank = (addr & ADDR_MASK) >> addr_shift;
68         
69         if(wr_table[bank].dev != NULL) {
70                 wr_table[bank].dev->write_memory_mapped_io8(addr, data);
71         } else {
72                 wr_table[bank].memory[addr & BANK_MASK] = data;
73         }
74 }
75
76 uint32_t MEMORY::read_data16(uint32_t addr)
77 {
78         int bank = (addr & ADDR_MASK) >> addr_shift;
79         
80         if(rd_table[bank].dev != NULL) {
81                 return rd_table[bank].dev->read_memory_mapped_io16(addr);
82         } else {
83                 int bank1 = ((addr + 1) & ADDR_MASK) >> addr_shift;
84                 if(bank != bank1) {
85                         uint32_t val = read_data8(addr);
86                         val |= read_data8(addr + 1) << 8;
87                         return val;
88                 } else {
89                         uint8_t* p = (uint8_t*)(&(rd_table[bank].memory[addr & BANK_MASK]));
90                         uint32_t val;
91 #if defined(__LITTLE_ENDIAN__)
92                         uint16_t* pp = (uint16_t*)p;
93                         val = (uint32_t)(*pp);
94 #else                   
95                         val = p[0];
96                         val =  (val << 8) | ((uint32_t)(p[1]));
97 #endif
98                         return val;
99                 }
100         }
101 }
102
103 void MEMORY::write_data16(uint32_t addr, uint32_t data)
104 {
105         int bank = (addr & ADDR_MASK) >> addr_shift;
106         
107         if(wr_table[bank].dev != NULL) {
108                 wr_table[bank].dev->write_memory_mapped_io16(addr, data);
109         } else {
110                 int bank1 = ((addr + 1) & ADDR_MASK) >> addr_shift;
111                 if(bank != bank1) {
112                         write_data8(addr, data & 0xff);
113                         write_data8(addr + 1, (data >> 8) & 0xff);
114                 } else {
115                         uint8_t* p = (uint8_t*)(&(wr_table[bank].memory[addr & BANK_MASK]));
116 #if defined(__LITTLE_ENDIAN__)
117                         uint16_t* pp = (uint16_t*)p;
118                         *pp = (uint16_t)data;
119 #else
120                         p[0] = data & 0xff;
121                         p[1] = (data >> 8) & 0xff;
122 #endif
123                 }                       
124         }
125 }
126
127 uint32_t MEMORY::read_data32(uint32_t addr)
128 {
129         int bank = (addr & ADDR_MASK) >> addr_shift;
130         
131         if(rd_table[bank].dev != NULL) {
132                 return rd_table[bank].dev->read_memory_mapped_io32(addr);
133         } else {
134                 int bank1 = ((addr + 3) & ADDR_MASK) >> addr_shift;
135                 if(bank != bank1) {
136                         uint32_t val = read_data16(addr);
137                         val |= read_data16(addr + 2) << 16;
138                         return val;
139                 } else {
140                         uint8_t* p = (uint8_t*)(&(rd_table[bank].memory[addr & BANK_MASK]));
141                         uint32_t val;
142 #if defined(__LITTLE_ENDIAN__)
143                         uint32_t* pp = (uint32_t*)p;
144                         val = *pp;
145 #else
146                         val = ((uint32_t)p[0]) | (((uint32_t)p[1]) << 8) | (((uint32_t)p[2]) << 16) |(((uint32_t)p[3]) << 24);
147 #endif
148                         return val;
149                 }
150         }
151 }
152
153 void MEMORY::write_data32(uint32_t addr, uint32_t data)
154 {
155         int bank = (addr & ADDR_MASK) >> addr_shift;
156         
157         if(wr_table[bank].dev != NULL) {
158                 wr_table[bank].dev->write_memory_mapped_io32(addr, data);
159         } else {
160                 int bank1 = ((addr + 3) & ADDR_MASK) >> addr_shift;
161                 if(bank != bank1) {
162                         write_data16(addr, data & 0xffff);
163                         write_data16(addr + 2, (data >> 16) & 0xffff);
164                 } else {
165                         uint8_t* p = (uint8_t*)(&(wr_table[bank].memory[addr & BANK_MASK]));
166 #if defined(__LITTLE_ENDIAN__)
167                         uint32_t* pp = (uint32_t*)p;
168                         *pp = data;
169 #else
170                         p[0] = data & 0xff;
171                         p[1] = (data >> 8) & 0xff;
172                         p[2] = (data >> 16) & 0xff;
173                         p[3] = (data >> 24) & 0xff;
174 #endif
175                 }
176         }
177 }
178
179 uint32_t MEMORY::read_data8w(uint32_t addr, int* wait)
180 {
181         int bank = (addr & ADDR_MASK) >> addr_shift;
182         
183         *wait = rd_table[bank].wait;
184         if(rd_table[bank].dev != NULL) {
185                 return rd_table[bank].dev->read_memory_mapped_io8(addr);
186         } else {
187                 return rd_table[bank].memory[addr & BANK_MASK];
188         }
189 }
190
191 void MEMORY::write_data8w(uint32_t addr, uint32_t data, int* wait)
192 {
193         int bank = (addr & ADDR_MASK) >> addr_shift;
194         
195         *wait = wr_table[bank].wait;
196         if(wr_table[bank].dev != NULL) {
197                 wr_table[bank].dev->write_memory_mapped_io8(addr, data);
198         } else {
199                 wr_table[bank].memory[addr & BANK_MASK] = data;
200         }
201 }
202
203 uint32_t MEMORY::read_data16w(uint32_t addr, int* wait)
204 {
205         int wait_l, wait_h;
206         uint32_t val = read_data8w(addr, &wait_l);
207         val |= read_data8w(addr + 1, &wait_h) << 8;
208         *wait = wait_l + wait_h;
209         return val;
210 }
211
212 void MEMORY::write_data16w(uint32_t addr, uint32_t data, int* wait)
213 {
214         int wait_l, wait_h;
215         write_data8w(addr, data & 0xff, &wait_l);
216         write_data8w(addr + 1, (data >> 8) & 0xff, &wait_h);
217         *wait = wait_l + wait_h;
218 }
219
220 uint32_t MEMORY::read_data32w(uint32_t addr, int* wait)
221 {
222         int wait_l, wait_h;
223         uint32_t val = read_data16w(addr, &wait_l);
224         val |= read_data16w(addr + 2, &wait_h) << 16;
225         *wait = wait_l + wait_h;
226         return val;
227 }
228
229 void MEMORY::write_data32w(uint32_t addr, uint32_t data, int* wait)
230 {
231         int wait_l, wait_h;
232         write_data16w(addr, data & 0xffff, &wait_l);
233         write_data16w(addr + 2, (data >> 16) & 0xffff, &wait_h);
234         *wait = wait_l + wait_h;
235 }
236
237 #ifdef MEMORY_DISABLE_DMA_MMIO
238 uint32_t MEMORY::read_dma_data8(uint32_t addr)
239 {
240         int bank = (addr & ADDR_MASK) >> addr_shift;
241         
242         if(rd_table[bank].dev != NULL) {
243 //              return rd_table[bank].dev->read_memory_mapped_io8(addr);
244                 return 0xff;
245         } else {
246                 return rd_table[bank].memory[addr & BANK_MASK];
247         }
248 }
249
250 void MEMORY::write_dma_data8(uint32_t addr, uint32_t data)
251 {
252         int bank = (addr & ADDR_MASK) >> addr_shift;
253         
254         if(wr_table[bank].dev != NULL) {
255 //              wr_table[bank].dev->write_memory_mapped_io8(addr, data);
256         } else {
257                 wr_table[bank].memory[addr & BANK_MASK] = data;
258         }
259 }
260
261 uint32_t MEMORY::read_dma_data16(uint32_t addr)
262 {
263         int bank = (addr & ADDR_MASK) >> addr_shift;
264         
265         if(rd_table[bank].dev != NULL) {
266 //              return rd_table[bank].dev->read_memory_mapped_io16(addr);
267                 return 0xffff;
268         } else {
269                 uint32_t val = read_dma_data8(addr);
270                 val |= read_dma_data8(addr + 1) << 8;
271                 return val;
272         }
273 }
274
275 void MEMORY::write_dma_data16(uint32_t addr, uint32_t data)
276 {
277         int bank = (addr & ADDR_MASK) >> addr_shift;
278         
279         if(wr_table[bank].dev != NULL) {
280 //              wr_table[bank].dev->write_memory_mapped_io16(addr, data);
281         } else {
282                 write_dma_data8(addr, data & 0xff);
283                 write_dma_data8(addr + 1, (data >> 8) & 0xff);
284         }
285 }
286
287 uint32_t MEMORY::read_dma_data32(uint32_t addr)
288 {
289         int bank = (addr & ADDR_MASK) >> addr_shift;
290         
291         if(rd_table[bank].dev != NULL) {
292 //              return rd_table[bank].dev->read_memory_mapped_io32(addr);
293                 return 0xffffffff;
294         } else {
295                 uint32_t val = read_dma_data16(addr);
296                 val |= read_dma_data16(addr + 2) << 16;
297                 return val;
298         }
299 }
300
301 void MEMORY::write_dma_data32(uint32_t addr, uint32_t data)
302 {
303         int bank = (addr & ADDR_MASK) >> addr_shift;
304         
305         if(wr_table[bank].dev != NULL) {
306 //              wr_table[bank].dev->write_memory_mapped_io32(addr, data);
307         } else {
308                 write_dma_data16(addr, data & 0xffff);
309                 write_dma_data16(addr + 2, (data >> 16) & 0xffff);
310         }
311 }
312 #endif
313
314 // register
315
316 void MEMORY::set_memory_r(uint32_t start, uint32_t end, uint8_t *memory)
317 {
318         MEMORY::initialize(); // subclass may overload initialize()
319         
320         uint32_t start_bank = start >> addr_shift;
321         uint32_t end_bank = end >> addr_shift;
322         
323         for(uint32_t i = start_bank; i <= end_bank; i++) {
324                 rd_table[i].dev = NULL;
325                 rd_table[i].memory = memory + bank_size * (i - start_bank);
326         }
327 }
328
329 void MEMORY::set_memory_w(uint32_t start, uint32_t end, uint8_t *memory)
330 {
331         MEMORY::initialize();
332         
333         uint32_t start_bank = start >> addr_shift;
334         uint32_t end_bank = end >> addr_shift;
335         
336         for(uint32_t i = start_bank; i <= end_bank; i++) {
337                 wr_table[i].dev = NULL;
338                 wr_table[i].memory = memory + bank_size * (i - start_bank);
339         }
340 }
341
342 void MEMORY::set_memory_mapped_io_r(uint32_t start, uint32_t end, DEVICE *device)
343 {
344         MEMORY::initialize();
345         
346         uint32_t start_bank = start >> addr_shift;
347         uint32_t end_bank = end >> addr_shift;
348         
349         for(uint32_t i = start_bank; i <= end_bank; i++) {
350                 rd_table[i].dev = device;
351         }
352 }
353
354 void MEMORY::set_memory_mapped_io_w(uint32_t start, uint32_t end, DEVICE *device)
355 {
356         MEMORY::initialize();
357         
358         uint32_t start_bank = start >> addr_shift;
359         uint32_t end_bank = end >> addr_shift;
360         
361         for(uint32_t i = start_bank; i <= end_bank; i++) {
362                 wr_table[i].dev = device;
363         }
364 }
365
366 void MEMORY::set_wait_r(uint32_t start, uint32_t end, int wait)
367 {
368         MEMORY::initialize();
369         
370         uint32_t start_bank = start >> addr_shift;
371         uint32_t end_bank = end >> addr_shift;
372         
373         for(uint32_t i = start_bank; i <= end_bank; i++) {
374                 rd_table[i].wait = wait;
375         }
376 }
377
378 void MEMORY::set_wait_w(uint32_t start, uint32_t end, int wait)
379 {
380         MEMORY::initialize();
381         
382         uint32_t start_bank = start >> addr_shift;
383         uint32_t end_bank = end >> addr_shift;
384         
385         for(uint32_t i = start_bank; i <= end_bank; i++) {
386                 wr_table[i].wait = wait;
387         }
388 }
389
390 void MEMORY::unset_memory_r(uint32_t start, uint32_t end)
391 {
392         MEMORY::initialize();
393         
394         uint32_t start_bank = start >> addr_shift;
395         uint32_t end_bank = end >> addr_shift;
396         
397         for(uint32_t i = start_bank; i <= end_bank; i++) {
398                 rd_table[i].dev = NULL;
399                 rd_table[i].memory = rd_dummy;
400         }
401 }
402
403 void MEMORY::unset_memory_w(uint32_t start, uint32_t end)
404 {
405         MEMORY::initialize();
406         
407         uint32_t start_bank = start >> addr_shift;
408         uint32_t end_bank = end >> addr_shift;
409         
410         for(uint32_t i = start_bank; i <= end_bank; i++) {
411                 wr_table[i].dev = NULL;
412                 wr_table[i].memory = wr_dummy;
413         }
414 }
415
416 void MEMORY::copy_table_w(uint32_t to, uint32_t start, uint32_t end)
417 {
418         MEMORY::initialize();
419
420         uint32_t start_bank = start >> addr_shift;
421         uint32_t end_bank = end >> addr_shift;
422         uint32_t to_bank = to >> addr_shift;
423         int blocks = (int)(addr_max / bank_size);
424         
425         for(uint32_t i = start_bank; i <= end_bank; i++) {
426                 if(to_bank >= blocks) break;
427                 wr_table[to_bank].dev = wr_table[i].dev;
428                 wr_table[to_bank].memory = wr_table[i].memory;
429                 wr_table[to_bank].wait = wr_table[i].wait;
430                 to_bank++;
431         }
432 }
433
434 void MEMORY::copy_table_r(uint32_t to, uint32_t start, uint32_t end)
435 {
436         MEMORY::initialize();
437
438         uint32_t start_bank = start >> addr_shift;
439         uint32_t end_bank = end >> addr_shift;
440         uint32_t to_bank = to >> addr_shift;
441         int blocks = (int)(addr_max / bank_size);
442
443         for(uint32_t i = start_bank; i <= end_bank; i++) {
444                 if(to_bank >= blocks) break;
445                 rd_table[to_bank].dev = rd_table[i].dev;
446                 rd_table[to_bank].memory = rd_table[i].memory;
447                 rd_table[to_bank].wait = rd_table[i].wait;
448                 to_bank++;
449         }
450 }
451
452 // load/save image
453
454 int MEMORY::read_bios(const _TCHAR *file_name, uint8_t *buffer, int size)
455 {
456         FILEIO* fio = new FILEIO();
457         int length = 0;
458         if(fio->Fopen(create_local_path(file_name), FILEIO_READ_BINARY)) {
459                 fio->Fread(buffer, size, 1);
460                 length = fio->Ftell();
461                 fio->Fclose();
462         }
463         out_debug_log("LOADING ROM %s REQ_SIZE=%d PRESENTED_SIZE=%d", create_local_path(file_name), size, length);
464         delete fio;
465         return length;
466 }
467
468 bool MEMORY::write_bios(const _TCHAR *file_name, uint8_t *buffer, int size)
469 {
470         FILEIO* fio = new FILEIO();
471         bool result = false;
472         
473         if(fio->Fopen(create_local_path(file_name), FILEIO_WRITE_BINARY)) {
474                 fio->Fwrite(buffer, size, 1);
475                 fio->Fclose();
476                 result = true;
477         }
478         delete fio;
479         return result;
480 }
481
482 bool MEMORY::read_image(const _TCHAR *file_path, uint8_t *buffer, int size)
483 {
484         FILEIO* fio = new FILEIO();
485         bool result = false;
486         
487         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
488                 fio->Fread(buffer, size, 1);
489                 fio->Fclose();
490                 result = true;
491         }
492         delete fio;
493         return result;
494 }
495
496 bool MEMORY::write_image(const _TCHAR* file_path, uint8_t* buffer, int size)
497 {
498         FILEIO* fio = new FILEIO();
499         bool result = false;
500         
501         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
502                 fio->Fwrite(buffer, size, 1);
503                 fio->Fclose();
504                 result = true;
505         }
506         delete fio;
507         return result;
508 }