1 |
/* |
2 |
* PearPC |
3 |
* jitc_mmu.S |
4 |
* |
5 |
* Copyright (C) 2003-2006 Sebastian Biallas (sb@biallas.net) |
6 |
* |
7 |
* This program is free software; you can redistribute it and/or modify |
8 |
* it under the terms of the GNU General Public License version 2 as |
9 |
* published by the Free Software Foundation. |
10 |
* |
11 |
* This program is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 |
*/ |
20 |
|
21 |
#ifndef PREFIX |
22 |
#define PREFIX |
23 |
#endif |
24 |
|
25 |
#define EXPORT(sym) EXPORT2(PREFIX, sym) |
26 |
#define EXPORT2(p, sym) EXPORT3(p, sym) |
27 |
#define EXPORT3(p, sym) .globl p##sym; p##sym |
28 |
|
29 |
#define EXTERN(sym) EXTERN2(PREFIX, sym) |
30 |
#define EXTERN2(p, sym) EXTERN3(p, sym) |
31 |
#define EXTERN3(p, sym) p##sym |
32 |
|
33 |
#define STRUCT .struct 0 |
34 |
#define MEMBER(m, s) m:;.struct m+s |
35 |
|
36 |
.intel_syntax prefix |
37 |
|
38 |
#define TLB_ENTRIES 32 |
39 |
|
40 |
# Define this if you want exact handling of the SO bit. |
41 |
/* #define EXACT_SO */ |
42 |
|
43 |
STRUCT #PPC_CPU_State |
44 |
MEMBER(dummy, 4) |
45 |
MEMBER(gpr, 32*4) |
46 |
MEMBER(fpr, 32*8) |
47 |
MEMBER(cr, 4) |
48 |
MEMBER(fpscr, 4) |
49 |
MEMBER(xer, 4) |
50 |
MEMBER(xer_ca, 4) |
51 |
MEMBER(lt, 4) |
52 |
MEMBER(ctr, 4) |
53 |
|
54 |
MEMBER(msr, 4) |
55 |
MEMBER(pvr, 4) |
56 |
|
57 |
MEMBER(ibatu, 4*4) |
58 |
MEMBER(ibatl, 4*4) |
59 |
MEMBER(ibat_bl, 4*4) |
60 |
MEMBER(ibat_nbl, 4*4) |
61 |
MEMBER(ibat_bepi, 4*4) |
62 |
MEMBER(ibat_brpn, 4*4) |
63 |
|
64 |
MEMBER(dbatu, 4*4) |
65 |
MEMBER(dbatl, 4*4) |
66 |
MEMBER(dbat_bl, 4*4) |
67 |
MEMBER(dbat_nbl, 4*4) |
68 |
MEMBER(dbat_bepi, 4*4) |
69 |
MEMBER(dbat_brpn, 4*4) |
70 |
|
71 |
MEMBER(sdr1, 4) |
72 |
|
73 |
MEMBER(sr, 16*4) |
74 |
|
75 |
MEMBER(dar, 4) |
76 |
MEMBER(dsisr, 4) |
77 |
MEMBER(sprg, 4*4) |
78 |
MEMBER(srr0, 4) |
79 |
MEMBER(srr1, 4) |
80 |
|
81 |
MEMBER(decr, 4) |
82 |
MEMBER(ear, 4) |
83 |
MEMBER(pir, 4) |
84 |
MEMBER(tb, 8) |
85 |
|
86 |
MEMBER(hid, 16*4) |
87 |
|
88 |
MEMBER(pc, 4) |
89 |
MEMBER(npc, 4) |
90 |
MEMBER(current_opc, 4) |
91 |
|
92 |
MEMBER(exception_pending, 1) |
93 |
MEMBER(dec_exception, 1) |
94 |
MEMBER(ext_exception, 1) |
95 |
MEMBER(stop_exception, 1) |
96 |
MEMBER(singlestep_ignore, 1) |
97 |
MEMBER(align1, 1) |
98 |
MEMBER(align2, 1) |
99 |
MEMBER(align3, 1) |
100 |
|
101 |
MEMBER(pagetable_base, 4) |
102 |
MEMBER(pagetable_hashmask, 4) |
103 |
MEMBER(reserve, 4) |
104 |
MEMBER(have_reservation, 4) |
105 |
|
106 |
MEMBER(tlb_last, 4) |
107 |
MEMBER(tlb_pa, 4*4) |
108 |
MEMBER(tlb_va, 4*4) |
109 |
MEMBER(effective_code_page, 4) |
110 |
MEMBER(physical_code_page, 4) |
111 |
MEMBER(pdec, 2*4) |
112 |
MEMBER(ptb, 2*4) |
113 |
|
114 |
MEMBER(temp, 4) |
115 |
MEMBER(temp2, 4) |
116 |
MEMBER(x87cw, 4) |
117 |
MEMBER(pc_ofs, 4) |
118 |
MEMBER(current_code_base, 4) |
119 |
|
120 |
STRUCT #JITC |
121 |
MEMBER(clientPages, 4) |
122 |
MEMBER(tlb_code_0_eff, TLB_ENTRIES*4) |
123 |
MEMBER(tlb_data_0_eff, TLB_ENTRIES*4) |
124 |
MEMBER(tlb_data_8_eff, TLB_ENTRIES*4) |
125 |
MEMBER(tlb_code_0_phys, TLB_ENTRIES*4) |
126 |
MEMBER(tlb_data_0_phys, TLB_ENTRIES*4) |
127 |
MEMBER(tlb_data_8_phys, TLB_ENTRIES*4) |
128 |
MEMBER(blblbl, 4) |
129 |
MEMBER(tlb_code_0_hits, 8) |
130 |
MEMBER(tlb_data_0_hits, 8) |
131 |
MEMBER(tlb_data_8_hits, 8) |
132 |
MEMBER(tlb_code_0_misses, 8) |
133 |
MEMBER(tlb_data_0_misses, 8) |
134 |
MEMBER(tlb_data_8_misses, 8) |
135 |
|
136 |
MEMBER(nativeReg, 8*4) |
137 |
|
138 |
MEMBER(nativeRegState, 8*4) |
139 |
|
140 |
MEMBER(nativeFlags, 4) |
141 |
|
142 |
MEMBER(nativeFlagsState, 4) |
143 |
MEMBER(nativeCarryState, 4) |
144 |
|
145 |
MEMBER(clientReg, 600*4) |
146 |
|
147 |
MEMBER(nativeRegsList, 8*4) |
148 |
|
149 |
MEMBER(LRUreg, 4) |
150 |
MEMBER(MRUreg, 4) |
151 |
|
152 |
MEMBER(LRUpage, 4) |
153 |
MEMBER(MRUpage, 4) |
154 |
|
155 |
MEMBER(freeFragmentsList, 4) |
156 |
|
157 |
MEMBER(freeClientPages, 4) |
158 |
|
159 |
MEMBER(translationCache, 4) |
160 |
|
161 |
STRUCT #ClientPage |
162 |
MEMBER(entrypoints, 1024*4) |
163 |
MEMBER(baseaddress, 4) |
164 |
MEMBER(tcf_current, 4) |
165 |
MEMBER(bytesLeft, 4) |
166 |
MEMBER(tcp, 4) |
167 |
MEMBER(moreRU, 4) |
168 |
MEMBER(lessRU, 4) |
169 |
|
170 |
#define gCPU(r) EXTERN(gCPU)+r |
171 |
#define gJITC(r) EXTERN(gJITC)+r |
172 |
|
173 |
.text |
174 |
|
175 |
.balign 16 |
176 |
############################################################################################## |
177 |
## |
178 |
EXPORT(ppc_mmu_tlb_invalidate_all_asm): |
179 |
cld |
180 |
or %eax, -1 |
181 |
mov %ecx, TLB_ENTRIES*4*3 / 4 |
182 |
mov %edi, offset gJITC(tlb_code_0_eff) |
183 |
rep stosd |
184 |
ret |
185 |
|
186 |
############################################################################################## |
187 |
## |
188 |
## IN: %eax: effective address to invalidate |
189 |
## |
190 |
EXPORT(ppc_mmu_tlb_invalidate_entry_asm): |
191 |
mov %ecx, %eax |
192 |
or %eax, -1 |
193 |
shr %ecx, 12 |
194 |
and %ecx, TLB_ENTRIES-1 |
195 |
mov [gJITC(tlb_code_0_eff+%ecx*4)], %eax |
196 |
mov [gJITC(tlb_data_0_eff+%ecx*4)], %eax |
197 |
mov [gJITC(tlb_data_8_eff+%ecx*4)], %eax |
198 |
ret |
199 |
|
200 |
############################################################################################## |
201 |
## read_physical_word_pg |
202 |
.macro read_physical_word_pg r1, r2 |
203 |
mov \r2, [EXTERN(gMemory)] |
204 |
mov \r2, [\r2 + \r1] |
205 |
bswap \r2 |
206 |
.endm |
207 |
|
208 |
.balign 16 |
209 |
############################################################################################## |
210 |
## ppc_pte_protection |
211 |
ppc_pte_protection: |
212 |
|
213 |
## read(0)/write(1)*8 | key*4 | pp |
214 |
|
215 |
## read |
216 |
.byte 1 # r/w |
217 |
.byte 1 # r/w |
218 |
.byte 1 # r/w |
219 |
.byte 1 # r |
220 |
.byte 0 # - |
221 |
.byte 1 # r |
222 |
.byte 1 # r/w |
223 |
.byte 1 # r |
224 |
|
225 |
## write |
226 |
.byte 1 # r/w |
227 |
.byte 1 # r/w |
228 |
.byte 1 # r/w |
229 |
.byte 0 # r |
230 |
.byte 0 # - |
231 |
.byte 0 # r |
232 |
.byte 1 # r/w |
233 |
.byte 0 # r |
234 |
|
235 |
############################################################################### |
236 |
## bat_lookup |
237 |
#define bat_lookup(di, n, rw, datacode) \ |
238 |
mov %edx, [gCPU(di##bat_bl + n*4)]; \ |
239 |
mov %ebx, [gCPU(di##bat_bepi + n*4)]; \ |
240 |
\ |
241 |
and %edx, %eax; \ |
242 |
cmp %ebx, %edx; \ |
243 |
jne 3f; \ |
244 |
\ |
245 |
bt dword ptr [gCPU(msr)], 14; \ |
246 |
mov %ebp, 2; \ |
247 |
sbb %ebp, 0; /* BATU_Vp / BATU_Vs */ \ |
248 |
\ |
249 |
test [gCPU(di##batu + n*4)], %ebp; \ |
250 |
jz 3f; \ |
251 |
\ |
252 |
/* FIXME: check access rights */ \ |
253 |
mov %esi, %eax; \ |
254 |
mov %edi, %eax; \ |
255 |
mov %edx, 0xfffff000; \ |
256 |
and %eax, [gCPU(di##bat_nbl + n*4)]; \ |
257 |
or %eax, [gCPU(di##bat_brpn + n*4)]; \ |
258 |
\ |
259 |
/** TLB-Code */ \ |
260 |
shr %edi, 12; \ |
261 |
and %esi, %edx; \ |
262 |
and %edi, TLB_ENTRIES-1; \ |
263 |
and %edx, %eax; \ |
264 |
mov [gJITC(tlb_##datacode##_##rw##_eff+%edi*4)], %esi; \ |
265 |
mov [gJITC(tlb_##datacode##_##rw##_phys+%edi*4)], %edx; \ |
266 |
/* add dword ptr [gJITC(tlb_##datatcode##_##rw##_misses)], 1; */ \ |
267 |
/* adc dword ptr [gJITC(tlb_##datatcode##_##rw##_misses+4)], 0; */ \ |
268 |
ret 4; \ |
269 |
3: |
270 |
|
271 |
############################################################################################## |
272 |
## pg_table_lookup |
273 |
## |
274 |
## param1: PTE1_H or 0 |
275 |
## param2: 0 for read, 8 for write |
276 |
## param3: data / code |
277 |
## param4: pt offset |
278 |
#define pg_table_lookup(n, rw, datacode, offset) \ |
279 |
read_physical_word_pg %ebx+offset, %eax; \ |
280 |
/* %ecx = pte1 */ \ |
281 |
\ |
282 |
mov %ecx, %eax; \ |
283 |
and %eax, (1<<6) | (1<<31); /* (PTE1_V | PTE1_H) */ \ |
284 |
cmp %eax, (n) | (1<<31); \ |
285 |
jne 1f; \ |
286 |
\ |
287 |
mov %eax, %ecx; \ |
288 |
shr %ecx, 7; \ |
289 |
and %ecx, 0xffffff; /* VSID */ \ |
290 |
cmp %ecx, %ebp; \ |
291 |
jne 1f; \ |
292 |
\ |
293 |
and %eax, 0x3f; /* API */ \ |
294 |
cmp %eax, %edi; \ |
295 |
jne 1f; \ |
296 |
\ |
297 |
/* page found */ \ |
298 |
\ |
299 |
read_physical_word_pg %ebx+4+offset, %esi; \ |
300 |
/* # %esi = pte2; */ \ |
301 |
\ |
302 |
/* FIXME: use bt trick? */ \ |
303 |
test dword ptr [gCPU(msr)], (1<<14); /* MSR_PR */ \ |
304 |
mov %eax, (1<<29); /* SR_Kp */ \ |
305 |
setz %cl; \ |
306 |
shl %eax, %cl; /* SR_Kp <--> SR_Ks */ \ |
307 |
test %edx, %eax; /* SR_Kp / SR_Ks */ \ |
308 |
setnz %al; \ |
309 |
movzx %eax, %al; \ |
310 |
\ |
311 |
mov %ecx, %esi; \ |
312 |
and %ecx, 3; \ |
313 |
\ |
314 |
cmp byte ptr [ppc_pte_protection + (rw) + 4*%eax + %ecx], 1; \ |
315 |
.if n==0; \ |
316 |
/* add %esp, 4; /* hash1, no longer needed */ \ |
317 |
pop %edx; \ |
318 |
.endif; \ |
319 |
pop %eax; /* the effective address */ \ |
320 |
jne protection_fault_##rw##_##datacode; \ |
321 |
\ |
322 |
/* update R and C bits */ \ |
323 |
mov %edx, %esi; \ |
324 |
.if rw==0; \ |
325 |
or %edx, (1<<8); /* PTE2_R */ \ |
326 |
.else; \ |
327 |
or %edx, (1<<8) | (1<<7); /* PTE2_R | PTE2_C */ \ |
328 |
.endif; \ |
329 |
bswap %edx; \ |
330 |
add %ebx, [EXTERN(gMemory)]; \ |
331 |
mov [%ebx+4+offset], %edx; \ |
332 |
\ |
333 |
and %esi, 0xfffff000; \ |
334 |
/** TLB-Code */ \ |
335 |
mov %edx, %eax; \ |
336 |
mov %ecx, %eax; \ |
337 |
shr %edx, 12; \ |
338 |
and %ecx, 0xfffff000; \ |
339 |
and %edx, TLB_ENTRIES-1; \ |
340 |
mov [gJITC(tlb_## datacode ##_## rw ##_eff + %edx*4)], %ecx; \ |
341 |
mov [gJITC(tlb_## datacode ##_## rw ##_phys + %edx*4)], %esi; \ |
342 |
/* add dword ptr [gJITC(tlb_## datacode ##_## rw ##_misses)], 1;*/ \ |
343 |
/* adc dword ptr [gJITC(tlb_## datacode ##_## rw ##_misses+4)], 0;*/ \ |
344 |
/***/ \ |
345 |
and %eax, 0x00000fff; \ |
346 |
or %eax, %esi; \ |
347 |
ret 4; \ |
348 |
1: |
349 |
|
350 |
############################################################################################## |
351 |
## protection_fault_%2_%3 |
352 |
protection_fault_0_code: |
353 |
# ppc_exception(PPC_EXC_ISI, PPC_EXC_SRR1_PROT, addr); |
354 |
pop %edx # return address is no longer needed |
355 |
pop %ebx # bytes to roll back |
356 |
add %esp, %ebx |
357 |
mov %ecx, (1<<27) # PPC_EXC_SRR1_PROT |
358 |
jmp EXTERN(ppc_isi_exception_asm) |
359 |
protection_fault_0_data: |
360 |
# ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PROT, addr); |
361 |
pop %edx # return address is no longer needed |
362 |
pop %ebx # bytes to roll back |
363 |
add %esp, %ebx |
364 |
mov %ecx, (1<<27) # PPC_EXC_DSISR_PROT |
365 |
jmp EXTERN(ppc_dsi_exception_asm) |
366 |
protection_fault_8_data: |
367 |
# ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PROT | PPC_EXC_DSISR_STORE, addr); |
368 |
pop %edx # return address is no longer needed |
369 |
pop %ebx # bytes to roll back |
370 |
add %esp, %ebx |
371 |
mov %ecx, (1<<27) | (1<<25) # PPC_EXC_DSISR_PROT | PPC_EXC_DSISR_STORE |
372 |
jmp EXTERN(ppc_dsi_exception_asm) |
373 |
|
374 |
############################################################################################## |
375 |
## param1: 0 for read, 8 for write |
376 |
## param2: data / code |
377 |
#define tlb_lookup(rw, datacode) \ |
378 |
mov %edx, %eax; \ |
379 |
mov %ecx, %eax; \ |
380 |
shr %edx, 12; \ |
381 |
and %ecx, 0xfffff000; \ |
382 |
and %edx, TLB_ENTRIES-1; \ |
383 |
cmp %ecx, [gJITC(tlb_##datacode##_##rw##_eff + %edx*4)]; \ |
384 |
jne 1f; \ |
385 |
/* \ |
386 |
* if a tlb entry is invalid, its \ |
387 |
* lower 12 bits are 1, so the cmp is guaranteed to fail. \ |
388 |
*/ \ |
389 |
/* add dword ptr [gJITC(tlb_##datacode##_##rw##_hits)], 1; */ \ |
390 |
/* adc dword ptr [gJITC(tlb_##datacode##_##rw##_hits+4)], 0; */ \ |
391 |
and %eax, 0x00000fff; \ |
392 |
or %eax, [gJITC(tlb_##datacode##_##rw##_phys + %edx*4)]; \ |
393 |
ret 4; \ |
394 |
1: \ |
395 |
|
396 |
.balign 16 |
397 |
ppc_effective_to_physical_code_ret: |
398 |
mov %edx, %eax |
399 |
mov %ecx, %eax |
400 |
shr %edx, 12 |
401 |
and %ecx, 0xfffff000 |
402 |
and %edx, TLB_ENTRIES-1 |
403 |
mov [gJITC(tlb_code_0_eff+%edx*4)], %ecx |
404 |
mov [gJITC(tlb_code_0_phys+%edx*4)], %ecx |
405 |
ret 4 |
406 |
|
407 |
.balign 16 |
408 |
############################################################################################## |
409 |
## uint32 FASTCALL ppc_effective_to_physical_code(uint32 addr) |
410 |
## |
411 |
## IN %eax: address to translate |
412 |
## |
413 |
## WILL NOT RETURN ON EXCEPTION! |
414 |
## |
415 |
EXPORT(ppc_effective_to_physical_code): |
416 |
tlb_lookup(0, code) |
417 |
|
418 |
test byte ptr [gCPU(msr)], (1<<5) # MSR_IR |
419 |
jz ppc_effective_to_physical_code_ret |
420 |
|
421 |
bat_lookup(i, 0, 0, code) |
422 |
bat_lookup(i, 1, 0, code) |
423 |
bat_lookup(i, 2, 0, code) |
424 |
bat_lookup(i, 3, 0, code) |
425 |
|
426 |
mov %ebx, %eax |
427 |
shr %ebx, 28 # SR |
428 |
mov %edx, [gCPU(sr+4*%ebx)] |
429 |
|
430 |
# test %edx, SR_T --> die |
431 |
|
432 |
test %edx, (1<<28) # SR_N |
433 |
jnz 9f |
434 |
|
435 |
mov %ebx, %eax |
436 |
mov %ebp, %edx |
437 |
shr %ebx, 12 |
438 |
mov %edi, %eax |
439 |
and %ebx, 0xffff |
440 |
shr %edi, 22 |
441 |
and %ebp, 0xffffff |
442 |
and %edi, 0x3f |
443 |
|
444 |
# now: |
445 |
# %eax = addr |
446 |
# %ebx = page_index |
447 |
# %ebp = VSID |
448 |
# %edi = api |
449 |
|
450 |
xor %ebx, %ebp |
451 |
|
452 |
# %ebx = hash1 |
453 |
|
454 |
push %eax |
455 |
push %ebx # das brauch ich |
456 |
|
457 |
and %ebx, [gCPU(pagetable_hashmask)] |
458 |
shl %ebx, 6 |
459 |
or %ebx, [gCPU(pagetable_base)] |
460 |
|
461 |
# %ebx = pteg_addr |
462 |
|
463 |
pg_table_lookup(0, 0, code, 0) |
464 |
pg_table_lookup(0, 0, code, 8) |
465 |
pg_table_lookup(0, 0, code, 16) |
466 |
pg_table_lookup(0, 0, code, 24) |
467 |
pg_table_lookup(0, 0, code, 32) |
468 |
pg_table_lookup(0, 0, code, 40) |
469 |
pg_table_lookup(0, 0, code, 48) |
470 |
pg_table_lookup(0, 0, code, 56) |
471 |
|
472 |
# hash function number 2 |
473 |
pop %ebx |
474 |
not %ebx |
475 |
and %ebx, [gCPU(pagetable_hashmask)] |
476 |
shl %ebx, 6 |
477 |
or %ebx, [gCPU(pagetable_base)] |
478 |
|
479 |
pg_table_lookup(1<<6, 0, code, 0) |
480 |
pg_table_lookup(1<<6, 0, code, 8) |
481 |
pg_table_lookup(1<<6, 0, code, 16) |
482 |
pg_table_lookup(1<<6, 0, code, 24) |
483 |
pg_table_lookup(1<<6, 0, code, 32) |
484 |
pg_table_lookup(1<<6, 0, code, 40) |
485 |
pg_table_lookup(1<<6, 0, code, 48) |
486 |
pg_table_lookup(1<<6, 0, code, 56) |
487 |
|
488 |
# page lookup failed --> throw exception |
489 |
|
490 |
pop %eax |
491 |
pop %edx # return address is no longer needed |
492 |
pop %ecx # bytes to roll back |
493 |
add %esp, %ecx |
494 |
|
495 |
mov %ecx, (1<<30) # PPC_EXC_SRR1_PAGE |
496 |
jmp EXTERN(ppc_isi_exception_asm) |
497 |
9: |
498 |
# segment isnt executable --> throw exception |
499 |
pop %edx # return address is no longer needed |
500 |
pop %ecx # bytes to roll back |
501 |
add %esp, %ecx |
502 |
|
503 |
mov %ecx, (1<<28) # PPC_EXC_SRR1_GUARD |
504 |
jmp EXTERN(ppc_isi_exception_asm) |
505 |
|
506 |
.balign 16 |
507 |
ppc_effective_to_physical_data_read_ret: |
508 |
mov %edx, %eax |
509 |
mov %ecx, %eax |
510 |
shr %edx, 12 |
511 |
and %ecx, 0xfffff000 |
512 |
and %edx, TLB_ENTRIES-1 |
513 |
mov [gJITC(tlb_data_0_eff+%edx*4)], %ecx |
514 |
mov [gJITC(tlb_data_0_phys+%edx*4)], %ecx |
515 |
ret 4 |
516 |
|
517 |
.balign 16 |
518 |
############################################################################################## |
519 |
## uint32 FASTCALL ppc_effective_to_physical_data_read(uint32 addr) |
520 |
## |
521 |
## IN %eax: address to translate |
522 |
## |
523 |
## WILL NOT RETURN ON EXCEPTION! |
524 |
## |
525 |
ppc_effective_to_physical_data_read: |
526 |
tlb_lookup(0, data) |
527 |
|
528 |
test byte ptr [gCPU(msr)], (1<<4) # MSR_DR |
529 |
jz ppc_effective_to_physical_data_read_ret |
530 |
|
531 |
bat_lookup(d, 0, 0, data) |
532 |
bat_lookup(d, 1, 0, data) |
533 |
bat_lookup(d, 2, 0, data) |
534 |
bat_lookup(d, 3, 0, data) |
535 |
|
536 |
mov %ebx, %eax |
537 |
shr %ebx, 28 # SR |
538 |
mov %edx, [gCPU(sr+4*%ebx)] |
539 |
|
540 |
# test %edx, SR_T --> die |
541 |
|
542 |
mov %ebx, %eax |
543 |
mov %ebp, %edx |
544 |
shr %ebx, 12 |
545 |
mov %edi, %eax |
546 |
and %ebx, 0xffff |
547 |
shr %edi, 22 |
548 |
and %ebp, 0xffffff |
549 |
and %edi, 0x3f |
550 |
|
551 |
# now: |
552 |
# %eax = addr |
553 |
# %ebx = page_index |
554 |
# %ebp = VSID |
555 |
# %edi = api |
556 |
|
557 |
xor %ebx, %ebp |
558 |
|
559 |
# %ebx = hash1 |
560 |
|
561 |
push %eax |
562 |
push %ebx # das brauch ich |
563 |
|
564 |
and %ebx, [gCPU(pagetable_hashmask)] |
565 |
shl %ebx, 6 |
566 |
or %ebx, [gCPU(pagetable_base)] |
567 |
|
568 |
# %ebx = pteg_addr |
569 |
|
570 |
pg_table_lookup(0, 0, data, 0) |
571 |
pg_table_lookup(0, 0, data, 8) |
572 |
pg_table_lookup(0, 0, data, 16) |
573 |
pg_table_lookup(0, 0, data, 24) |
574 |
pg_table_lookup(0, 0, data, 32) |
575 |
pg_table_lookup(0, 0, data, 40) |
576 |
pg_table_lookup(0, 0, data, 48) |
577 |
pg_table_lookup(0, 0, data, 56) |
578 |
|
579 |
# hash function number 2 |
580 |
pop %ebx |
581 |
not %ebx |
582 |
and %ebx, [gCPU(pagetable_hashmask)] |
583 |
shl %ebx, 6 |
584 |
or %ebx, [gCPU(pagetable_base)] |
585 |
|
586 |
pg_table_lookup(1<<6, 0, data, 0) |
587 |
pg_table_lookup(1<<6, 0, data, 8) |
588 |
pg_table_lookup(1<<6, 0, data, 16) |
589 |
pg_table_lookup(1<<6, 0, data, 24) |
590 |
pg_table_lookup(1<<6, 0, data, 32) |
591 |
pg_table_lookup(1<<6, 0, data, 40) |
592 |
pg_table_lookup(1<<6, 0, data, 48) |
593 |
pg_table_lookup(1<<6, 0, data, 56) |
594 |
|
595 |
# page lookup failed --> throw exception |
596 |
|
597 |
pop %eax |
598 |
pop %edx # return address is no longer needed |
599 |
pop %ecx # bytes to roll back |
600 |
add %esp, %ecx |
601 |
|
602 |
mov %ecx, (1<<30) # PPC_EXC_DSISR_PAGE |
603 |
jmp EXTERN(ppc_dsi_exception_asm) |
604 |
|
605 |
.balign 16 |
606 |
ppc_effective_to_physical_data_write_ret: |
607 |
mov %edx, %eax |
608 |
mov %ecx, %eax |
609 |
shr %edx, 12 |
610 |
and %ecx, 0xfffff000 |
611 |
and %edx, TLB_ENTRIES-1 |
612 |
mov [gJITC(tlb_data_8_eff+%edx*4)], %ecx |
613 |
mov [gJITC(tlb_data_8_phys+%edx*4)], %ecx |
614 |
ret 4 |
615 |
|
616 |
.balign 16 |
617 |
############################################################################################## |
618 |
## uint32 FASTCALL ppc_effective_to_physical_data_write(uint32 addr) |
619 |
## |
620 |
## IN %eax: address to translate |
621 |
## |
622 |
## WILL NOT RETURN ON EXCEPTION! |
623 |
## |
624 |
ppc_effective_to_physical_data_write: |
625 |
tlb_lookup(8, data) |
626 |
|
627 |
test byte ptr [gCPU(msr)], (1<<4) # MSR_DR |
628 |
jz ppc_effective_to_physical_data_write_ret |
629 |
|
630 |
bat_lookup(d, 0, 8, data) |
631 |
bat_lookup(d, 1, 8, data) |
632 |
bat_lookup(d, 2, 8, data) |
633 |
bat_lookup(d, 3, 8, data) |
634 |
|
635 |
mov %ebx, %eax |
636 |
shr %eax, 28 # SR |
637 |
mov %edx, [gCPU(sr+4*%eax)] |
638 |
|
639 |
# test %edx, SR_T --> die |
640 |
|
641 |
mov %eax, %ebx |
642 |
mov %edi, %ebx |
643 |
mov %ebp, %edx |
644 |
shr %ebx, 12 |
645 |
and %ebx, 0xffff |
646 |
shr %edi, 22 |
647 |
and %ebp, 0xffffff |
648 |
and %edi, 0x3f |
649 |
|
650 |
# now: |
651 |
# %eax = addr |
652 |
# %ebx = page_index |
653 |
# %ebp = VSID |
654 |
# %edi = api |
655 |
|
656 |
xor %ebx, %ebp |
657 |
|
658 |
# %ebx = hash1 |
659 |
|
660 |
push %eax |
661 |
push %ebx # das brauch ich |
662 |
|
663 |
and %ebx, [gCPU(pagetable_hashmask)] |
664 |
shl %ebx, 6 |
665 |
or %ebx, [gCPU(pagetable_base)] |
666 |
|
667 |
# %ebx = pteg_addr |
668 |
|
669 |
pg_table_lookup(0, 8, data, 0) |
670 |
pg_table_lookup(0, 8, data, 8) |
671 |
pg_table_lookup(0, 8, data, 16) |
672 |
pg_table_lookup(0, 8, data, 24) |
673 |
pg_table_lookup(0, 8, data, 32) |
674 |
pg_table_lookup(0, 8, data, 40) |
675 |
pg_table_lookup(0, 8, data, 48) |
676 |
pg_table_lookup(0, 8, data, 56) |
677 |
|
678 |
# hash function number 2 |
679 |
mov %ebx, [%esp] |
680 |
add %esp, 4 |
681 |
not %ebx |
682 |
and %ebx, [gCPU(pagetable_hashmask)] |
683 |
shl %ebx, 6 |
684 |
or %ebx, [gCPU(pagetable_base)] |
685 |
|
686 |
pg_table_lookup(1<<6, 8, data, 0) |
687 |
pg_table_lookup(1<<6, 8, data, 8) |
688 |
pg_table_lookup(1<<6, 8, data, 16) |
689 |
pg_table_lookup(1<<6, 8, data, 24) |
690 |
pg_table_lookup(1<<6, 8, data, 32) |
691 |
pg_table_lookup(1<<6, 8, data, 40) |
692 |
pg_table_lookup(1<<6, 8, data, 48) |
693 |
pg_table_lookup(1<<6, 8, data, 56) |
694 |
|
695 |
# page lookup failed --> throw exception |
696 |
|
697 |
pop %eax |
698 |
pop %edx # return address is no longer needed |
699 |
pop %ebx # bytes to roll back |
700 |
add %esp, %ebx |
701 |
|
702 |
mov %ecx, (1<<30)|(1<<25) # PPC_EXC_DSISR_PAGE | PPC_EXC_DSISR_STORE |
703 |
jmp EXTERN(ppc_dsi_exception_asm) |
704 |
|
705 |
.balign 16 |
706 |
############################################################################################## |
707 |
## uint32 FASTCALL ppc_effective_write_byte() |
708 |
## |
709 |
## IN %eax: address to translate |
710 |
## %esi: current client pc offset |
711 |
## %dl: byte to be written |
712 |
## |
713 |
## WILL NOT RETURN ON EXCEPTION! |
714 |
## |
715 |
EXPORT(ppc_write_effective_byte_asm): |
716 |
mov [gCPU(pc_ofs)], %esi |
717 |
|
718 |
push %edx |
719 |
push 8 # roll back 8 bytes in case of exception |
720 |
call ppc_effective_to_physical_data_write |
721 |
cmp %eax, [EXTERN(gMemorySize)] |
722 |
pop %edx |
723 |
jae 1f |
724 |
add %eax, [EXTERN(gMemory)] |
725 |
mov [%eax], %dl |
726 |
ret |
727 |
1: |
728 |
mov %ecx, 1 |
729 |
movzx %edx, %dl |
730 |
jmp EXTERN(io_mem_write_glue) |
731 |
|
732 |
.balign 16 |
733 |
############################################################################################## |
734 |
## uint32 FASTCALL ppc_effective_write_half() |
735 |
## |
736 |
## IN %eax: address to translate |
737 |
## %dx: half to be written |
738 |
## %esi: current client pc offset |
739 |
## |
740 |
## WILL NOT RETURN ON EXCEPTION! |
741 |
## |
742 |
EXPORT(ppc_write_effective_half_asm): |
743 |
mov [gCPU(pc_ofs)], %esi |
744 |
mov %ebx, %eax |
745 |
and %ebx, 0xfff |
746 |
cmp %ebx, 4095 |
747 |
jae 1f |
748 |
|
749 |
push %edx |
750 |
push 8 # roll back 8 bytes in case of exception |
751 |
call ppc_effective_to_physical_data_write |
752 |
cmp %eax, [EXTERN(gMemorySize)] |
753 |
pop %edx |
754 |
jae 2f |
755 |
add %eax, [EXTERN(gMemory)] |
756 |
mov [%eax], %dh |
757 |
mov [%eax+1], %dl |
758 |
ret |
759 |
2: |
760 |
xchg %dh, %dl |
761 |
mov %ecx, 2 |
762 |
movzx %edx, %dx |
763 |
jmp EXTERN(io_mem_write_glue) |
764 |
|
765 |
1: |
766 |
push %edx |
767 |
push %eax |
768 |
push 12 # roll back 12 bytes in case of exception |
769 |
call ppc_effective_to_physical_data_write |
770 |
mov %ebx, %eax |
771 |
pop %eax |
772 |
push %ebx |
773 |
inc %eax |
774 |
push 12 # roll back 12 bytes in case of exception |
775 |
call ppc_effective_to_physical_data_write |
776 |
pop %ebx |
777 |
pop %edx |
778 |
cmp %ebx, [EXTERN(gMemorySize)] |
779 |
jae 1f |
780 |
add %ebx, [EXTERN(gMemory)] |
781 |
mov [%ebx], %dh |
782 |
3: |
783 |
cmp %eax, [EXTERN(gMemorySize)] |
784 |
jae 2f |
785 |
add %eax, [EXTERN(gMemory)] |
786 |
mov [%eax], %dl |
787 |
ret |
788 |
|
789 |
1: |
790 |
push %eax |
791 |
push %edx |
792 |
movzx %edx, %dh |
793 |
mov %eax, %ebx |
794 |
mov %ecx, 1 |
795 |
call EXTERN(io_mem_write_glue) |
796 |
pop %edx |
797 |
pop %eax |
798 |
jmp 3b |
799 |
2: |
800 |
movzx %edx, %dl |
801 |
mov %ecx, 1 |
802 |
jmp EXTERN(io_mem_write_glue) |
803 |
|
804 |
.balign 16 |
805 |
############################################################################################## |
806 |
## uint32 FASTCALL ppc_effective_write_word() |
807 |
## |
808 |
## IN %eax: address to translate |
809 |
## %edx: word to be written |
810 |
## %esi: current client pc offset |
811 |
## |
812 |
## WILL NOT RETURN ON EXCEPTION! |
813 |
## |
814 |
EXPORT(ppc_write_effective_word_asm): |
815 |
mov [gCPU(pc_ofs)], %esi |
816 |
mov %ebx, %eax |
817 |
and %ebx, 0xfff |
818 |
cmp %ebx, 4093 |
819 |
jae 1f |
820 |
|
821 |
bswap %edx |
822 |
|
823 |
push %edx |
824 |
push 8 # roll back 8 bytes in case of exception |
825 |
call ppc_effective_to_physical_data_write |
826 |
cmp %eax, [EXTERN(gMemorySize)] |
827 |
pop %edx |
828 |
jae 2f |
829 |
add %eax, [EXTERN(gMemory)] |
830 |
mov [%eax], %edx |
831 |
ret |
832 |
|
833 |
2: |
834 |
mov %ecx, 4 |
835 |
jmp EXTERN(io_mem_write_glue) |
836 |
|
837 |
1: |
838 |
push %edx |
839 |
push %eax |
840 |
push 12 # roll back 12 bytes in case of exception |
841 |
call ppc_effective_to_physical_data_write |
842 |
mov %ebx, %eax |
843 |
pop %eax |
844 |
add %eax, 4 |
845 |
push %ebx |
846 |
push 12 # roll back 12 bytes in case of exception |
847 |
call ppc_effective_to_physical_data_write |
848 |
pop %ebx |
849 |
pop %edx |
850 |
mov %ebp, %ebx |
851 |
and %ebp, 0xfff |
852 |
neg %ebp |
853 |
add %ebp, 4096 |
854 |
cmp %ebx, [EXTERN(gMemorySize)] |
855 |
jae 2f |
856 |
add %ebx, [EXTERN(gMemory)] |
857 |
1: |
858 |
rol %edx, 8 |
859 |
mov [%ebx], %dl |
860 |
inc %ebx |
861 |
dec %ebp |
862 |
jnz 1b |
863 |
4: |
864 |
mov %ebp, %eax |
865 |
and %eax, 0xfffff000 |
866 |
and %ebp, 0x00000fff |
867 |
cmp %eax, [EXTERN(gMemorySize)] |
868 |
jae 3f |
869 |
add %eax, [EXTERN(gMemory)] |
870 |
1: |
871 |
rol %edx, 8 |
872 |
mov [%eax], %dl |
873 |
inc %eax |
874 |
dec %ebp |
875 |
jnz 1b |
876 |
ret |
877 |
|
878 |
2: |
879 |
push %eax |
880 |
1: |
881 |
rol %edx, 8 |
882 |
push %ebp |
883 |
#push %ebx |
884 |
push %edx |
885 |
movzx %edx, %dl |
886 |
mov %eax, %ebx |
887 |
mov %ecx, 1 |
888 |
call EXTERN(io_mem_write_glue) |
889 |
pop %edx |
890 |
pop %ebp |
891 |
inc %ebx |
892 |
dec %ebp |
893 |
jnz 1b |
894 |
pop %eax |
895 |
jmp 4b |
896 |
3: |
897 |
1: |
898 |
rol %edx, 8 |
899 |
push %ebp |
900 |
push %eax |
901 |
push %edx |
902 |
movzx %edx, %dl |
903 |
mov %ecx, 1 |
904 |
call EXTERN(io_mem_write_glue) |
905 |
pop %edx |
906 |
pop %eax |
907 |
pop %ebp |
908 |
inc %eax |
909 |
dec %ebp |
910 |
jnz 1b |
911 |
ret |
912 |
.balign 16 |
913 |
############################################################################################## |
914 |
## uint32 FASTCALL ppc_effective_write_dword() |
915 |
## |
916 |
## IN %eax: address to translate |
917 |
## %ecx:%edx dword to be written |
918 |
## %esi: current client pc offset |
919 |
## |
920 |
## WILL NOT RETURN ON EXCEPTION! |
921 |
## |
922 |
EXPORT(ppc_write_effective_dword_asm): |
923 |
mov [gCPU(pc_ofs)], %esi |
924 |
mov %ebx, %eax |
925 |
and %ebx, 0xfff |
926 |
cmp %ebx, 4089 |
927 |
jae 2f # overlap |
928 |
|
929 |
bswap %ecx |
930 |
bswap %edx |
931 |
|
932 |
push %ecx |
933 |
push %edx |
934 |
push 12 # roll back 12 bytes in case of exception |
935 |
call ppc_effective_to_physical_data_write |
936 |
cmp %eax, [EXTERN(gMemorySize)] |
937 |
pop %edx |
938 |
pop %ecx |
939 |
jae 1f |
940 |
add %eax, [EXTERN(gMemory)] |
941 |
mov [%eax], %ecx |
942 |
mov [%eax+4], %edx |
943 |
ret |
944 |
1: |
945 |
mov %ebx, %ecx |
946 |
mov %ecx, %edx |
947 |
mov %edx, %ebx |
948 |
jmp EXTERN(io_mem_write64_glue) |
949 |
|
950 |
2: |
951 |
push %ecx |
952 |
push %edx |
953 |
push %eax |
954 |
push 16 # roll back 16 bytes in case of exception |
955 |
call ppc_effective_to_physical_data_write |
956 |
mov %ebx, %eax |
957 |
pop %eax |
958 |
add %eax, 8 |
959 |
push %ebx |
960 |
push 16 # roll back 16 bytes in case of exception |
961 |
call ppc_effective_to_physical_data_write |
962 |
pop %ebx |
963 |
pop %edx |
964 |
pop %ecx |
965 |
mov %ebp, %ebx |
966 |
and %ebp, 0xfff |
967 |
neg %ebp |
968 |
add %ebp, 4096 |
969 |
bswap %ecx |
970 |
bswap %edx |
971 |
cmp %ebx, [EXTERN(gMemorySize)] |
972 |
jae 3f |
973 |
add %ebx, [EXTERN(gMemory)] |
974 |
1: |
975 |
mov [%ebx], %cl |
976 |
shrd %ecx, %edx, 8 |
977 |
inc %ebx |
978 |
shr %edx, 8 |
979 |
dec %ebp |
980 |
jnz 1b |
981 |
4: |
982 |
mov %ebp, %eax |
983 |
and %eax, 0xfffff000 |
984 |
and %ebp, 0x00000fff |
985 |
cmp %eax, [EXTERN(gMemorySize)] |
986 |
jae 5f |
987 |
add %eax, [EXTERN(gMemory)] |
988 |
1: |
989 |
mov [%eax], %cl |
990 |
shrd %ecx, %edx, 8 |
991 |
inc %eax |
992 |
shr %edx, 8 |
993 |
dec %ebp |
994 |
jnz 1b |
995 |
ret |
996 |
3: |
997 |
1: |
998 |
pusha |
999 |
movzx %edx, %cl |
1000 |
mov %eax, %ebx |
1001 |
mov %ecx, 1 |
1002 |
call EXTERN(io_mem_write_glue) |
1003 |
popa |
1004 |
shrd %ecx, %edx, 8 |
1005 |
inc %ebx |
1006 |
shr %edx, 8 |
1007 |
dec %ebp |
1008 |
jnz 1b |
1009 |
jmp 4b |
1010 |
5: |
1011 |
1: |
1012 |
pusha |
1013 |
movzx %edx, %cl |
1014 |
mov %ecx, 1 |
1015 |
call EXTERN(io_mem_write_glue) |
1016 |
popa |
1017 |
shrd %ecx, %edx, 8 |
1018 |
inc %eax |
1019 |
shr %edx, 8 |
1020 |
dec %ebp |
1021 |
jnz 1b |
1022 |
ret |
1023 |
.balign 16 |
1024 |
############################################################################################## |
1025 |
## uint32 FASTCALL ppc_effective_write_qword() |
1026 |
## |
1027 |
## IN %eax: address to translate |
1028 |
## %edx: address from which to get the values to be written |
1029 |
## %esi: current client pc offset |
1030 |
## |
1031 |
## WILL NOT RETURN ON EXCEPTION! |
1032 |
## |
1033 |
EXPORT(ppc_write_effective_qword_asm): |
1034 |
mov [gCPU(pc_ofs)], %esi |
1035 |
and %eax, 0xfffffff0 |
1036 |
push %edx |
1037 |
|
1038 |
push 8 # roll back 8 bytes in case of exception |
1039 |
call ppc_effective_to_physical_data_write |
1040 |
|
1041 |
cmp %eax, [EXTERN(gMemorySize)] |
1042 |
pop %edx |
1043 |
jae 1f |
1044 |
|
1045 |
add %eax, [EXTERN(gMemory)] |
1046 |
|
1047 |
mov %ebx, [%edx] |
1048 |
mov %ecx, [%edx+4] |
1049 |
mov %edi, [%edx+8] |
1050 |
mov %esi, [%edx+12] |
1051 |
|
1052 |
bswap %ebx |
1053 |
bswap %ecx |
1054 |
bswap %edi |
1055 |
bswap %esi |
1056 |
|
1057 |
mov [%eax+12], %ebx |
1058 |
mov [%eax+8], %ecx |
1059 |
mov [%eax+4], %edi |
1060 |
mov [%eax], %esi |
1061 |
ret |
1062 |
1: |
1063 |
call EXTERN(io_mem_write128_glue) |
1064 |
ret |
1065 |
|
1066 |
ppc_write_effective_qword_sse_asm: |
1067 |
mov [gCPU(pc_ofs)], %esi |
1068 |
and %eax, 0xfffffff0 |
1069 |
push %edx |
1070 |
|
1071 |
push 8 # roll back 8 bytes in case of exception |
1072 |
call ppc_effective_to_physical_data_write |
1073 |
|
1074 |
cmp %eax, [EXTERN(gMemorySize)] |
1075 |
pop %edx |
1076 |
jae 1f |
1077 |
|
1078 |
add %eax, [EXTERN(gMemory)] |
1079 |
|
1080 |
movaps [%eax], %xmm0 |
1081 |
ret |
1082 |
1: |
1083 |
movaps [%edx], %xmm0 |
1084 |
call EXTERN(io_mem_write128_native_glue) |
1085 |
ret |
1086 |
.balign 16 |
1087 |
############################################################################################## |
1088 |
## uint32 FASTCALL ppc_read_effective_byte() |
1089 |
## |
1090 |
## IN %eax: address to translate |
1091 |
## %esi: current client pc offset |
1092 |
## |
1093 |
## OUT %edx: byte, zero extended |
1094 |
## |
1095 |
## WILL NOT RETURN ON EXCEPTION! |
1096 |
## |
1097 |
EXPORT(ppc_read_effective_byte_asm): |
1098 |
mov [gCPU(pc_ofs)], %esi |
1099 |
|
1100 |
push 4 # roll back 4 bytes in case of exception |
1101 |
call ppc_effective_to_physical_data_read |
1102 |
cmp %eax, [EXTERN(gMemorySize)] |
1103 |
jae 1f |
1104 |
add %eax, [EXTERN(gMemory)] |
1105 |
movzx %edx, byte ptr [%eax] |
1106 |
ret |
1107 |
1: |
1108 |
mov %edx, 1 |
1109 |
call EXTERN(io_mem_read_glue) |
1110 |
movzx %edx, %al |
1111 |
ret |
1112 |
|
1113 |
.balign 16 |
1114 |
############################################################################################## |
1115 |
## uint32 FASTCALL ppc_read_effective_half() |
1116 |
## |
1117 |
## IN %eax: address to translate |
1118 |
## %esi: current client pc offset |
1119 |
## |
1120 |
## OUT %edx: half, zero extended |
1121 |
## |
1122 |
## WILL NOT RETURN ON EXCEPTION! |
1123 |
## |
1124 |
EXPORT(ppc_read_effective_half_z_asm): |
1125 |
mov [gCPU(pc_ofs)], %esi |
1126 |
mov %ebx, %eax |
1127 |
and %ebx, 0xfff |
1128 |
cmp %ebx, 4095 |
1129 |
jae 1f |
1130 |
|
1131 |
push 4 # roll back 4 bytes in case of exception |
1132 |
call ppc_effective_to_physical_data_read |
1133 |
cmp %eax, [EXTERN(gMemorySize)] |
1134 |
jae 2f |
1135 |
add %eax, [EXTERN(gMemory)] |
1136 |
movzx %edx, word ptr [%eax] |
1137 |
xchg %dl, %dh |
1138 |
ret |
1139 |
2: |
1140 |
mov %edx, 2 |
1141 |
call EXTERN(io_mem_read_glue) |
1142 |
xchg %al, %ah |
1143 |
movzx %edx, %ax |
1144 |
ret |
1145 |
|
1146 |
1: |
1147 |
push %eax |
1148 |
push 8 # roll back 8 bytes in case of exception |
1149 |
call ppc_effective_to_physical_data_read |
1150 |
xor %edx, %edx |
1151 |
cmp %eax, [EXTERN(gMemorySize)] |
1152 |
jae 2f |
1153 |
add %eax, [EXTERN(gMemory)] |
1154 |
mov %dh, [%eax] |
1155 |
1: |
1156 |
pop %eax |
1157 |
push %edx |
1158 |
inc %eax |
1159 |
push 8 # roll back 8 bytes in case of exception |
1160 |
call ppc_effective_to_physical_data_read |
1161 |
pop %edx |
1162 |
cmp %eax, [EXTERN(gMemorySize)] |
1163 |
jae 3f |
1164 |
add %eax, [EXTERN(gMemory)] |
1165 |
mov %dl, [%eax] |
1166 |
ret |
1167 |
|
1168 |
2: |
1169 |
pusha |
1170 |
mov %edx, 1 |
1171 |
call EXTERN(io_mem_read_glue) |
1172 |
mov [gCPU(temp2)], %al |
1173 |
popa |
1174 |
mov %dh, [gCPU(temp2)] |
1175 |
jmp 1b |
1176 |
3: |
1177 |
push %edx |
1178 |
mov %edx, 1 |
1179 |
call EXTERN(io_mem_read_glue) |
1180 |
pop %edx |
1181 |
mov %dl, %al |
1182 |
ret |
1183 |
.balign 16 |
1184 |
############################################################################################## |
1185 |
## uint32 FASTCALL ppc_read_effective_half() |
1186 |
## |
1187 |
## IN %eax: address to translate |
1188 |
## %esi: current client pc offset |
1189 |
## |
1190 |
## OUT %edx: half, sign extended |
1191 |
## |
1192 |
## WILL NOT RETURN ON EXCEPTION! |
1193 |
## |
1194 |
EXPORT(ppc_read_effective_half_s_asm): |
1195 |
mov [gCPU(pc_ofs)], %esi |
1196 |
mov %ebx, %eax |
1197 |
and %ebx, 0xfff |
1198 |
cmp %ebx, 4095 |
1199 |
jae 1f |
1200 |
|
1201 |
push 4 # roll back 4 bytes in case of exception |
1202 |
call ppc_effective_to_physical_data_read |
1203 |
cmp %eax, [EXTERN(gMemorySize)] |
1204 |
jae 2f |
1205 |
add %eax, [EXTERN(gMemory)] |
1206 |
mov %cx, [%eax] |
1207 |
xchg %ch, %cl |
1208 |
movsx %edx, %cx |
1209 |
ret |
1210 |
2: |
1211 |
mov %edx, 2 |
1212 |
call EXTERN(io_mem_read_glue) |
1213 |
xchg %ah, %al |
1214 |
movsx %edx, %ax |
1215 |
ret |
1216 |
|
1217 |
1: |
1218 |
push %eax |
1219 |
push 8 # roll back 8 bytes in case of exception |
1220 |
call ppc_effective_to_physical_data_read |
1221 |
cmp %eax, [EXTERN(gMemorySize)] |
1222 |
jae 2f |
1223 |
add %eax, [EXTERN(gMemory)] |
1224 |
mov %ch, [%eax] |
1225 |
1: |
1226 |
pop %eax |
1227 |
push %ecx |
1228 |
inc %eax |
1229 |
push 8 # roll back 8 bytes in case of exception |
1230 |
call ppc_effective_to_physical_data_read |
1231 |
pop %ecx |
1232 |
cmp %eax, [EXTERN(gMemorySize)] |
1233 |
jae 3f |
1234 |
add %eax, [EXTERN(gMemory)] |
1235 |
mov %cl, [%eax] |
1236 |
movsx %edx, %cx |
1237 |
ret |
1238 |
|
1239 |
2: |
1240 |
pusha |
1241 |
mov %edx, 1 |
1242 |
call EXTERN(io_mem_read_glue) |
1243 |
mov [gCPU(temp2)], %al |
1244 |
popa |
1245 |
mov %ch, [gCPU(temp2)] |
1246 |
jmp 1b |
1247 |
3: |
1248 |
push %ecx |
1249 |
mov %edx, 1 |
1250 |
call EXTERN(io_mem_read_glue) |
1251 |
pop %ecx |
1252 |
mov %cl, %al |
1253 |
movsx %edx, %cx |
1254 |
ret |
1255 |
|
1256 |
.balign 16 |
1257 |
############################################################################################## |
1258 |
## uint32 FASTCALL ppc_read_effective_word() |
1259 |
## |
1260 |
## IN %eax: address to translate |
1261 |
## %esi: current client pc offset |
1262 |
## |
1263 |
## OUT %edx: word |
1264 |
## |
1265 |
## WILL NOT RETURN ON EXCEPTION! |
1266 |
## |
1267 |
EXPORT(ppc_read_effective_word_asm): |
1268 |
mov [gCPU(pc_ofs)], %esi |
1269 |
mov %ebx, %eax |
1270 |
and %ebx, 0xfff |
1271 |
cmp %ebx, 4093 |
1272 |
jae 1f |
1273 |
|
1274 |
push 4 # roll back 4 bytes in case of exception |
1275 |
call ppc_effective_to_physical_data_read |
1276 |
cmp %eax, [EXTERN(gMemorySize)] |
1277 |
jae 2f |
1278 |
add %eax, [EXTERN(gMemory)] |
1279 |
mov %edx, [%eax] |
1280 |
bswap %edx |
1281 |
ret |
1282 |
2: |
1283 |
mov %edx, 4 |
1284 |
call EXTERN(io_mem_read_glue) |
1285 |
mov %edx, %eax |
1286 |
bswap %edx |
1287 |
ret |
1288 |
1: |
1289 |
push %eax |
1290 |
push %ebx |
1291 |
push 12 # roll back 12 bytes in case of exception |
1292 |
call ppc_effective_to_physical_data_read |
1293 |
pop %ebx |
1294 |
mov %ecx, 4096 |
1295 |
sub %ecx, %ebx |
1296 |
cmp %eax, [EXTERN(gMemorySize)] |
1297 |
jae 2f |
1298 |
add %eax, [EXTERN(gMemory)] |
1299 |
1: |
1300 |
shl %edx, 8 |
1301 |
mov %dl, [%eax] |
1302 |
inc %eax |
1303 |
dec %ecx |
1304 |
jnz 1b |
1305 |
4: |
1306 |
pop %eax |
1307 |
push %edx |
1308 |
add %eax, 4 |
1309 |
push %ebx |
1310 |
and %eax, 0xfffff000 |
1311 |
push 12 # roll back 12 bytes in case of exception |
1312 |
call ppc_effective_to_physical_data_read |
1313 |
pop %ebx |
1314 |
pop %edx |
1315 |
sub %ebx, 4092 |
1316 |
cmp %eax, [EXTERN(gMemorySize)] |
1317 |
jae 3f |
1318 |
add %eax, [EXTERN(gMemory)] |
1319 |
1: |
1320 |
shl %edx, 8 |
1321 |
mov %dl, [%eax] |
1322 |
inc %eax |
1323 |
dec %ebx |
1324 |
jnz 1b |
1325 |
ret |
1326 |
|
1327 |
2: |
1328 |
1: |
1329 |
shl %edx, 8 |
1330 |
pusha |
1331 |
mov %edx, 1 |
1332 |
call EXTERN(io_mem_read_glue) |
1333 |
mov [gCPU(temp2)], %al |
1334 |
popa |
1335 |
mov %dl, [gCPU(temp2)] |
1336 |
inc %eax |
1337 |
dec %ecx |
1338 |
jnz 1b |
1339 |
jmp 4b |
1340 |
3: |
1341 |
1: |
1342 |
shl %edx, 8 |
1343 |
pusha |
1344 |
mov %edx, 1 |
1345 |
call EXTERN(io_mem_read_glue) |
1346 |
mov [gCPU(temp2)], %al |
1347 |
popa |
1348 |
mov %dl, [gCPU(temp2)] |
1349 |
inc %eax |
1350 |
dec %ebx |
1351 |
jnz 1b |
1352 |
ret |
1353 |
.balign 16 |
1354 |
############################################################################################## |
1355 |
## uint32 FASTCALL ppc_read_effective_dword() |
1356 |
## |
1357 |
## IN %eax: address to translate |
1358 |
## %esi: current client pc offset |
1359 |
## |
1360 |
## OUT %ecx:%edx dword |
1361 |
## |
1362 |
## WILL NOT RETURN ON EXCEPTION! |
1363 |
## |
1364 |
EXPORT(ppc_read_effective_dword_asm): |
1365 |
mov [gCPU(pc_ofs)], %esi |
1366 |
mov %ebx, %eax |
1367 |
and %ebx, 0xfff |
1368 |
cmp %ebx, 4089 |
1369 |
jae 1f |
1370 |
|
1371 |
push 4 # roll back 4 bytes in case of exception |
1372 |
call ppc_effective_to_physical_data_read |
1373 |
cmp %eax, [EXTERN(gMemorySize)] |
1374 |
jae 2f |
1375 |
add %eax, [EXTERN(gMemory)] |
1376 |
mov %ecx, [%eax] |
1377 |
mov %edx, [%eax+4] |
1378 |
bswap %ecx |
1379 |
bswap %edx |
1380 |
ret |
1381 |
2: |
1382 |
call EXTERN(io_mem_read64_glue) |
1383 |
mov %ecx, %eax |
1384 |
mov %edx, %edx |
1385 |
bswap %ecx |
1386 |
bswap %edx |
1387 |
ret |
1388 |
|
1389 |
1: |
1390 |
push %eax |
1391 |
push %ebx |
1392 |
push 12 # roll back 12 bytes in case of exception |
1393 |
call ppc_effective_to_physical_data_read |
1394 |
pop %ebx |
1395 |
mov %ebp, 4096 |
1396 |
sub %ebp, %ebx |
1397 |
cmp %eax, [EXTERN(gMemorySize)] |
1398 |
jae 2f |
1399 |
add %eax, [EXTERN(gMemory)] |
1400 |
1: |
1401 |
shld %ecx, %edx, 8 |
1402 |
shl %edx, 8 |
1403 |
mov %dl, [%eax] |
1404 |
inc %eax |
1405 |
dec %ebp |
1406 |
jnz 1b |
1407 |
4: |
1408 |
pop %eax |
1409 |
push %ecx |
1410 |
push %edx |
1411 |
add %eax, 8 |
1412 |
push %ebx |
1413 |
and %eax, 0xfffff000 |
1414 |
push 16 # roll back 16 bytes in case of exception |
1415 |
call ppc_effective_to_physical_data_read |
1416 |
pop %ebx |
1417 |
pop %edx |
1418 |
pop %ecx |
1419 |
sub %ebx, 4088 |
1420 |
cmp %eax, [EXTERN(gMemorySize)] |
1421 |
jae 3f |
1422 |
add %eax, [EXTERN(gMemory)] |
1423 |
1: |
1424 |
shld %ecx, %edx, 8 |
1425 |
shl %edx, 8 |
1426 |
mov %dl, [%eax] |
1427 |
inc %eax |
1428 |
dec %ebx |
1429 |
jnz 1b |
1430 |
ret |
1431 |
|
1432 |
2: |
1433 |
1: |
1434 |
shld %ecx, %edx, 8 |
1435 |
shl %edx, 8 |
1436 |
pusha |
1437 |
mov %edx, 1 |
1438 |
call EXTERN(io_mem_read_glue) |
1439 |
mov [gCPU(temp2)], %al |
1440 |
popa |
1441 |
mov %dl, [gCPU(temp2)] |
1442 |
inc %eax |
1443 |
dec %ebp |
1444 |
jnz 1b |
1445 |
jmp 4b |
1446 |
3: |
1447 |
1: |
1448 |
shld %ecx, %edx, 8 |
1449 |
shl %edx, 8 |
1450 |
pusha |
1451 |
mov %edx, 1 |
1452 |
call EXTERN(io_mem_read_glue) |
1453 |
mov [gCPU(temp2)], %al |
1454 |
popa |
1455 |
mov %dl, [gCPU(temp2)] |
1456 |
inc %eax |
1457 |
dec %ebx |
1458 |
jnz 1b |
1459 |
ret |
1460 |
.balign 16 |
1461 |
############################################################################################## |
1462 |
## uint32 FASTCALL ppc_read_effective_qword() |
1463 |
## |
1464 |
## IN %eax: address to translate |
1465 |
## %edx: address to store the qword |
1466 |
## %esi: current client pc offset |
1467 |
## |
1468 |
## WILL NOT RETURN ON EXCEPTION! |
1469 |
## |
1470 |
EXPORT(ppc_read_effective_qword_asm): |
1471 |
mov [gCPU(pc_ofs)], %esi |
1472 |
and %eax, 0xfffffff0 |
1473 |
push %edx |
1474 |
|
1475 |
push 8 # roll back 8 bytes in case of exception |
1476 |
call ppc_effective_to_physical_data_read |
1477 |
|
1478 |
cmp %eax, [EXTERN(gMemorySize)] |
1479 |
pop %edx |
1480 |
jae 1f |
1481 |
|
1482 |
add %eax, [EXTERN(gMemory)] |
1483 |
|
1484 |
mov %ebx, [%eax] |
1485 |
mov %ecx, [%eax+4] |
1486 |
mov %edi, [%eax+8] |
1487 |
mov %esi, [%eax+12] |
1488 |
|
1489 |
bswap %ebx |
1490 |
bswap %ecx |
1491 |
bswap %edi |
1492 |
bswap %esi |
1493 |
|
1494 |
mov [%edx+12], %ebx |
1495 |
mov [%edx+8], %ecx |
1496 |
mov [%edx+4], %edi |
1497 |
mov [%edx], %esi |
1498 |
ret |
1499 |
1: |
1500 |
call EXTERN(io_mem_read128_glue) |
1501 |
ret |
1502 |
|
1503 |
EXPORT(ppc_read_effective_qword_sse_asm): |
1504 |
mov [gCPU(pc_ofs)], %esi |
1505 |
and %eax, 0xfffffff0 |
1506 |
push %edx |
1507 |
|
1508 |
push 8 # roll back 8 bytes in case of exception |
1509 |
call ppc_effective_to_physical_data_read |
1510 |
|
1511 |
cmp %eax, [EXTERN(gMemorySize)] |
1512 |
pop %edx |
1513 |
jae 1f |
1514 |
|
1515 |
add %eax, [EXTERN(gMemory)] |
1516 |
|
1517 |
movaps %xmm0, [%eax] |
1518 |
|
1519 |
mov %ebx, [%eax] |
1520 |
mov %ecx, [%eax+4] |
1521 |
mov %edi, [%eax+8] |
1522 |
mov %esi, [%eax+12] |
1523 |
|
1524 |
bswap %ebx |
1525 |
bswap %ecx |
1526 |
bswap %edi |
1527 |
bswap %esi |
1528 |
|
1529 |
mov [%edx+12], %ebx |
1530 |
mov [%edx+8], %ecx |
1531 |
mov [%edx+4], %edi |
1532 |
mov [%edx], %esi |
1533 |
ret |
1534 |
|
1535 |
1: |
1536 |
push %edx |
1537 |
call EXTERN(io_mem_read128_native_glue) |
1538 |
pop %edx |
1539 |
|
1540 |
movaps %xmm0, [%edx] |
1541 |
|
1542 |
mov %eax, [%edx] |
1543 |
mov %ebx, [%edx+4] |
1544 |
mov %edi, [%edx+8] |
1545 |
mov %esi, [%edx+12] |
1546 |
|
1547 |
bswap %eax |
1548 |
bswap %ebx |
1549 |
bswap %edi |
1550 |
bswap %esi |
1551 |
|
1552 |
mov [%edx+12], %esi |
1553 |
mov [%edx+8], %edi |
1554 |
mov [%edx+4], %ebx |
1555 |
mov [%edx], %eax |
1556 |
ret |
1557 |
|
1558 |
.balign 16 |
1559 |
############################################################################################## |
1560 |
## uint32 FASTCALL ppc_opc_stswi_asm() |
1561 |
## |
1562 |
## IN %ecx: NB |
1563 |
## %ebx: source |
1564 |
## %eax: dest |
1565 |
## %esi: current client pc offset |
1566 |
## |
1567 |
## WILL NOT RETURN ON EXCEPTION! |
1568 |
## |
1569 |
EXPORT(ppc_opc_stswi_asm): |
1570 |
mov [gCPU(pc_ofs)], %esi |
1571 |
mov %edi, 1 |
1572 |
|
1573 |
1: |
1574 |
dec %edi |
1575 |
jnz 2f |
1576 |
mov %edx, [gCPU(gpr+4*%ebx)] |
1577 |
inc %ebx |
1578 |
mov %edi, 4 |
1579 |
and %ebx, 0x1f |
1580 |
2: |
1581 |
push %eax |
1582 |
push %ecx |
1583 |
push %ebx |
1584 |
push %edi |
1585 |
push %edx |
1586 |
push 24 # roll back 24 bytes in case of exception |
1587 |
call ppc_effective_to_physical_data_write |
1588 |
cmp %eax, [EXTERN(gMemorySize)] |
1589 |
pop %edx |
1590 |
mov %ecx, %edx |
1591 |
jae 3f |
1592 |
shr %ecx, 24 |
1593 |
add %eax, [EXTERN(gMemory)] |
1594 |
mov [%eax], %cl |
1595 |
4: |
1596 |
pop %edi |
1597 |
pop %ebx |
1598 |
pop %ecx |
1599 |
pop %eax |
1600 |
shl %edx, 8 |
1601 |
inc %eax |
1602 |
dec %ecx |
1603 |
jnz 1b |
1604 |
ret |
1605 |
|
1606 |
3: |
1607 |
push %edx |
1608 |
mov %ecx, 1 |
1609 |
shr %edx, 24 |
1610 |
call EXTERN(io_mem_write_glue) |
1611 |
pop %edx |
1612 |
jmp 4b |
1613 |
.balign 16 |
1614 |
############################################################################################## |
1615 |
## uint32 FASTCALL ppc_opc_lswi_asm() |
1616 |
## |
1617 |
## IN %ecx: NB |
1618 |
## %ebx: dest |
1619 |
## %eax: source |
1620 |
## %esi: current client pc offset |
1621 |
## |
1622 |
## WILL NOT RETURN ON EXCEPTION! |
1623 |
## |
1624 |
EXPORT(ppc_opc_lswi_asm): |
1625 |
mov [gCPU(pc_ofs)], %esi |
1626 |
mov %edi, 4 |
1627 |
1: |
1628 |
or %edi, %edi |
1629 |
jnz 2f |
1630 |
mov [gCPU(gpr+4*%ebx)], %edx |
1631 |
inc %ebx |
1632 |
mov %edi, 4 |
1633 |
and %ebx, 0x1f |
1634 |
xor %edx, %edx |
1635 |
2: |
1636 |
|
1637 |
push %eax |
1638 |
push %ecx |
1639 |
push %ebx |
1640 |
push %edi |
1641 |
push %edx |
1642 |
push 24 # roll back 24 bytes in case of exception |
1643 |
call ppc_effective_to_physical_data_read |
1644 |
pop %edx |
1645 |
cmp %eax, [EXTERN(gMemorySize)] |
1646 |
jae 3f |
1647 |
add %eax, [EXTERN(gMemory)] |
1648 |
shl %edx, 8 |
1649 |
mov %dl, byte ptr [%eax] |
1650 |
4: |
1651 |
pop %edi |
1652 |
pop %ebx |
1653 |
pop %ecx |
1654 |
pop %eax |
1655 |
|
1656 |
dec %edi |
1657 |
inc %eax |
1658 |
dec %ecx |
1659 |
jnz 1b |
1660 |
|
1661 |
or %edi, %edi |
1662 |
jz 5f |
1663 |
2: |
1664 |
shl %edx, 8 |
1665 |
dec %edi |
1666 |
jnz 2b |
1667 |
|
1668 |
5: |
1669 |
mov [gCPU(gpr)+4*%ebx], %edx |
1670 |
ret |
1671 |
|
1672 |
3: |
1673 |
push %edx |
1674 |
mov %edx, 1 |
1675 |
call EXTERN(io_mem_read_glue) |
1676 |
pop %edx |
1677 |
shl %edx, 8 |
1678 |
mov %dl, %al |
1679 |
jmp 4b |
1680 |
|
1681 |
.balign 16 |
1682 |
############################################################################################## |
1683 |
## uint32 FASTCALL ppc_opc_icbi_asm() |
1684 |
## |
1685 |
## IN %eax: effective address |
1686 |
EXPORT(ppc_opc_icbi_asm): |
1687 |
mov [gCPU(pc_ofs)], %esi |
1688 |
push 4 # roll back 4 bytes in case of exception |
1689 |
add %eax, 1 # FIXME: WTF??? |
1690 |
call ppc_effective_to_physical_data_read |
1691 |
cmp %eax, [EXTERN(gMemorySize)] |
1692 |
mov %ebp, [gJITC(clientPages)] |
1693 |
jae 1f |
1694 |
shr %eax, 12 |
1695 |
cmp dword ptr [%ebp+%eax*4], 0 |
1696 |
jnz 2f |
1697 |
1: |
1698 |
ret |
1699 |
|
1700 |
2: |
1701 |
mov %eax, [%ebp+%eax*4] |
1702 |
jmp EXTERN(jitcDestroyAndFreeClientPage) |