25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: memory_rw.c,v 1.95 2006/07/25 21:49:14 debug Exp $ |
* $Id: memory_rw.c,v 1.97 2006/09/07 11:44:01 debug Exp $ |
29 |
* |
* |
30 |
* Generic memory_rw(), with special hacks for specific CPU families. |
* Generic memory_rw(), with special hacks for specific CPU families. |
31 |
* |
* |
98 |
/* Crossing a page boundary? Then do one byte at a time: */ |
/* Crossing a page boundary? Then do one byte at a time: */ |
99 |
if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL) |
if ((vaddr & 0xfff) + len > 0x1000 && !(misc_flags & PHYSICAL) |
100 |
&& cpu->cd.x86.cr[0] & X86_CR0_PG) { |
&& cpu->cd.x86.cr[0] & X86_CR0_PG) { |
101 |
/* For WRITES: Read ALL BYTES FIRST and write them back!!! |
/* |
102 |
Then do a write of all the new bytes. This is to make sure |
* For WRITES: Read ALL BYTES FIRST and write them back!!! |
103 |
than both pages around the boundary are writable so we don't |
* Then do a write of all the new bytes. This is to make sure |
104 |
do a partial write. */ |
* than both pages around the boundary are writable so that |
105 |
|
* there is no "partial write" performed. |
106 |
|
*/ |
107 |
int res = 0; |
int res = 0; |
108 |
size_t i; |
size_t i; |
109 |
if (writeflag == MEM_WRITE) { |
if (writeflag == MEM_WRITE) { |
166 |
+ (misc_flags & MEMORY_USER_ACCESS) |
+ (misc_flags & MEMORY_USER_ACCESS) |
167 |
#endif |
#endif |
168 |
+ (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0)); |
+ (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0)); |
169 |
/* If the translation caused an exception, or was invalid in |
|
170 |
some way, we simply return without doing the memory |
/* |
171 |
access: */ |
* If the translation caused an exception, or was invalid in |
172 |
|
* some way, then simply return without doing the memory |
173 |
|
* access: |
174 |
|
*/ |
175 |
if (!ok) |
if (!ok) |
176 |
return MEMORY_ACCESS_FAILED; |
return MEMORY_ACCESS_FAILED; |
177 |
} |
} |
229 |
*/ |
*/ |
230 |
#if 1 |
#if 1 |
231 |
for (i=0; i<mem->n_mmapped_devices; i++) |
for (i=0; i<mem->n_mmapped_devices; i++) |
232 |
if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) && |
if (paddr >= (mem->devices[i].baseaddr & ~offset_mask)&& |
233 |
paddr <= ((mem->dev_endaddr[i]-1) | offset_mask)) { |
paddr <= ((mem->devices[i].endaddr-1)|offset_mask)){ |
234 |
dyntrans_device_danger = 1; |
dyntrans_device_danger = 1; |
235 |
break; |
break; |
236 |
} |
} |
241 |
|
|
242 |
/* Scan through all devices: */ |
/* Scan through all devices: */ |
243 |
do { |
do { |
244 |
if (paddr >= mem->dev_baseaddr[i] && |
if (paddr >= mem->devices[i].baseaddr && |
245 |
paddr < mem->dev_endaddr[i]) { |
paddr < mem->devices[i].endaddr) { |
246 |
/* Found a device, let's access it: */ |
/* Found a device, let's access it: */ |
247 |
mem->last_accessed_device = i; |
mem->last_accessed_device = i; |
248 |
|
|
249 |
paddr -= mem->dev_baseaddr[i]; |
paddr -= mem->devices[i].baseaddr; |
250 |
if (paddr + len > mem->dev_length[i]) |
if (paddr + len > mem->devices[i].length) |
251 |
len = mem->dev_length[i] - paddr; |
len = mem->devices[i].length - paddr; |
252 |
|
|
253 |
if (cpu->update_translation_table != NULL && |
if (cpu->update_translation_table != NULL && |
254 |
!(ok & MEMORY_NOT_FULL_PAGE) && |
!(ok & MEMORY_NOT_FULL_PAGE) && |
255 |
mem->dev_flags[i] & DM_DYNTRANS_OK) { |
mem->devices[i].flags & DM_DYNTRANS_OK) { |
256 |
int wf = writeflag == MEM_WRITE? 1 : 0; |
int wf = writeflag == MEM_WRITE? 1 : 0; |
257 |
unsigned char *host_addr; |
unsigned char *host_addr; |
258 |
|
|
259 |
if (!(mem->dev_flags[i] & |
if (!(mem->devices[i].flags & |
260 |
DM_DYNTRANS_WRITE_OK)) |
DM_DYNTRANS_WRITE_OK)) |
261 |
wf = 0; |
wf = 0; |
262 |
|
|
263 |
if (writeflag && wf) { |
if (writeflag && wf) { |
264 |
if (paddr < mem-> |
if (paddr < mem->devices[i]. |
265 |
dev_dyntrans_write_low[i]) |
dyntrans_write_low) |
266 |
mem-> |
mem->devices[i]. |
267 |
dev_dyntrans_write_low |
dyntrans_write_low = |
268 |
[i] = paddr & |
paddr &~offset_mask; |
269 |
~offset_mask; |
if (paddr >= mem->devices[i]. |
270 |
if (paddr >= mem-> |
dyntrans_write_high) |
271 |
dev_dyntrans_write_high[i]) |
mem->devices[i]. |
272 |
mem-> |
dyntrans_write_high = |
273 |
dev_dyntrans_write_high |
paddr | offset_mask; |
|
[i] = paddr | |
|
|
offset_mask; |
|
274 |
} |
} |
275 |
|
|
276 |
if (mem->dev_flags[i] & |
if (mem->devices[i].flags & |
277 |
DM_EMULATED_RAM) { |
DM_EMULATED_RAM) { |
278 |
/* MEM_WRITE to force the page |
/* MEM_WRITE to force the page |
279 |
to be allocated, if it |
to be allocated, if it |
280 |
wasn't already */ |
wasn't already */ |
281 |
uint64_t *pp = (uint64_t *) |
uint64_t *pp = (uint64_t *)mem-> |
282 |
mem->dev_dyntrans_data[i]; |
devices[i].dyntrans_data; |
283 |
uint64_t p = orig_paddr - *pp; |
uint64_t p = orig_paddr - *pp; |
284 |
host_addr = |
host_addr = |
285 |
memory_paddr_to_hostaddr( |
memory_paddr_to_hostaddr( |
286 |
mem, p & ~offset_mask, |
mem, p & ~offset_mask, |
287 |
MEM_WRITE); |
MEM_WRITE); |
288 |
} else { |
} else { |
289 |
host_addr = |
host_addr = mem->devices[i]. |
290 |
mem->dev_dyntrans_data[i] + |
dyntrans_data + |
291 |
(paddr & ~offset_mask); |
(paddr & ~offset_mask); |
292 |
} |
} |
293 |
|
|
297 |
} |
} |
298 |
|
|
299 |
res = 0; |
res = 0; |
300 |
if (!no_exceptions || (mem->dev_flags[i] & |
if (!no_exceptions || (mem->devices[i].flags & |
301 |
DM_READS_HAVE_NO_SIDE_EFFECTS)) |
DM_READS_HAVE_NO_SIDE_EFFECTS)) |
302 |
res = mem->dev_f[i](cpu, mem, paddr, |
res = mem->devices[i].f(cpu, mem, paddr, |
303 |
data, len, writeflag, |
data, len, writeflag, |
304 |
mem->dev_extra[i]); |
mem->devices[i].extra); |
305 |
|
|
306 |
if (res == 0) |
if (res == 0) |
307 |
res = -1; |
res = -1; |
315 |
debug("%s device '%s' addr %08lx " |
debug("%s device '%s' addr %08lx " |
316 |
"failed\n", writeflag? |
"failed\n", writeflag? |
317 |
"writing to" : "reading from", |
"writing to" : "reading from", |
318 |
mem->dev_name[i], (long)paddr); |
mem->devices[i].name, (long)paddr); |
319 |
#ifdef MEM_MIPS |
#ifdef MEM_MIPS |
320 |
mips_cpu_exception(cpu, EXCEPTION_DBE, |
mips_cpu_exception(cpu, EXCEPTION_DBE, |
321 |
0, vaddr, 0, 0, 0, 0); |
0, vaddr, 0, 0, 0, 0); |
326 |
goto do_return_ok; |
goto do_return_ok; |
327 |
} |
} |
328 |
|
|
329 |
if (paddr < mem->dev_baseaddr[i]) |
if (paddr < mem->devices[i].baseaddr) |
330 |
end = i - 1; |
end = i - 1; |
331 |
if (paddr >= mem->dev_endaddr[i]) |
if (paddr >= mem->devices[i].endaddr) |
332 |
start = i + 1; |
start = i + 1; |
333 |
i = (start + end) >> 1; |
i = (start + end) >> 1; |
334 |
} while (start <= end); |
} while (start <= end); |
504 |
#endif |
#endif |
505 |
paddr & ~offset_mask); |
paddr & ~offset_mask); |
506 |
|
|
507 |
/* Invalidate code translations for the page we are writing to. */ |
/* |
508 |
|
* If writing, then invalidate code translations for the (physical) |
509 |
|
* page address: |
510 |
|
*/ |
511 |
if (writeflag == MEM_WRITE && cpu->invalidate_code_translation != NULL) |
if (writeflag == MEM_WRITE && cpu->invalidate_code_translation != NULL) |
512 |
cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR); |
cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR); |
513 |
|
|