📄 ppc_mmu.c
字号:
} else { return PPC_MMU_FATAL; }}inline int FASTCALL ppc_write_physical_word(uint32 addr, uint32 data){ if (addr < boot_romSize) { // big endian *((uint32*)(boot_rom+addr)) = ppc_word_to_BE(data); return PPC_MMU_OK; } return io_mem_write(addr, ppc_bswap_word(data), 4);}inline int FASTCALL ppc_write_effective_qword(uint32 addr, Vector_t data){ uint32 p; int r; addr &= ~0x0f; if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, &p)))) { return ppc_write_physical_qword(p, &data); } return r;}inline int FASTCALL ppc_write_effective_dword(uint32 addr, uint64 data){ uint32 p; int r; if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, &p)))) { if (EA_Offset(addr) > 4088) { // write overlaps two pages.. tricky byte *r1, *r2; byte b[14]; ppc_effective_to_physical((addr & ~0xfff)+4089, PPC_MMU_WRITE, &p); if ((r = ppc_direct_physical_memory_handle(p, r1))) return r; if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_WRITE, &p))) return r; if ((r = ppc_direct_physical_memory_handle(p, r2))) return r; data = ppc_dword_to_BE(data); memmove(&b[0], r1, 7); memmove(&b[7], r2, 7); memmove(&b[EA_Offset(addr)-4089], &data, 8); memmove(r1, &b[0], 7); memmove(r2, &b[7], 7); return PPC_MMU_OK; } else { return ppc_write_physical_dword(p, data); } } return r;}/*************************************************************************** * DMA Interface */bool ppc_dma_write(uint32 dest, const void *src, uint32 size){ if (dest > boot_romSize || (dest+size) > boot_romSize) return false; byte *ptr; ppc_direct_physical_memory_handle(dest, ptr); memcpy(ptr, src, size); return true;}bool ppc_dma_read(void *dest, uint32 src, uint32 size){ if (src > boot_romSize || (src+size) > boot_romSize) return false; byte *ptr; ppc_direct_physical_memory_handle(src, ptr); memcpy(dest, ptr, size); return true;}bool ppc_dma_set(uint32 dest, int c, uint32 size){ if (dest > boot_romSize || (dest+size) > boot_romSize) return false; byte *ptr; ppc_direct_physical_memory_handle(dest, ptr); memset(ptr, c, size); return true;}/*************************************************************************** * DEPRECATED prom interface */bool ppc_prom_set_sdr1(uint32 newval, bool quiesce){ return ppc_mmu_set_sdr1(newval, quiesce);}bool ppc_prom_effective_to_physical(uint32 *result, uint32 ea){ return ppc_effective_to_physical(ea, PPC_MMU_READ|PPC_MMU_SV|PPC_MMU_NO_EXC, result) == PPC_MMU_OK;}bool ppc_prom_page_create(uint32 ea, uint32 pa){ uint32 sr = gCPU.sr[EA_SR(ea)]; uint32 page_index = EA_PageIndex(ea); // 16 bit uint32 VSID = SR_VSID(sr); // 24 bit uint32 api = EA_API(ea); // 6 bit (part of page_index) uint32 hash1 = (VSID ^ page_index); uint32 pte, pte2; uint32 h = 0; int j; for (j=0; j<2; j++) { uint32 pteg_addr = ((hash1 & gCPU.pagetable_hashmask)<<6) | gCPU.pagetable_base; int i; for (i=0; i<8; i++) { if (ppc_read_physical_word(pteg_addr, &pte)) { PPC_MMU_ERR("read physical in address translate failed\n"); return false; } if (!(pte & PTE1_V)) { // free pagetable entry found pte = PTE1_V | (VSID << 7) | h | api; pte2 = (PA_RPN(pa) << 12) | 0; if (ppc_write_physical_word(pteg_addr, pte) || ppc_write_physical_word(pteg_addr+4, pte2)) { return false; } else { // ok return true; } } pteg_addr+=8; } hash1 = ~hash1; h = PTE1_H; } return false;}bool ppc_prom_page_free(uint32 ea){ return true;}/*************************************************************************** * MMU Opcodes */#include "ppc_dec.h"/* * dcbz Data Cache Clear to Zero * .464 */void ppc_opc_dcbz(){#ifdef E500 //printf("DBG:In %s, for e500,cache is not implemented.\n",__FUNCTION__); //PPC_L1_CACHE_LINE_SIZE int rA, rD, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, rD, rA, rB); // assert rD=0 uint32 a = (rA?gCPU.gpr[rA]:0)+gCPU.gpr[rB]; // bytes of per Cache line is 32 bytes int i = 0; for(; i < 32; i += 4) ppc_write_effective_word(a + i, 0);#else //PPC_L1_CACHE_LINE_SIZE int rA, rD, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, rD, rA, rB); // assert rD=0 uint32 a = (rA?gCPU.gpr[rA]:0)+gCPU.gpr[rB]; // BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ppc_write_effective_dword(a, 0) || ppc_write_effective_dword(a+8, 0) || ppc_write_effective_dword(a+16, 0) || ppc_write_effective_dword(a+24, 0);#endif}void ppc_opc_dcbtls(){#ifdef E500 //printf("DBG:In %s, for e500,cache is not implemented.\n",__FUNCTION__);#else fprintf(stderr,"In %s, cache is not implemented.\n",__FUNCTION__);#endif}/* * lbz Load Byte and Zero * .521 */void ppc_opc_lbz(){ int rA, rD; uint32 imm; PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, rD, rA, imm); uint8 r; int ret = ppc_read_effective_byte((rA?gCPU.gpr[rA]:0)+imm, &r); if (ret == PPC_MMU_OK) { gCPU.gpr[rD] = r; }}/* * lbzu Load Byte and Zero with Update * .522 */void ppc_opc_lbzu(){ int rA, rD; uint32 imm; PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, rD, rA, imm); // FIXME: check rA!=0 && rA!=rD uint8 r; int ret = ppc_read_effective_byte(gCPU.gpr[rA]+imm, &r); if (ret == PPC_MMU_OK) { gCPU.gpr[rA] += imm; gCPU.gpr[rD] = r; } }/* * lbzux Load Byte and Zero with Update Indexed * .523 */void ppc_opc_lbzux(){ int rA, rD, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, rD, rA, rB); // FIXME: check rA!=0 && rA!=rD uint8 r; int ret = ppc_read_effective_byte(gCPU.gpr[rA]+gCPU.gpr[rB], &r); if (ret == PPC_MMU_OK) { gCPU.gpr[rA] += gCPU.gpr[rB]; gCPU.gpr[rD] = r; }}/* * lbzx Load Byte and Zero Indexed * .524 */void ppc_opc_lbzx(){ int rA, rD, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, rD, rA, rB); uint8 r; int ret = ppc_read_effective_byte((rA?gCPU.gpr[rA]:0)+gCPU.gpr[rB], &r); if (ret == PPC_MMU_OK) { gCPU.gpr[rD] = r; }}/* * lfd Load Floating-Point Double * .530 */void ppc_opc_lfd(){ if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU, 0, 0); return; } int rA, frD; uint32 imm; PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, frD, rA, imm); uint64 r; int ret = ppc_read_effective_dword((rA?gCPU.gpr[rA]:0)+imm, &r); if (ret == PPC_MMU_OK) { gCPU.fpr[frD] = r; } }/* * lfdu Load Floating-Point Double with Update * .531 */void ppc_opc_lfdu(){ if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU, 0, 0); return; } int rA, frD; uint32 imm; PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, frD, rA, imm); // FIXME: check rA!=0 uint64 r; int ret = ppc_read_effective_dword(gCPU.gpr[rA]+imm, &r); if (ret == PPC_MMU_OK) { gCPU.fpr[frD] = r; gCPU.gpr[rA] += imm; } }/* * lfdux Load Floating-Point Double with Update Indexed * .532 */void ppc_opc_lfdux(){ if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU, 0, 0); return; } int rA, frD, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, frD, rA, rB); // FIXME: check rA!=0 uint64 r; int ret = ppc_read_effective_dword(gCPU.gpr[rA]+gCPU.gpr[rB], &r); if (ret == PPC_MMU_OK) { gCPU.gpr[rA] += gCPU.gpr[rB]; gCPU.fpr[frD] = r; } }/* * lfdx Load Floating-Point Double Indexed * .533 */void ppc_opc_lfdx(){ if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU, 0, 0); return; } int rA, frD, rB; PPC_OPC_TEMPL_X(gCPU.current_opc, frD, rA, rB); uint64 r; int ret = ppc_read_effective_dword((rA?gCPU.gpr[rA]:0)+gCPU.gpr[rB], &r); if (ret == PPC_MMU_OK) { gCPU.fpr[frD] = r; } }/* * lfs Load Floating-Point Single * .534 */void ppc_opc_lfs(){ if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU, 0, 0); return; } int rA, frD; uint32 imm; PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, frD, rA, imm); uint32 r; int ret = ppc_read_effective_word((rA?gCPU.gpr[rA]:0)+imm, &r); if (ret == PPC_MMU_OK) { ppc_single s; ppc_double d; ppc_fpu_unpack_single(&s, r); ppc_fpu_single_to_double(&s, &d); ppc_fpu_pack_double(&d, &(gCPU.fpr[frD])); } }/* * lfsu Load Floating-Point Single with Update * .535 */void ppc_opc_lfsu(){ if ((gCPU.msr & MSR_FP) == 0) { ppc_exception(PPC_EXC_NO_FPU, 0, 0); return; } int rA, frD; uint32 imm; PPC_OPC_TEMPL_D_SImm(gCPU.current_opc, frD, rA, imm); // FIXME: check rA!=0 uint32 r; int ret = ppc_read_effective_word(gCPU.gpr[rA]+imm, &r); if (ret == PPC_MMU_OK) { ppc_single s; ppc_double d; ppc_fpu_unpack_single(&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -