📄 ppc_mmu.c
字号:
/* * PearPC * ppc_mmu.cc * * Copyright (C) 2003, 2004 Sebastian Biallas (sb@biallas.net) * Portions Copyright (C) 2004 Daniel Foesch (dfoesch@cs.nmsu.edu) * Portions Copyright (C) 2004 Apple Computer, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Pages marked: v.??? * From: IBM PowerPC MicroProcessor Family: Altivec(tm) Technology... * Programming Environments Manual */#include "debug.h"#include "tracers.h"#include "sysendian.h"#include "io.h"#include "ppc_cpu.h"#include "ppc_fpu.h"#include "ppc_vec.h"#include "ppc_mmu.h"#include "ppc_exc.h"#include "ppc_tools.h"#include "ppc_memory.h"#include "ppc_e500_exc.h"#define DEFAULT_CCSR_MEM 0xFF700000#define CCSR_MEM_SIZE 0x100000#define GET_CCSR_BASE(reg)(((reg >> 8)&0xFFF) << 20)e500_mmu_t e500_mmu;ppc_tlb_entry_t l1_i_vsp[4]; /* instruction, filled by TLB1 hit */ppc_tlb_entry_t l1_i_tlb4k[64]; /* instruction, filled by TLB0 hit */ppc_tlb_entry_t l1_d_vsp[4]; /* data, filled by TLB1 hit */ppc_tlb_entry_t l1_d_tlb4k[64]; /* data, filled by TLB0 hit */#define L2_TLB0_SIZE 256#define L2_TLB1_SIZE 16ppc_tlb_entry_t l2_tlb0_4k[L2_TLB0_SIZE]; /* unified, filled by tlbwe instruction */ppc_tlb_entry_t l2_tlb1_vsp[L2_TLB1_SIZE]; /* filled by tlbwe insructions *//*ea = effective addressif translation is an instruction address then as = MSR[IS];else // data address translation as = MSR[DS]for all TLB entries if !TLB[entry].v then next // compare next TLB entry if as != TLB[entry].ts then next // compare next TLB entry if TLB[entry].tid == 0 then goto pid_match for all PID registers if this PID register == TLB[entry].tid then goto pid_match endfor next // no PIDs matched pid_match://translation match mask = ~(1024 << (2 * TLB[entry].tsize)) - 01 if (ea & mask) != TLB[entry].epn then next // no address match real address = TLB[entry].rpn | (ea & ~mask) // real address computed end translation --success endfor end translation tlb miss*/int ppc_effective_to_physical(uint32 addr, int flags, uint32 *result){ int i,j; uint32 mask; ppc_tlb_entry_t *entry; int tlb1_index; int pid_match = 0; i = 0; /* walk over tlb0 and tlb1 to find the entry */ while(i++ < (L2_TLB0_SIZE + L2_TLB1_SIZE)){ if(i > (L2_TLB0_SIZE - 1)){ tlb1_index = i - L2_TLB0_SIZE; entry = &l2_tlb1_vsp[tlb1_index]; } else entry = &l2_tlb0_4k[i]; if(!entry->v) continue; /* FIXME, not check ts bit now */ if(entry->ts & 0x0) continue; if(entry->tid != 0){ for(j = 0; j < 3; j++){ if(e500_mmu.pid[j] == entry->tid) break; } if(e500_mmu.pid[j] != entry->tid) continue; } if(i > (L2_TLB0_SIZE - 1)){ int k,s = 1; for(k = 0; k < entry->size; k++) s = s * 4; mask = ~((1024 * (s - 1) - 0x1) + 1024); } else mask = ~(1024 * 4 - 0x1); if(entry->size != 0xb){ if((addr & mask) != ((entry->epn << 12) & mask)) continue; *result = (entry->rpn << 12) | (addr & ~mask); // get real address } else {/*if 4G size is mapped, we will not do address check */ //fprintf(stderr,"warning:4G address is used.\n"); if(addr < (entry->epn << 12)) continue; *result = (entry->rpn << 12) | (addr - (entry->epn << 12)); // get real address } return PPC_MMU_OK; } if(ppc_exception(DATA_TLB, 0, addr)) return PPC_MMU_EXC; return PPC_MMU_FATAL; }int e500_mmu_init(){ /* the initial tlb map of real hardware */ ppc_tlb_entry_t * entry = &l2_tlb1_vsp[0]; entry->v = 1; /* entry is valid */ entry->ts = 0; /* address space 0 */ entry->tid = 0; /* TID value for shared(global) page */ entry->epn = 0xFFFFF; /* Address of last 4k byte in address space*/ entry->rpn = 0xFFFFF; /* Address of last 4k byte in address space*/ entry->size = 0x1; /* 4k byte page size */ /* usxrw should be initialized to 010101 */ entry->usxrw |= 0x15; /* Full supervisor mode access allowed */ entry->usxrw &= 0x15; /* No user mode access allowed */ entry->wimge = 0x8; /* Caching-inhibited, non-coherent,big-endian*/ entry->x = 0; /* Reserved system attributes */ entry->u = 0; /* User attribute bits */ entry->iprot = 1; /* Page is protected from invalidation */ gCPU.ccsr.ccsr = 0xFF700; e500_mmu.tlbcfg[0] = 0x4110200; e500_mmu.tlbcfg[1] = 0x101bc010; gCPU.lb_ctrl.lcrr = 0x80000008; gCPU.i2c_reg.i2csr = 0x81; gCPU.i2c_reg.i2cdfsrr = 0x10; gCPU.pic_ram.ctpr0 = 0x0000000F; gCPU.pic_global.svr = 0xFFFF;}int FASTCALL ppc_read_effective_word(uint32 addr, uint32 *result){ uint32 p; int r; if (!(r = ppc_effective_to_physical(addr, PPC_MMU_READ, &p))) { //printf("DBG:ccsr=0x%x,CCSR_BASE=0x%x\n",gCPU.ccsr.ccsr,GET_CCSR_BASE(gCPU.ccsr.ccsr)); if((p >= GET_CCSR_BASE(gCPU.ccsr.ccsr)) && (p < (GET_CCSR_BASE(gCPU.ccsr.ccsr) + CCSR_MEM_SIZE))){ int offset = p - GET_CCSR_BASE(gCPU.ccsr.ccsr); //printf("DBG:in %s,read CCSR,offset=0x%x,pc=0x%x\n", __FUNCTION__, offset, gCPU.pc); if(offset >= 0x919C0 && offset <= 0x919E0){ switch(offset){ case 0x919C0: *result = gCPU.cpm_reg.cpcr; return r; default: fprintf(stderr,"in %s, error when read CCSR.offset=0x%x,pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); skyeye_exit(-1); } } if(offset >= 0x2000 && offset <= 0x2E58){ switch(offset){ case 0x2E44: *result = gCPU.ddr_ctrl.err_disable; return r; default: fprintf(stderr,"in %s, error when read CCSR.offset=0x%x,pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); skyeye_exit(-1); } } /** * PIC Register Address Map */ if(offset >= 0x50000 && offset <= 0x600B0){ if(offset >= 0x50000 && offset <= 0x50170){ int index = (offset - 0x50000) >> 4; if(index & 0x1) *result = gCPU.pic_ram.eidr[index >> 1]; else *result = gCPU.pic_ram.eivpr[index >> 1]; return r; } if(offset >= 0x50200 && offset <= 0x505F0){ int index = (offset - 0x50200) >> 4; if(index & 0x1) *result = gCPU.pic_ram.iidr[index >> 1]; else *result = gCPU.pic_ram.iivpr[index >> 1]; return r; } switch(offset){ case 0x60080: *result = gCPU.pic_ram.ctpr0; return r; case 0x600a0: *result = gCPU.pic_percpu.iack0; return r; default: fprintf(stderr,"in %s, error when write pic ram,offset=0x%x,pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); break; } } /** * Interrupt Controller */ if(offset >= 0x90C00 && offset <= 0x90C7F){ switch(offset){ case 0x90C08: *result = gCPU.int_ctrl.sipnr_h; return r; case 0x90C0C: *result = gCPU.int_ctrl.sipnr_l; return r; case 0x90C14: *result = gCPU.int_ctrl.scprr_h; return r; case 0x90C18: *result = gCPU.int_ctrl.scprr_l; return r; case 0x90C1C: *result = gCPU.int_ctrl.simr_h; return r; case 0x90C20: *result = gCPU.int_ctrl.simr_l; return r; default: fprintf(stderr,"in %s, error when read interrupt controller,offset=0x%x,pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); return r; } } if(offset >= 0x91A00 && offset <= 0x91A3F){ int i = (0x20 & offset) >> 5; offset = 0x1f & offset; switch(offset){ case 0x0: *result = gCPU.cpm_reg.scc[i].gsmrl; return r; default: fprintf(stderr,"in %s, error when read CCSR.offset=0x%x, \ pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); skyeye_exit(-1); } } /* CPM MUX I/O */ if(offset >= 0x91B00 && offset <= 0x91B1F){ switch(offset){ case 0x91B08: *result = gCPU.cpm_reg.mux.cmxscr; return r; case 0x91B04: *result = gCPU.cpm_reg.mux.cmxfcr; return r; default: fprintf(stderr,"in %s, error when read CCSR.offset=0x%x, \ pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); skyeye_exit(-1); } } /* PIC Global register */ if(offset >= 0x40000 && offset <= 0x4FFF0){ switch(offset){ case 0x41000: *result = gCPU.pic_global.frr= 0x370002; /* according to 8560 manual */ return r; case 0x400a0: *result = gCPU.pic_global.iack; return r; case 0x410f0: *result = gCPU.pic_global.tfrr; return r; case 0x41020: /* source attribute register for DMA0 */ *result = gCPU.pic_global.gcr; return r; case 0x410e0: *result = gCPU.pic_global.svr; return r; case 0x41120: *result = gCPU.pic_global.gtvpr0; return r; case 0x41160: *result = gCPU.pic_global.gtvpr1; return r; case 0x41170: *result = gCPU.pic_global.gtdr1; return r; case 0x411a0: *result = gCPU.pic_global.gtvpr2; return r; case 0x411B0: *result = gCPU.pic_global.gtdr2; returnr; case 0x411E0: *result = gCPU.pic_global.gtvpr3; returnr; default: fprintf(stderr,"in %s, error when read global.offset=0x%x, \ pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); return r; //skyeye_exit(-1); } } /* DMA */ if(offset >= 0x21100 && offset <= 0x21300){ switch(offset){ case 0x21110: /* source attribute register for DMA0 */ *result = gCPU.dma.satr0; return r; case 0x21118: *result = gCPU.dma.satr0; return r; default: fprintf(stderr,"in %s, error when read dma.offset=0x%x, \ pc=0x%x\n",__FUNCTION__, offset, gCPU.pc); return r; //skyeye_exit(-1); } } /* Input/Output port */ if(offset >= 0x90D00 && offset <= 0x90D70){ switch(offset){ case 0x90D00: *result = gCPU.cpm_reg.ioport.pdira; return r; case 0x90D04: *result = gCPU.cpm_reg.ioport.ppara; return r; case 0x90D08: *result = gCPU.cpm_reg.ioport.psora; return r; case 0x90D0C: *result = gCPU.cpm_reg.ioport.podra ; return r; case 0x90D10: *result = gCPU.cpm_reg.ioport.pdata; return r; case 0x90D20: *result = gCPU.cpm_reg.ioport.pdirb; return r; case 0x90D24:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -