/[gxemul]/trunk/src/cpus/memory_ppc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpus/memory_ppc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 20 by dpavlin, Mon Oct 8 16:19:23 2007 UTC revision 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory_ppc.c,v 1.20 2005/11/22 21:56:18 debug Exp $   *  $Id: memory_ppc.c,v 1.24 2006/06/24 21:47:23 debug Exp $
29   *   *
30   *  Included from cpu_ppc.c.   *  Included from cpu_ppc.c.
31   */   */
# Line 41  Line 41 
41   *  BAT translation. Returns -1 if there was no BAT hit, >= 0 for a hit.   *  BAT translation. Returns -1 if there was no BAT hit, >= 0 for a hit.
42   *  (0 for access denied, 1 for read-only, and 2 for read-write access allowed.)   *  (0 for access denied, 1 for read-only, and 2 for read-write access allowed.)
43   */   */
44  int ppc_bat(struct cpu *cpu, uint64_t vaddr, uint64_t *return_addr, int flags,  int ppc_bat(struct cpu *cpu, uint64_t vaddr, uint64_t *return_paddr, int flags,
45          int user)          int user)
46  {  {
47          int i, pp, regnr;          int i, istart = 0, iend = 8, pp;
48    
49            if (flags & FLAG_INSTR)
50                    iend = 4;
51            else
52                    istart = 4;
53    
54          if (cpu->cd.ppc.bits != 32) {          if (cpu->cd.ppc.bits != 32) {
55                  fatal("TODO: ppc_bat() for non-32-bit\n");                  fatal("TODO: ppc_bat() for non-32-bit\n");
# Line 55  int ppc_bat(struct cpu *cpu, uint64_t va Line 60  int ppc_bat(struct cpu *cpu, uint64_t va
60                  exit(1);                  exit(1);
61          }          }
62    
63          /*  4 instruction BATs, 4 data BATs...  */          /*  Scan either the 4 instruction BATs or the 4 data BATs:  */
64          for (i=0; i<8; i++) {          for (i=istart; i<iend; i++) {
65                  regnr = SPR_IBAT0U + i * 2;                  int regnr = SPR_IBAT0U + i * 2;
66                  uint32_t upper = cpu->cd.ppc.spr[regnr];                  uint32_t upper = cpu->cd.ppc.spr[regnr];
67                  uint32_t lower = cpu->cd.ppc.spr[regnr + 1];                  uint32_t lower = cpu->cd.ppc.spr[regnr + 1];
68                  uint32_t phys = lower & BAT_RPN, ebs = upper & BAT_EPI;                  uint32_t phys = lower & BAT_RPN, ebs = upper & BAT_EPI;
69                  uint32_t mask = ((upper & BAT_BL) << 15) | 0x1ffff;                  uint32_t mask = ((upper & BAT_BL) << 15) | 0x1ffff;
70    
                 /*  Instruction BAT, but not instruction lookup? Then skip.  */  
                 if (i < 4 && !(flags & FLAG_INSTR))  
                         continue;  
                 if (i >= 4 && (flags & FLAG_INSTR))  
                         continue;  
   
71                  /*  Not valid in either supervisor or user mode?  */                  /*  Not valid in either supervisor or user mode?  */
72                  if (user && !(upper & BAT_Vu))                  if (user && !(upper & BAT_Vu))
73                          continue;                          continue;
# Line 79  int ppc_bat(struct cpu *cpu, uint64_t va Line 78  int ppc_bat(struct cpu *cpu, uint64_t va
78                  if ((vaddr & ~mask) != (ebs & ~mask))                  if ((vaddr & ~mask) != (ebs & ~mask))
79                          continue;                          continue;
80    
81                  *return_addr = (vaddr & mask) | (phys & ~mask);                  *return_paddr = (vaddr & mask) | (phys & ~mask);
82    
83                  pp = lower & BAT_PP;                  pp = lower & BAT_PP;
84                  switch (pp) {                  switch (pp) {
# Line 108  int ppc_bat(struct cpu *cpu, uint64_t va Line 107  int ppc_bat(struct cpu *cpu, uint64_t va
107  static int get_pte_low(struct cpu *cpu, uint64_t pteg_select,  static int get_pte_low(struct cpu *cpu, uint64_t pteg_select,
108          uint32_t *lowp, uint32_t cmp)          uint32_t *lowp, uint32_t cmp)
109  {  {
110            unsigned char *d = memory_paddr_to_hostaddr(cpu->mem, pteg_select, 1)
111                + (pteg_select & ((1 << BITS_PER_MEMBLOCK) - 1));
112          int i;          int i;
         uint32_t upper;  
         unsigned char d[8];  
113    
114          for (i=0; i<8; i++) {          for (i=0; i<8; i++) {
115                  cpu->memory_rw(cpu, cpu->mem, pteg_select + i*8,                  uint32_t *ep = (uint32_t *) (d + (i << 3)), upper;
116                      &d[0], 8, MEM_READ, PHYSICAL | NO_EXCEPTIONS);                  upper = *ep;
117                  upper = (d[0]<<24)+(d[1]<<16)+(d[2]<<8)+d[3];                  upper = BE32_TO_HOST(upper);
118    
119                  /*  Valid PTE, and correct api and vsid?  */                  /*  Valid PTE, and correct api and vsid?  */
120                  if (upper == cmp) {                  if (upper == cmp) {
121                          *lowp = ((d[4]<<24)+(d[5]<<16)+(d[6]<<8)+d[7]);                          uint32_t lo = ep[1];
122                            lo = BE32_TO_HOST(lo);
123                            *lowp = lo;
124                          return 1;                          return 1;
125                  }                  }
126          }          }
# Line 138  static int get_pte_low(struct cpu *cpu, Line 139  static int get_pte_low(struct cpu *cpu,
139   *  a permission violation. *resp is set to 0 for no access, 1 for read-only   *  a permission violation. *resp is set to 0 for no access, 1 for read-only
140   *  access, or 2 for read/write access.   *  access, or 2 for read/write access.
141   */   */
142  static int ppc_vtp32(struct cpu *cpu, uint32_t vaddr, uint64_t *return_addr,  static int ppc_vtp32(struct cpu *cpu, uint32_t vaddr, uint64_t *return_paddr,
143          int *resp, uint64_t msr, int writeflag, int instr)          int *resp, uint64_t msr, int writeflag, int instr)
144  {  {
145          int srn = (vaddr >> 28) & 15, api = (vaddr >> 22) & PTE_API;          int srn = (vaddr >> 28) & 15, api = (vaddr >> 22) & PTE_API;
# Line 185  static int ppc_vtp32(struct cpu *cpu, ui Line 186  static int ppc_vtp32(struct cpu *cpu, ui
186                  return 1;                  return 1;
187    
188          access = lower_pte & PTE_PP;          access = lower_pte & PTE_PP;
189          *return_addr = (lower_pte & PTE_RPGN) | (vaddr & ~PTE_RPGN);          *return_paddr = (lower_pte & PTE_RPGN) | (vaddr & ~PTE_RPGN);
190    
191          key = (cpu->cd.ppc.sr[srn] & SR_PRKEY && msr & PPC_MSR_PR) ||          key = (cpu->cd.ppc.sr[srn] & SR_PRKEY && msr & PPC_MSR_PR) ||
192              (cpu->cd.ppc.sr[srn] & SR_SUKEY && !(msr & PPC_MSR_PR));              (cpu->cd.ppc.sr[srn] & SR_SUKEY && !(msr & PPC_MSR_PR));
# Line 211  static int ppc_vtp32(struct cpu *cpu, ui Line 212  static int ppc_vtp32(struct cpu *cpu, ui
212    
213    
214  /*  /*
215   *  ppc_translate_address():   *  ppc_translate_v2p():
216   *   *
217   *  Don't call this function is userland_emul is non-NULL, or cpu is NULL.   *  Don't call this function is userland_emul is non-NULL, or cpu is NULL.
218   *   *
# Line 220  static int ppc_vtp32(struct cpu *cpu, ui Line 221  static int ppc_vtp32(struct cpu *cpu, ui
221   *      1  Success, the page is readable only   *      1  Success, the page is readable only
222   *      2  Success, the page is read/write   *      2  Success, the page is read/write
223   */   */
224  int ppc_translate_address(struct cpu *cpu, uint64_t vaddr,  int ppc_translate_v2p(struct cpu *cpu, uint64_t vaddr,
225          uint64_t *return_addr, int flags)          uint64_t *return_paddr, int flags)
226  {  {
227          int instr = flags & FLAG_INSTR, res = 0, match, user;          int instr = flags & FLAG_INSTR, res = 0, match, user;
228          int writeflag = flags & FLAG_WRITEFLAG? 1 : 0;          int writeflag = flags & FLAG_WRITEFLAG? 1 : 0;
# Line 234  int ppc_translate_address(struct cpu *cp Line 235  int ppc_translate_address(struct cpu *cp
235                  vaddr &= 0xffffffff;                  vaddr &= 0xffffffff;
236    
237          if ((instr && !(msr & PPC_MSR_IR)) || (!instr && !(msr & PPC_MSR_DR))) {          if ((instr && !(msr & PPC_MSR_IR)) || (!instr && !(msr & PPC_MSR_DR))) {
238                  *return_addr = vaddr;                  *return_paddr = vaddr;
239                  return 2;                  return 2;
240          }          }
241    
242          if (cpu->cd.ppc.cpu_type.flags & PPC_601) {          if (cpu->cd.ppc.cpu_type.flags & PPC_601) {
243                  fatal("ppc_translate_address(): TODO: 601\n");                  fatal("ppc_translate_v2p(): TODO: 601\n");
244                  exit(1);                  exit(1);
245          }          }
246    
247          /*  Try the BATs first:  */          /*  Try the BATs first:  */
248          if (cpu->cd.ppc.bits == 32) {          if (cpu->cd.ppc.bits == 32) {
249                  res = ppc_bat(cpu, vaddr, return_addr, flags, user);                  res = ppc_bat(cpu, vaddr, return_paddr, flags, user);
250                  if (res > 0)                  if (res > 0)
251                          return res;                          return res;
252                  if (res == 0) {                  if (res == 0) {
# Line 256  int ppc_translate_address(struct cpu *cp Line 257  int ppc_translate_address(struct cpu *cp
257    
258          /*  Virtual to physical translation:  */          /*  Virtual to physical translation:  */
259          if (cpu->cd.ppc.bits == 32) {          if (cpu->cd.ppc.bits == 32) {
260                  match = ppc_vtp32(cpu, vaddr, return_addr, &res, msr,                  match = ppc_vtp32(cpu, vaddr, return_paddr, &res, msr,
261                      writeflag, instr);                      writeflag, instr);
262                  if (match && res > 0)                  if (match && res > 0)
263                          return res;                          return res;
# Line 278  int ppc_translate_address(struct cpu *cp Line 279  int ppc_translate_address(struct cpu *cp
279                  return 0;                  return 0;
280    
281          if (!quiet_mode)          if (!quiet_mode)
282                  fatal("[ memory_ppc: exception! vaddr=0x%llx pc=0x%llx "                  fatal("[ memory_ppc: exception! vaddr=0x%"PRIx64" pc=0x%"PRIx64
283                      "instr=%i user=%i wf=%i ]\n", (long long)vaddr,                      " instr=%i user=%i wf=%i ]\n", (uint64_t) vaddr,
284                      (long long)cpu->pc, instr, user, writeflag);                      (uint64_t) cpu->pc, instr, user, writeflag);
285    
286          if (cpu->cd.ppc.cpu_type.flags & PPC_603) {          if (cpu->cd.ppc.cpu_type.flags & PPC_603) {
287                  cpu->cd.ppc.spr[instr? SPR_IMISS : SPR_DMISS] = vaddr;                  cpu->cd.ppc.spr[instr? SPR_IMISS : SPR_DMISS] = vaddr;

Legend:
Removed from v.20  
changed lines
  Added in v.26

  ViewVC Help
Powered by ViewVC 1.1.26